Spark on k8s: 调试Driver Pod的方法
相关文章
1 . Spark on k8s: 调试客户端spark-submit进程
通过前一篇博客的学习,已经学会了客户端 spark-submit 这个进程的调试方式,由于是本地进程整个过程还是比较方便的。我们知道 Spark 提交模式一般分为 client/cluster 两种,直观上的区别就是 SparkContext
类是否在客户端进程中进行实例化。Spark on K8S 从2.3版本开始支持cluster模式,从2.4开始支持client模式,对于调试 Driver 而言,client 模式可以直接按照之前的文章进行,对于 cluster 模式,Diver 运行在 Pod 里面,我们改如何调试呢?
前置条件
- 你有一个可以提交 Spark on k8s 作业的 k8s 集群,可以参考https://spark.apache.org/docs/latest/running-on-kubernetes.html,自己弄一个 minikube
- 你最爱的的 IDE
- 推荐 Intellj IDEA
- 把 Spark 源码放进 IDE
- 把源码打包 或者 checkout至已存在包的git revision
原理说明

上图所示是 Spark 官方文档中的 Spark on k8s 的架构图,图很简单,左边的 Client 和右边的 k8s 集群,当然这个官方图比较老,也不是很准确的描述 Spark on k8s 所有的提交方式, 它所示的是 cluster 模式是的运行时形态, 我们可见 Spark 的 Driver Pod 在 k8s 的某个 kubelet 之上,我们要调试它,就需要和他内部的 jvm 建立 JPDA Transport 通信。
配置 IDE
这边我们可以直接建立一个 local host 的远程调试配置

开始调试
我们需要在spark的提交参数中加入如下的关键配置,该配置的值可以从 IDE 中copy
-conf spark.driver.extraJavaOptions=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=50014
总的提交命令如下
bin/spark-submit \
--conf spark.driver.extraJavaOptions=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=50014 \
--conf spark.kubernetes.namespace=ns1 \
--conf spark.kubernetes.container.image.pullSecrets=mysecret \
--conf spark.kubernetes.hadoop.configMapName=hz10-hadoop-dir \
--conf spark.master=k8s://https://10.120.238.100:7443 \
--conf spark.kubernetes.container.image=harbor-inner.sparkonk8s.netease.com/tenant1-project1/spark:v3-SPARK-28896
--conf spark.kerberos.keytab=/Users/Kent/Downloads/kyuubi.keytab \
--conf spark.kerberos.principal=kyuubi/dev@HADOOP.HZ.NETEASE.COM \
--conf spark.kubernetes.kerberos.krb5.path=/etc/krb5.conf \
--name hehe \
--deploy-mode cluster \
--class org.apache.spark.examples.HdfsTest \
local:///opt/spark/examples/jars/spark-examples_2.12-3.0.0-SNAPSHOT.jar \
hdfs://hz-cluster10/user/kyuubi/hive_db/kyuubi.db/hive_tbl
如果提交成功我们看到如下图所示的信息,拿到 Spark Driver Pod 的 pod name,它的状态转变成running状态时,说明已经ok,可以进行下一步操作

通过kubectl命令也可以查看该 pod的状态,如下图所示

通过
kubectl log hehe-2c6c6c6cdbf66f13-driver -nns1
命令查看日志,可以看到,我们的 Driver pod 正阻塞在监听状态。

我们需要将这个端口给port-forward
出来,

然后我们就可以在 IDE 中进行启动调试了,当然也不忘在该打断点的地方打上断点
点击debug按钮后,port-forward
会继续打印如下信息。

重新打印 pod 日志,可以发现日志已经打印到断点所在的最前面位置

回转到我们的 IDE, 可以看到已经进入我们设置的断点,接下来就可以进行正常的调试过程了。

下一个断点

我们从上图中可以看到在 Spark Driver Pod 中还会实例化一个 kubernetes 的 client,通过这个 client,Spark Driver进程可以实现与 k8s api server 的通信,实现诸如 executor 分配等逻辑。
总结
对于 Spark On K8S 调试Driver 的 Pod,我们需要通过
-conf spark.driver.extraJavaOptions=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=50014
, 在Driver Pod中启动监听服务,然后通过 k8s 提供的 port-forward
功能, 将这个地址弄到本地,方便的进行调试。