一次 Spark Operator 问题的救火

你也许刚好没有接触这块的知识点 , 对 , 刚好 。 没有关系 , 我尝试输出的是一种定位和解决问题的快乐方法 。
背景你听过Spark , Maybe听过SparkonK8S , 但是Almostnot听过SparkOperator 。
JustRemember这是个车厂多于轮胎厂的时代 , 组合创新盛行而有效 。
SparkOperator就是GoogleCloudNative方式在K8S上运行Spark的组装车 。 不多说 , 上车 。
现象在升级SparkOperator后遇到了SparkApplication无法解析HDFSnamenodeservicename , 报"UnknownHost"的错误 。 前方说我们十万火急 , 需要立刻解决 , 不解决就影响项目进度了 。 耳熟?对 , 我们遇到的问题4个9以上面的话结尾 。 First , calmdown 。
线索从表象上看 , 最直接的问题是在SparkDriver中没有HDFS的配置文件:hdfs-site.xml从Pod的信息中可以看到HDFS配置Volume未挂载查看SparkOperator的Log , 有一行可疑信息"BadCertificate"信息因为"BadCertificate"能给我们的信息可能很关键 , 但是并不直观 , 没有直接说明是谁和谁之间通信的证书不对 , 所以本次定位是采用从Volume挂载的地方入手 。 平常喜欢的方式是从现象到理论到代码的方式进行递进 。 先顺着线索收集了相关的理论信息 。
1.MountingvolumeSparkOperator的说明文档中有指出Mountingvolume需要Enablewebhook , 这个点比较难找 。
https://github.com/GoogleCloudPlatform/spark-on-k8s-operator/blob/master/docs/user-guide.md#mounting-volumes
2.Mutatingadmissionwebhook这个概念属于K8S的范畴 , 这张图说明了MutatingAdmissionWebhook插件化应用的位置 。
图片来源于这篇对AdmissionWebhook的介绍:,(敲黑板 , 贴出来原链接的意思就是值得看) 。
在K8S中 , ServiceAccount通常我们只能使用公钥 , 如果自定义服务之间需要访问 , 就需要自己生成密钥对、创建K8sSecret , 这个过程在Spark-web-hook-init中调用源码里面hack目录下的脚本完成 。
3.Web-hook-init从这个Job的yaml文件中可以看到 , 在早期的版本中干的事情是清除密钥和创建密钥 。 但是遇到了Update会清除密钥但不创建新密钥的问题 , 后面就将这两个功能拆分成两个yaml 。 见
issues:
猜测从现象和前面收集的信息来看 , 最大的可能是Web-hook-init产生的密钥并没有更新到SparkApiServer 。 很大的可能性是升级是先升级了Spark-operator的APIServer , 然后重新执行了web-hook-init 。 基于原理的猜想 , 大概不那么玄学了吧 , 有效驳斥了老程序定位问题的直觉说 。
验证既然是顺序问题 , 那么我们重启Spark-operator服务 , 功能正常 。 嗯 , 对 , 还是重启大法好啊 。 说的没错 , 同时咱们是有理有据的重启 。
Deeper我起初怀疑是我们内部没有采用Helm部署导致的问题 , 翻开Yaml却发现并没有关于InstallOrder的控制 , Helm的默认控制顺序和预期的不一样 , Deployment先部署 , Secret后部署 。
#L61
思考为什么部署的时候没事 , 反而update的时候有事呢? 。 这里有关于如果pod创建时 , Secret还没有创建是如何运作的介绍 。
这个纯粹和我们Update的方式相关 , 操作人员在Update前执行了Delete操作 。 理论上K8S走的是Volidate-Diff-Apply的操作模式 , 只会更新Diff的地方 。 单纯的Update是不会更新Secret的 。
所以 , 包含这么多知识点的一个问题 , 归根到底却是一个操作问题 。 又有什么关系呢?有收获就OK了 。
后记我是个经常救火 , 又立志决不当Fireman的人 , 所以保持借假修真的心态 , 探究的更加深入 , 找出知识点和乐趣 。
【一次 Spark Operator 问题的救火】提前祝各位Coder中秋快乐 。


    推荐阅读