Spark on k8s: 调试客户端spark-submit进程

Spark on K8S模块的代码又臭又长,离我们上生产环境,也就一个debug的距离。干干巴巴,麻麻咧咧,盘它。。。

前置条件

  • 你有一个可以提交 Spark on k8s 作业的 k8s 集群,可以参考https://spark.apache.org/docs/latest/running-on-kubernetes.html,自己搭一个玩玩

    • 理论上没有也没关系,因为我们客户端进程只是一个本地的java程序,只是如果没有真正的 k8s 集群,这个作业在debug到一定阶段会走不下去而已
  • 一只你熟练使用的 IDE

    • 推荐 Intellj IDEA
  • 一份新鲜热乎的 Spark 源码

  • 一坨打包过的Spark package

    • 可以根据上面的spark源码自己打包 - building-a-runnable-distribution
    • 也可以下载 release,然后将代码 checkout 到对应的 tag

原理说明

Spark on k8s: 调试客户端spark-submit进程_第1张图片
spark on k8s架构

上图所示是 Spark 官方文档中的 Spark on k8s 的架构图,图很简单,左边的 Client 和右边的 k8s 集群,其中 client 通过 spark-submit 接口和 k8s 集群进行交互,主要完成的是Spark Driver Pod的构建,当然由于本文主要讲的是 Client 进程调试相关的东西,后面的细节就先搁置了。

配置 IDE

通过 Remote 模板新建一份配置,默认的话 Host 的指向的一般是localhost,如果你在远程的机器上启动 spark-submit 进程,需要正确的设置Host,我们本地提交的话,直接改个name就可以使用了,如下图所示,


Spark on k8s: 调试客户端spark-submit进程_第2张图片
ide debug 配置

我们需要复制 Command line arguments for remote JVM 的内容,来配置到 spark-submit 进程的 java options里。

配置SPARK_SUBMIT_OPTS

设置 spark-submit 的客户端 java 参数可以通过 SPARK_SUBMIT_OPTS 环境变量来搞定,具体如下,

echo SPARK_SUBMIT_OPTS=\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=50014\" >> conf/spark-env.sh

开始调试

我们使用spark自带的示例程序 org.apache.spark.examples.HdfsTest 来进行调试,

Kent@KentsMacBookPro  ~/Documents/spark-on-k8s/spark-3.0.0-SNAPSHOT-bin-2.7.3  bin/spark-submit \
    --master k8s://https://10.120.238.100:7443 \
    --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

当出现如下打印信息,即可切换到 IDE 中点击 debug 按钮。

Listening for transport dt_socket at address: 50014

当然,在这之前,必须要在合适的位置加上断点。


Spark on k8s: 调试客户端spark-submit进程_第3张图片
断点

运气好的话,启动 debug 后,你就可以在如下位置进入断点。


Spark on k8s: 调试客户端spark-submit进程_第4张图片
断点

我们注意到这个类中有一个 KubernetesClient 对象,我们试着用它来和 k8s 集群做个亲密交互。

Spark on k8s: 调试客户端spark-submit进程_第5张图片
获取configmap

上面的例子是访问我在 k8s 上提前建立好的一个ConfigMap。

所以我们可以看到 Client 进程中主要就是实例化了一个 KubernetesClient 对象来达到了和 k8s 集群,也就是 api server 的交互,完成对Spark Driver Pod的描述。

总结

文章很长,干干巴巴,麻麻咧咧,其实就是设置一个 SPARK_SUBMIT_OPTS 环境变量的事情,233333~

你可能感兴趣的:(Spark on k8s: 调试客户端spark-submit进程)