Spark on Kubernetes PodTemplate 的配置
1 Overview
本文主要讲 Apache Spark 在 on Kubernetes 的 PodTemplate 的问题,以及也会讲到 Spark Operator 里关于 PodTemplate 的问题,当然也会讲到 Apache Spark 2.2 on Kubernetes 那个 Fork 的版本,感兴趣的同学可以往下看看。
之前讲过 Apache Spark on Kubernetes 在配置 Pod 的时候的一些限制,比如针对 Pod 的调度,想加个 NodeSelector 或者 Tolerations。这在集群公用,或者有各种类型任务的集群里,是经常会遇到的情况,而在 Spark 2.x 里是很难做到的。
目前最新 Release 的版本 2.4.5 还没有支持通过 PodTemplate 来自定义 Pod 的配置,而社区的计划是在 Spark 3.0 的时候将这一 feature 完成,他支持的方式其实也比较简单,就是可以有一个 PodTemplate 的一个文件,去描述 Driver/Executor 的 metadata/spec 字段,这样当然就可以在模板文件里加入跟调度需要的一些字段了,
关于 PodTemplate 可以带来什么呢?比如说其实 Apache Spark 2.2 on Kubernetes 一开始是支持 initContainer 的,当时可以通过 spark.kubernetes.initcontainer.docker.image
来配置 Pod 的 initContainer 但是随着版本的演进,关于 initContainer 的代码已经去掉了,可以想象,如果只通过几个 SparkConf 来配置 initContainer 的话,这样限制实现太多了,SparkConf 的表达能力有限,如果都通过 spark.kubernetes.driver.label.*
这样的 SparkConf 来配置的话,既不灵活,也让 SparkConf 的配置数量急剧膨胀。
那么现在如果用户想通过 initContainer 做一些事情那可以怎么办?在 Spark 2.x 的版本里,应该是没有办法的,除非通过一些迂回的办法来实现原先你想通过 intContainer 达到的目标,比如说将一个文件提交下载到 Volume 并进行挂载这类操作,又或者直接去改下源码。
具体可以参考在 SPARK-24434 Support user-specified driver and executor pod templates 的相关讨论。不论 initContainer 的逻辑怎么样了,至少现在用户可以通过 PodTemplate 来自定义 Pod,当然包括定义需要的 initContainer,以及跟调度相关的一些字段。
2 PodTemplate
实际上,如果是在 Spark Operator 里,本身就支持 Pod Template 的配置 SparkPodSpec,也就是说,像 NodeSelector, Tolerations 之类的,可以在创建 CRD 对象的时候在 YAML 上添加上,比如下面的例子。
apiVersion: sparkoperator.k8s.io/v1beta2 kind: SparkApplication metadata: name: spark-pi namespace: default spec: type: Scala mode: cluster image: gcr.io/spark/spark:v2.4.5 mainClass: org.apache.spark.examples.SparkPi mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.11-2.4.5.jar nodeSelector: key: value
所以之前的文章也有说过 Spark Operator 的配置上,会更加灵活。
而在 Apache Spark 3.0 中,PodTemplate 是需要在 spark-submit
阶段将模板文件加到 spark.kubernetes.driver.podTemplateFile
或者 spark.kubernetes.executor.podTemplateFile
里的。
大家都知道 Spark 在下载依赖文件的时候,可以通过 HTTP/HDFS/S3 等协议来下载需要的文件。但是读取 PodTemplate 的 API,目前只支持本地文件系统(当然要改成支持 http 也不是很复杂),SparkConf 的配置可能如下。
# template 在本地 spark.kubernetes.driver.podTemplateFile=/opt/spark/template.yaml spark.kubernetes.executor.podTemplateFile=/opt/spark/template.yaml
关于 Apache Spark 3.0 是如何加载这些 PodTemplate 的文件,我们可以看看源码。在将 PodTemplate 文件加载到系统里的关键方法是是 KubernetesUtils.loadPodFromTemplate()
。
def loadPodFromTemplate( kubernetesClient: KubernetesClient, templateFile: File, containerName: Option[String]): SparkPod = { try { // 主要的还是利用 K8S 的客户端去 load 模板文件 // load 模板文件目前只能支持本地文件系统,因为底层调用的是 File 接口 val pod = kubernetesClient.pods().load(templateFile).get() // 这里需要注意会从模板里把指定 Container 捞出来 // 目的主要是捞出来 Driver 和 Executor 容器 // 否则就是以第一个容器作为 Driver/Executor 的容器 selectSparkContainer(pod, containerName) } catch { case e: Exception => logError( s"Encountered exception while attempting to load initial pod spec from file", e) throw new SparkException("Could not load pod from template file.", e) } }
通过上述方法就可以利用 PodTemplate 来做一些 Pod 的定义了,避免了大量极其繁琐的 SparkConf 的配置。如果想在 Apache Spark 3.0 之前的版本去实现 NodeSelector/Toleration 这些操作,直接通过 SparkConf 是不行的。后面 Driver/Executor 的 Pod 构建就分别交给 KubernetesDriverBuilder
和 KubernetesExecutorBuilder
去做了。而在执行 spark-submit
的环境中,需要去读取 PodTemplate 文件,然后通过 ConfigMap 来挂载到 Driver/Executor Pod。当然了,我觉得这样还是不够灵活,因为 Executor 的 PodTemplate 也可以在 Spark 镜像里,不需要一定要在 spark-submit
的环境里,目前的做法,如果是使用本地文件的话,就必须在 spark-submit
的本地环境了,而我觉得没必要,不过我们还是可以改成通过 http 等方式,让本地可以读取到这些 PodTemplate 文件的,只是你还需要一个文件服务器去放这些 PodTemplate 的文件。
因为通过 PodTemplate 来引导定义的操作相对来说是比较前置的,所以有些属性,可能会被后面针对 Pod 的其他配置给 overwrite,在 Spark 的最新文档的 running-on-kubernetes,可以找到那些属性可能会被后置配置覆盖掉。
下面是关于 Spark Driver Pod 是怎么通过各种 Step 按顺序最后给构建出来的示意图。
val features = Seq( new BasicDriverFeatureStep(conf), new DriverKubernetesCredentialsFeatureStep(conf), new DriverServiceFeatureStep(conf), new MountSecretsFeatureStep(conf), new EnvSecretsFeatureStep(conf), new MountVolumesFeatureStep(conf), new DriverCommandFeatureStep(conf), new HadoopConfDriverFeatureStep(conf), new KerberosConfDriverFeatureStep(conf), new PodTemplateConfigMapStep(conf), new LocalDirsFeatureStep(conf)) val spec = KubernetesDriverSpec( initialPod, driverKubernetesResources = Seq.empty, conf.sparkConf.getAll.toMap) features.foldLeft(spec) { case (spec, feature) => val configuredPod = feature.configurePod(spec.pod) val addedSystemProperties = feature.getAdditionalPodSystemProperties() val addedResources = feature.getAdditionalKubernetesResources() KubernetesDriverSpec( configuredPod, spec.driverKubernetesResources ++ addedResources, spec.systemProperties ++ addedSystemProperties) }
看完整个过程,可以发现,装配 Driver Pod 的步骤竟然如此复杂。这个设计也是延续了 Spark 2.2 on K8S 那个 Fork 的思路。
- 通过自定义镜像,将 PodTemplate 文件置入镜像的某个目录中,如
/opt/spark/template.yaml
- 然后在 SparkConf 填入参数
spark.kubernetes.driver.podTemplateFile=/opt/spark/template/driver.yaml
- 如果 Pod 里准备起其他容器,则需要在 SparkConf 指定 Driver Container 的名字,例如
spark.kubernetes.driver.podTemplateContainerName=driver-container
3 Example
下面给出一个例子,来给 Spark 的 Drvier/Executor 都加一个 initContainer,将 PodTemplate 文件 template-init.yaml
放在 /opt/spark
目录下,下面是 PodTemplate 的具体内容,就是加一个会 sleep 1s
的 initContainer。
apiversion: v1 kind: Pod spec: initContainers: - name: init-s3 image: hub.oa.com/runzhliu/busybox:latest command: ['sh', '-c', 'sleep 1']
SparkConf 需要加上
spark.kubernetes.driver.podTemplateFile=/opt/spark/template-init.yaml spark.kubernetes.executor.podTemplateFile=/opt/spark/template-init.yaml
运行一个 SparkPi 的例子,spark-submit
命令如下。
/opt/spark/bin/spark-submit --deploy-mode=cluster --class org.apache.spark.examples.SparkPi --master=k8s://https://172.17.0.1:443 --conf spark.kubernetes.namespace=demo --conf spark.kubernetes.driver.container.image=hub.oa.com/public/spark:v3.0.0-template --conf spark.kubernetes.executor.container.image=hub.oa.com/public/spark:v3.0.0-template --conf=spark.driver.cores=1 --conf=spark.driver.memory=4096M --conf=spark.executor.cores=1 --conf=spark.executor.memory=4096M --conf=spark.executor.instances=2 --conf spark.kubernetes.driver.podTemplateFile=/opt/spark/template-init.yaml --conf spark.kubernetes.executor.podTemplateFile=/opt/spark/template-init.yaml --conf=spark.kubernetes.executor.deleteOnTermination=false local:///opt/spark/examples/jars/spark-examples_2.12-3.0.0-SNAPSHOT.jar 100
运行结束,查看一下 Driver Pod 的 YAML 文件,发现 initContainer 已经加上,并且运行正常。
... initContainers: - command: - sh - -c - sleep 1 image: hub.oa.com/runzhliu/busybox:latest imagePullPolicy: Always name: init resources: {} ... initContainerStatuses: - containerID: docker://526049a9a78c4b29d4e4f7b5fcc89935d44c0605bcbf427456c7d7bdf39a6172 image: hub.oa.com/runzhliu/busybox:latest lastState: {} name: init ready: true restartCount: 0 state: terminated: containerID: docker://526049a9a78c4b29d4e4f7b5fcc89935d44c0605bcbf427456c7d7bdf39a6172 exitCode: 0 finishedAt: "2020-04-02T00:03:35Z" reason: Completed startedAt: "2020-04-02T00:03:34Z"
PodTemplate 文件里,有几个事情需要注意一下的,就是大小写要符合 Kubernetes 的规范,比如 Pod 不能写成 pod,initContainer 不能写成 initcontainer,否则是不生效的。
4 Summary
Apache Spark 3.0 支持 PodTemplate,所以用户在配置 Driver/Executor 的 Pod 的时候,会更加灵活,但是 Spark 本身是不会校验 PodTemplate 的正确性的,所以这也给调试带来了很多麻烦。关于 NodeSelector, Taints, Tolerations 等,这些字段在 Spark Operator 中设置,倒是比较方便的。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
如何让你的k8s集群更安全
最近阿里云容器团队与Palo Alto Networks的安全团队发现,目前用户自己部署的Kubernetes集群中有约2752个可能存在的安全隐患,比如用户把Kubernetes的API向所有互联网IP地址开放了。其中有超过120个Kubernetes集群甚至没有启用API认证,这导致了所有人都可以对这些不安全Kubernetes集群进行访问,读取信息,甚至远程部署恶意容器。这将给用户带来极大的安全风险。同时,Palo Alto Networks的Unit42的资深研究员Jay Chan发现目前全球有超过1400个不安全的Docker主机,8673个不安全运行的容器,17927个有漏洞的镜像和15229个不安全的目录挂载。更需要大家引起重视的是,其中47.7%在中国。可查看原文链接。 首先,介绍一下什么是Kubernetes的API server。顾名思义,Kubernetes的API server的主要功能就是提供REST API,来访问和控制Kubernetes集群的。它的功能非常强大,一旦你拥有了这个API的所有权限,也就类似你有了对整个集群的root权限了。对于没有对Kube...
- 下一篇
【云栖号在线课堂】重磅推荐:湖畔大学执行教育长陈龙 讲述疫情下的全球经济
受疫情影响,如何轻松实现在家办公和学习?不用慌,云栖号在线课堂,每天都有产品技术专家分享,带你快速入门云计算!下面就给大家推荐关于CIO学院攻“疫”技术培训及2020大数据技术公开课第二季的精品课程! CIO学院攻“疫”技术培训 “开展技术普惠公益,与广大技术人共同学习成长!”是阿里CIO学院“技术攻疫(公益)大咖讲开设的初衷。该系列课程邀请到李飞飞、贾扬清、丁险峰、华先胜、王刚、金榕、小邪、五福、司罗、肖力、施尧耘、吴翰清等数十位技术大咖,与大家共同探讨人工智能、云计算、企业安全体系……的技术与实践。CIO学院攻“疫”技术培训第一期 达摩院自动驾驶实验室负责人王刚介绍无人驾驶的经典发展路线、面对的核心问题、最新到技术成果以及从黑科技到商业化的未来。阿里巴巴集团副总裁、达摩院高级研究员金榕从深度学习到AI三大关键技术方向,看AI技术应用中的困局、破局,以及未来。 【课程目录】 讲师 直播主题 观看视频 王刚 自动驾驶之路上的“能”与“不能” 点击观看 金榕 困局与破局:从深度学习到AI三大关键技术 点击观看 CIO学院攻“疫”技术培训第二期 云可以带来哪些切实的好处?如何用好云?在云的...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS关闭SELinux安全模块
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程