Spark on K8s -- statefulset

本文介绍了Spark在Kubernetes上使用StatefulSet运行executor的实现,包括测试样例、实现分析和为何选择StatefulSet。作者分享了构建executor Pod、StatefulSet的过程,并探讨了与ReplicaSet的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道现在已经release的spark版本中,spark on K8s的实现,是将driver和executor作为pod跑在K8s中,但是目前spark已经实现了将executor作为statefulsets跑在K8s中,只不过还处于开发阶段,有一些细节还在完善中。但是博主已经在自己的环境中尝试过了,已经可以成功的运行一个spark application,相信这个功能应该能很快上线。本文这里就针对这个功能的实现做一些介绍。

主要参考链接:[SPARK-36058][K8S]: https://github.com/apache/spark/pull/33508

测试样例

拉取最新的spark master branch的code,制作一个docker image, 这些步骤都比较简单,参考官网就可以完成:

1. ./build/mvn -Pkubernetes -DskipTests clean package
2. $ ./bin/docker-image-tool.sh  -t my-tag build

submit command:
提交一个spark-pi job

.\bin\spark-submit.cmd --master k8s://<master-url> --deploy-mode cluster --name spark-pi --class org.apache.spark.examples.SparkPi --conf spark.executor.instance=2 --conf spark.kubernetes.container.image=<docker image>  --conf spark.kubernetes.allocation.pods.allocator=statefulset --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark local:///opt/spark/examples/jars/spark-examples_2.12-3.3.0-SNAPSHOT.jar 5000

通过执行kubectl 的一些命令,可以观察到,最终运行了一个driver pod和一个statefulset, 这个statefulset中有两个pod作为了executor。当job结束,statefulset就会被删除。

实现分析

这里我给出一个基础的UML图,很多东西都有省略,具体大家可以对照源码看。
在这里插入图片描述

上图是已经release的spark版本的code,也就是将executor作为Pod直接跑在K8s上。为了实现statefulset, 开源社区做了一些扩展和改动。

从entrypoint.sh文件里我们可以看到,之前launch一个executor的class是CoarseGrainedExecutorBackend,现在改为了KubernetesExecutorBackend,这个作为在K8s上运行在executor上的backend。

executor)
    shift 1
    CMD=(
      ${JAVA_HOME}/bin/java
      "${SPARK_EXECUTOR_JAVA_OPTS[@]}"
      -Xms$SPARK_EXECUTOR_MEMORY
      -Xmx$SPARK_EXECUTOR_MEMORY
      -cp "$SPARK_CLASSPATH:$SPARK_DIST_CLASSPATH"
      org.apache.spark.scheduler.cluster.k8s.KubernetesExecutorBackend
      --driver-url $SPARK_DRIVER_URL
      --executor-id $SPARK_EXECUTOR_ID
      --cores $SPARK_EXECUTOR_CORES
      --app-id $SPARK_APPLICATION_ID
      --hostname $SPARK_EXECUTOR_POD_IP
      --resourceProfileId $SPARK_RESOURCE_PROFILE_ID
      --podName $SPARK_EXECUTOR_POD_NAME
    )
    ;;

增加了一个abstract class AbstractPodsAllocator,这样就将来不管是以什么方式去allocate executor,只需要实现该类即可。

@DeveloperApi
abstract class AbstractPodsAllocator {
   
  /*
   * Set the total expected executors for an application
   */
  def setTotalExpectedExecutors(resourceProfileToTotalExecs: Map[ResourceProfile, Int]): Unit
  /*
   * Reference to driver pod.
   */
  def driverPod: Option[Pod]
  /*
   * If the pod for a given exec id is deleted.
   */
  def isDeleted(executorId: String): Boolean
  /*
   * Start hook.
   */
  def start(applicationId: String, schedulerBackend: KubernetesCluster
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值