随着云原生技术的倒退和成熟,大数据基础设施踊跃拥抱云原生是业内倒退的一大趋势。网易传媒在 2021 年胜利将 SparkSQL 部署到了 K8s 集群,并实现与局部在线业务的混合部署,到目前曾经稳固运行了一年多。期间传媒联结杭研 Spark 内核团队和云计算团队对呈现的问题进行了继续的改良,本文将对这些落地优化实际进行初步的梳理总结,心愿能给大家带来一些有用的参考。目前,传媒大数据中心的大部分 SparkSQL 工作都曾经迁徙到了 K8s 集群,但仍有一部分算力保留在 Yarn 集群,作业调度次要依靠于无数平台,SparkSQL 工作的提交形式以 Kyuubi [1] 为主,Spark 版本次要基于 3.1.2 进行演进,下图简略形容了咱们以后 Spark 离线计算的根本架构:
以下将别离从 on K8s 落地收益、工作迁徙计划、集群和工作运行监控、工作资源占用治理、任务调度优化等几个方面逐步开展介绍。
SparkSQL 迁徙到 K8s 的收益
传媒大数据将 SparkSQL 迁徙到 K8s 次要基于如下考量:
- 能够将计算和存储进行解耦,即存算拆散。在存储和计算耦合的架构中,因为各业务场景对存储和计算的需要不均衡,绑定两者同步进行伸缩,会呈现其中一种资源节约的状况;将计算和存储解耦后则能够依据须要别离进行弹性伸缩,零碎在负载平衡调度方面能够更加灵便。
- 对立算力资源池实现兼顾调度,SparkSQL 能够作为离线业务与其它在线业务进行混混部达到峰谷互补的成果,有助于晋升服务器资源利用率和治理运维效率,节约总成本。
工作由 Yarn 迁徙到 K8S 的计划
迁徙方面,咱们已提前将大部分工作由 HiveSQL 迁徙到了 SparkSQL 引擎[2],而 SparkSQL 从 Yarn 集群上切换到 K8S 集群上对用户来说基本上是无感知的。不过,迁徙初期为了保障未知危险尽量可控,咱们采取了如下措施:
- 先迁徙非核心的上游工作来踩坑,逐渐扩充规模再推动到上游工作。
- 先迁徙自定义脚本类型工作,得益于对 Kyuubi 的应用,只须要大量代码就能够不便地将失败任务调度至 Yarn 集群进行重试。
这样咱们在迁徙初期尽量减少了对须要保障的外围 SLA 工作链路的影响。
工作在 K8s 上的运行监控
工作迁徙到 K8s 之后,在遇到问题进行排查时,用户都迫切希望能尽快看到作业的运行状况从而疾速进行问题诊断和作业优化。传统的 SparkSQL on Yarn 场景,咱们有 Yarn 的 web 页面作为入口来查看队列资源占用和工作运行状态,但在 K8s 环境下并没有一个相似的对立入口。而 Spark History Server 上的工作统计列表因为须要期待工作运行日志上传至 HDFS 后能力解析展现,绝对要滞后许多,这导致了在迁徙初期咱们对集群和工作的运行状况根本处于两眼一抹黑的状态。为了解决这个问题,咱们首先设置所有工作均应用 client 模式提交 SparkSQL,让 Spark Driver 在调度机本地运行,这样一来,便只须要在几台任务调度机上部署监控程序,通过 Spark Driver 本地的 Spark http 接口获取当前任务运行信息即可。这种形式尽管不是很合乎所有组件都跑在容器中的云原生理念,然而人力老本绝对较低,在后期简化了咱们的监控告警工作,未来待计划进一步欠缺后再切换到 cluster 运行模式。另外,随着优化工作的推动,咱们跟杭研 Spark 内核组配合搭建了 Hygieia 工作运行指标监控服务,跟部门运维和杭研云计算团队减少了调度资源相干的监控,对监控需要进行了进一步欠缺。以下简略列举了日常看得比拟多的几个监控报表:
- 工作实时运行列表:实时监控集群上以后的工作列表,能够间接跳转相应的 Spark UI 来查看实时运行状况。
- 工作资源分配监控:监控 CPU、内存等资源分配量的变动,能够按工作或用户维度进行重叠,次要用于监控集群的整体运行状况,比方是否有异样工作或用户抢占大量资源、或者资源分配速度不失常等等。
- 工作运行状态统计:监控集群上运行中和 pending 的工作数或 pod 数,能够直观地反映集群资源的竞争水平和 K8s 的调度负载。
- 集群运行指标监控:次要通过哨兵提供的监控页面查看,具体各业务的资源容量和理论使用量状况次要通过云计算团队提供的 Grafana 监控查看。
局部监控报表理论应用中,通过上述监控,根本能较全面地查看集群和 SparkSQL 工作的运行状态,有助于疾速定位问题。
工作资源占用治理
工作在 K8S 上安稳运行之后,大家的关注点逐步转移到性能问题上来,尤其是集群的资源使用率和基线工作的产出工夫等,这方面咱们针对 K8S 集群的特点陆续落地了一系列优化策略,以下别离从 CPU、内存、磁盘等资源角度进行介绍。
1.CPU
为尽可能地进步集群的承载容量,最大化能并发运行的 executor pod 数量,咱们依据集群和工作的统计状况对 CPU 做了肯定比例的超售。通过比照 CPU 申请量和理论使用量的整体比值,最终对立将工作的 spark.kubernetes.executor.request.cores 参数配置为 1,而 spark.kubernetes.executor.limit.cores 不做限度,同时将 spark.executor.cores 配置为 4,即 excutor 按 1 核的申请量跑 4 并发的 task,以此最大限度地压迫集群的 CPU 算力。CPU 超售会减轻集群负载不平衡的问题,造成局部节点负载过高,但得益于云计算团队开发的 Zeus 混部调度器,能够动静更新资源隔离配置,防止对在线业务产生过多烦扰[3]
2. 内存
因为之前 Yarn 集群的内存资源较短缺,业务上对各工作内存申请的审批也绝对宽松,导致工作内存申请方面普遍存在“虚胖”的问题,从而导致在迁徙到 K8s 集群后内存成为瓶颈,集群并发上不去呈现算力节约状况。与 CPU 相比,内存作为一种不可压缩资源绝对紧缺,且不同工作所需的内存大小不一,不能对工作内存申请执行一刀切的策略。如何平安且高效地升高 SparkSQL 工作的内存调配,是一个要害的问题。为了给每个工作评估出一个绝对正当的内存申请值,咱们首先基于前文提到的 Spark 监控插件 Hygieia,实现了对 SparkSQL 工作运行指标的实时采集。在积攒了一段时间的样本数据后,咱们开始依据每个工作的历史统计数据对内存申请进行例行化调整,调整策略次要如下:
- 取工作近一段时间所有实例 executor 堆内和堆外内存使用量之和的最大值,按 128MB 为单位向上取整作为内存申请倡议值进行调整。另外,为了平安思考设置了调整上限。
- 对调整后的工作进行一段时间的衰弱监测,包含工作运行时长和 GC 吞吐量等指标。当工作运行时长呈现缩短或者 GC 吞吐量下降时,则须要回调内存或人工染指排查。一个简化版的模型是,当工作内存被削减后一周内的 GC 吞吐量中位位数若低于 95%,每低 1% 则减少 512MB 内存,直至复原到调整前。
具体执行上,咱们通过猛犸调度平台的凋谢 API 做到了每天例行自动化调整。另外,为了防止工作被频繁调整无奈评估成果,还针对每个工作设置了调整冷却期等。截止到以后,调整策略对业务而言基本上做到了通明无感知和 0 事变。下图展现了自调整策略执行以来内存调配量 95 分位与 CPU 理论使用量 95 分位比值的变动曲线,以后比值已降至靠近 4:1 的正当程度,集群 0-7 点的 CPU 利用率放弃在 80+%,且 GC 吞吐量放弃在 95+%:
- 磁盘
尽管“内存计算”是 Spark 的次要个性之一,但在理论场景中往往因为工作 shuffle 数据量大,导致对磁盘容量和 IO 速度要求也较高。目前传媒应用的还是 ESS 计划,尚未切换到 RSS 计划 [4],且传媒 K8s 集群挂载的数据盘容量无限,如果一些异样工作产生歪斜,极易引发个别节点磁盘被写满的危险,导致工作失败和重试。为了解决这些问题,次要措施如下:
- 数据盘对立应用 SSD:迁徙之初,K8s 集群应用了局部云盘,而 Spark 离线计算工作高峰期突发数据流量十分大,导致云盘读写呈现显著提早,集群 CPU 的 io_wait 工夫占比很高,工作大量工夫消耗在等 IO 上。全副改为应用 SSD 后,运行速度失去显著晋升。
- 应用 zstd 压缩 shuffle 数据:zstd 压缩算法性能优良,在压缩率和耗时上都有卓越的体现。相较于 shuffle 默认的压缩算法 lz4,zstd level1 压缩级别在工作性能体现上根本持平,但压缩率晋升了近一倍。经实际,切换到 zstd 压缩可显著升高 shuffle 写盘的数据量,无效缓解磁盘容量上和 IO 上的压力,从而晋升容错下限。下图展现了切换 zstd 压缩算法前后磁盘空间使用率的变动状况:
- 大 shuffle 任务调度至 Yarn:因为传媒以后还保留有一部分 Yarn 算力,将 shuffle 量较大的任务调度至 Yarn 能够无效加重 K8S shuffle 服务的压力,做到物尽其用。
任务调度优化传媒 SparkSQL 工作次要以分钟级为主,且基于 3.1.2 版本开启了动静资源分配机制,运行时会依据需要动静申请和开释 executor,理论应用中对集群的调度吞吐能力有肯定的性能要求,这自身对以调度长时服务起家的 K8s 提出了不小的挑战。咱们遇到的问题和应答策略次要如下:
- 调度性能瓶颈问题优化
上文提到 SparkSQL 工作是作为离线业务与其它在线业务进行混部的,且初期共用一个线性调度器,而因为离线工作的优先级都要低于在线业务,导致呈现了高峰期时集群有资源然而迟迟调度不下来的景象。通过与杭研 Spark 内核团队配合,咱们对每个工作所能并发申请的 pod 数进行了限度,肯定水平上缩小了 excutor pod 的频繁申请和开释。通过与杭研云计算团队配合,咱们为 SparkSQL 独立出了一个专用的调度器,将 SparkSQL 的调度与其它业务的调度负载隔离开,从而打消了 SparkSQL 在调度性能上的瓶颈。
- 针对调度歪斜开启反亲和调度
如果某个工作的 excutor pod 集中在少数几个节点上,而这个工作的 shuffle 或计算又比拟重,比拟容易导致节点磁盘写满或 CPU 负载高,理论场景中这种状况并不少见。为了应答这个问题,咱们在 executor pod 的调度上开启了反亲和个性,即同一个工作的 pod 尽可能扩散到不同的节点上,也获得了比拟不错的成果。 - 开启优先级调度保障外围工作链路
随着迁徙到 K8S 集群上工作规模的扩充,资源竞争逐步加剧,高峰期频繁呈现工作长时间 pending 的状况,尤其是在呈现重大新闻事件时须要把集群资源歪斜给线上要害业务时。这个时候给不同 SLA 级别的工作设置不同资源分配优先级的需要分外强烈起来。通过与杭研 Spark 内核团队配合,咱们为工作指定了不同的 PriorityClass 来对调度优先级进行辨别。下图别离是敞开和开启优先级调度时的 SLA 工作运行状况,其中每个色彩代表一个工作所占用的 pod 数。能够看到,开启优先级调度时,SLA 工作在高峰期时的资源分配失去了优先保障,pod 数的峰值进步 20+%,工作“身材”显著“瘦”下来,拖尾景象失去缓解。
敞开优先级调度时
开启优先级调度时优先级调度的落地,为重大新闻事件时的高优数据保障工作提供了一个托底的机制。
总结与瞻望
传媒 SparkSQL on K8S 稳固运行一年来,随着优化计划的落地,集群的规模相较于初期曾经缩容了 30+%,但基线产出仍放弃了稳固,甚至有所晋升。这与部门内和杭研相干团队的无力反对是分不开的,在此一并表示感谢!后续工作将围绕以下几个方面开展:
- 持续扩充 SparkSQL on K8s 的规模
后续传媒将持续扩充 SparkSQL on K8s 的规模,对立算力资源池,扩充规模效应。以后大数据技术核心正在帮助举荐业务发展迁徙验证,也曾经获得了不错的测试成果。 - 摸索与 Flink on K8s 混部
以后传媒也正在落地 Flink on K8s 的云原生计划,并摸索与 SparkSQL on K8s 做混部。相较于后盾线上服务,Flink 实时计算的流量特色更加显著,负载稳定更能与 SparkSQL on K8s 互补,且同属于大数据业务便于兼顾调度资源。 - 摸索存储的云原生计划
存算拆散后,目前传媒大数据的存储资源仍全副集中在 HDFS 集群上,因为与 Yarn 计算资源的绑定,而导致不足相应的弹性伸缩能力。以后对象存储和基于对象存储的 Hadoop 兼容文件系统倒退迅速,传媒也正在开展对该模式的摸索,以期实现存储资源池的对立。传媒以后 SparkSQL on K8s 应用的 ESS shuffle 计划依赖于计算节点上的磁盘来存储长期数据,还不算残缺云原生意义上的存算拆散,后续将开始调研并落地 RSS 相干的计划。
援用:
Apache Kyuubi (Incubating)
Hive SQL 迁徙 Spark SQL 在网易传媒的实际
降本增效黑科技 | 基于 Kubernetes 的在 / 离线业务混部
Apache Uniffle (Incubating)
作者:鲁成祥 易顺