如何在K8s上让同一Spark应用的Executor Pod分散到不同节点?
解决Spark Executor Pod在K8s上跨节点分散部署的问题
核心思路:使用Pod反亲和性(PodAntiAffinity)
要让同一应用的Executor Pod尽可能分散到不同节点,应该用podAntiAffinity(反亲和性)而非podAffinity——后者是让Pod聚集,反亲和性才是让Pod尽量避开同节点的同应用Executor。
利用Spark运行时标签配置反亲和性
Spark会自动给Executor Pod打上spark-app-name、spark-app-selector这类运行时标签,你可以通过Spark的配置直接注入反亲和性规则,规则里可直接引用这些动态生成的标签。
方法1:命令行参数直接配置
提交Spark应用时,添加以下配置即可指定反亲和性规则:
spark-submit \ --master k8s://https://<k8s-api-server> \ --deploy-mode cluster \ --name my-spark-app \ --conf spark.kubernetes.executor.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution='[{ "weight": 100, "podAffinityTerm": { "labelSelector": { "matchExpressions": [{ "key": "spark-app-name", "operator": "In", "values": ["${spark.app.name}"] }] }, "topologyKey": "kubernetes.io/hostname" } }]' \ # 其他应用参数...
关键细节:
preferredDuringSchedulingIgnoredDuringExecution是软约束:如果集群节点不足,Pod仍会被调度,只是优先分散;若要强制分散(硬约束),改用requiredDuringSchedulingIgnoredDuringExecution,但需确保集群有足够节点,否则Pod会处于Pending状态。${spark.app.name}是Spark内置变量,会自动替换为你提交时指定的应用名称,对应Executor Pod上的spark-app-name标签。topologyKey: kubernetes.io/hostname表示以节点为分散单位。
方法2:使用Pod模板文件
如果配置逻辑复杂,建议用Pod模板文件(比如executor-pod-template.yaml),内容如下:
apiVersion: v1 kind: Pod metadata: labels: # 可自定义额外标签,Spark会自动添加上运行时标签 spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: spark-app-name operator: In values: - ${spark.app.name} topologyKey: kubernetes.io/hostname # 其他Pod配置,比如容器镜像、资源限制等
提交应用时指定该模板:
spark-submit \ --master k8s://https://<k8s-api-server> \ --deploy-mode cluster \ --name my-spark-app \ --conf spark.kubernetes.executor.podTemplateFile=executor-pod-template.yaml \ # 其他应用参数...
验证配置效果
提交应用后,查看Executor Pod的调度分布:
kubectl get pods -l spark-app-name=my-spark-app -o wide
检查输出的NODE列,同一应用的Executor Pod应分布在不同节点(集群节点充足的前提下)。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

