在 K8S 上运行 Spark 的最佳实践和陷阱
Posted zhisheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在 K8S 上运行 Spark 的最佳实践和陷阱相关的知识,希望对你有一定的参考价值。
阿里云高级技术专家范振为大家带来在kubernetes上运行apache spark的介绍。内容包括Data mechanics平台介绍,Spark on k8s,以及EMR团队云原生的思考和实践。以下由Spark+AI Summit中文精华版峰会的精彩内容整理。
一、Data Mechanic平台介绍
这块是data mechanics平台的一个介绍。首先,它是一个serverless的平台,即一个全托管的平台,用户不用去关心自己的机器。所有的应用的启动和扩容都是在这种秒级的。然后,对于这种本地的开发转到这种线上的部署,它是一种无缝的转换。然后,它还能提供这种配置自动的spark的一些参数调优,整个这条pipeline都会做得非常的快,已经非常地稳定。
然后他们相当于是把整个的平台部署在用户的账号里边的K8S集群。这样的话,对整个的安全是一个非常大的保证。然后数据权限,包括运行权限,都在统一的账号里面。
二、Spark on k8s
(一)核心概念
首先,k8s和spark的结合是出现在spark 2.3版本以后的事情,在此之前有几种方式。第一种就是Standalone,大家使用的并不是非常的多。第二种是Apache mesos,在国外用的比较多,但是市场规模也在逐渐缩小。第三种是Yarn,我们现在绝大多数的企业都是跑在Yarn的集群里面了。第四种是Kubernetes,现在大家也逐渐的把spark跑在k8s上面。
Spark on k8s的架构如下图所示:
提交应用的方式有两种。一种是Spark submit,另一种是Spark-on-k8s operator。它们各自的特点如下图所示:
然后我们再对比一下Yarn和k8s的依赖的管理。这块是区分点比较大的一个地方。Yarn提供一个全局的spark版本,包括python的版本,全局的包的依赖,缺少环境隔离。而k8s是完全的环境隔离,每一个应用可以跑在完全不同的环境、版本等。Yarn的包管理方案是上传依赖包到HDFS。K8s的包管理方案是自己管理镜像仓库,将依赖包打入image中,支持包依赖管理,将包上传到 OSS/HDFS,区分不同级别任务,混合使用以上两种模式。
(二)配置和性能
然后我们说一下配置spark executors的小坑。举个例子,假设k8s node为16G-RAM,4-core的ECS,下面的配置会一个executor都申请不到!如下图所示。
原因是什么,就是说Spark pod只能按照node资源的一定比例来申请资源,而spark.executor.cores=4占用了node cores全部资源。如下图所示,假设我们计算得到的可用资源是85%,那么我们应该这样配置资源,spark.kubernetes.executor.request.cores=3400m。
然后这块是一个比较重要的特点,就是动态资源。动态资源的完整支持目前做不到。比如说,Kill一个pod,shuffle file会丢失, 会带来重算。
这一块是Cluster autoscaling和dynamic allocation。上文中,我们看到PPT的某一页,它有一个实线框,还有一个虚线框。实际上说的是,k8s cluster autoscaler:当pod处于pending状态不能被分配资源时,扩展node节点。然后, Autoscaling和动态资源配合起来工作,就是说,当有资源时,executor会在10s内注册到driver。而当没有资源时,先通过autoscaling添加ECS资源,再申请executors。大约在1min~2min内完成executor申请过程。
这个实际上也是更好的保证了我们运行时的弹性,还有一个我自己的理解,比较有意思的一个玩法,就是说更加省成本。Spot instance会使得成本降低75%,它是可以被抢占的一种资源方式,跑一些SLA不高、价格敏感的应用。它在架构上整体设计,使得成本最低。如果executor被kill,会recover。如果driver被kill,就会很危险。配置node selector和affinities来控制Driver调度在非抢占的node,executor调度在spot instance。
然后,下一个就是对象存储的IO问题。Sparkonk8s通常都是针对对象存储,rename,list,commit task/job会非常费时。如果没有S3A committers,Jindofs JobCommitter,应该设置 spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version=2。
还有Shuffle性能。I/O性能是shuffle bound workload的关键点,spark2.x版本用docker file system。而Docker file system是非常慢的,需要用volume来代替。
(三)未来工作
未来的工作,我认为比较重要的就是shuffle的提升,中间数据的存储与计算分离。这块是一个比较大的工作。另外,还有Node decommission,支持上传python依赖文件等等。
我们选择k8s的优缺点,如下图所示:
部署spark on k8s的具体步骤,如下图所示:
三、EMR团队云原生的思考和实践
(一)整体架构
这块是我们的一个整体架构,如下图所示:
(二)动态资源&shuffle提升
Shuffle service解决核心问题:
▪ 解决动态资源问题
▪ 解决挂载云盘贵,事前不确定大小的痛点
▪ 解决NAS作为中心存储的扩展性以及性能问题
▪ 避免task由于fetch失败重新计算的问题,提升中大作业的稳定性
▪ 通过Tiered存储提升作业性能
(三)EMR Spark云原生规划
EMR产品体系,创建EMR集群类型为ON ACK:
▪ JindoSpark镜像
▪ JindoFSService/JindoFSSDK提升访问OSS数据湖能力
▪ JindoJobCommitter增强提交OSS作业能力
▪ JindoShuffleService&动态资源能力增强
▪ ACK集群打通EMR原有集群,可以互访老集群表和HDFS数据
▪ Operator增强,Dependency管理,提供一站式管控命令
▪ 云原生日志、监控一站式平台
以上是关于在 K8S 上运行 Spark 的最佳实践和陷阱的主要内容,如果未能解决你的问题,请参考以下文章