新版spark镜像与旧版spark-operator不兼容问题排查

前端时间我们团队在更新spark任务使用的镜像时,发现新版spark与旧版的spark-operator不兼容,导致了一些问题,在此记录一下,供有需要的同学参考。

1. 背景

我们团队的主要项目是一个机器学习平台,可以帮助用户创建和管理各种机器学习任务,比如单机任务、spark任务、mpi任务等。平台底层是k8s,我们的平台是基于k8s做的二次开发,实际任务是运行在k8s平台上的。
对于spark任务,我们引入了spark-operator作为任务调度器,spark-operator是由谷歌开发的,并不是spark官方或k8s官方的项目,所以对不同版本的spark和k8s其实兼容性不是很好。
基于spark-operator,spark任务在k8s平台上的运行流程大概是这样的:

  1. 客户端提交sparkapp对象到k8s(spark-operator有validatingWebhook,在sparkapp对象提交时会做拦截,可配置)
  2. spark-operator监听到sparkapp对象,根据对象内容,创建driver pod
  3. driver pod向k8s提交executor pod的创建申请
  4. spark-operator有mutatingWebhook,会在driver pod和executor pod提交时,为他们patch上一些额外信息,比如volume信息和挂载信息,权限相关信息等,之所以不在提交driver pod时一并提交,应该是因为spark-submit命令不支持这些字段,是的,spark-operator内部也是靠spark官方的spark-submit命令来提交driver pod的

2. 环境信息

k8s版本:1.16
spark-operator镜像版本:v1beta2-1.2.3-3.1.1
升级后的spark镜像版本:3.2.1

3. 问题现象

用新的任务镜像(spark版本3.2.1),写出csv文件时会产生一个_temporary目录,跑完了也不删,里面的目录是root的(我们在sparkapp的配置中指定了一个用户,并不是root),并且产出的csv文件也是root的。
产出的文件所属用户不对

在driver和executor pod运行时,进入pod执行id命令,可以看到driver中用户是正常的,而executor中用户是root:
executor pod中用户不对

4. 问题分析

executor pod容器的securityContext是在spark-operator的mutatingWebhook中patch的,如果没patch上,就会默认以root用户运行,产出的文件也就是root的了。经过验证,executor pod的容器securityContext确实是空的,没有patch上。
为什么升级spark镜像之前可以patch上,升级spark版本后却patch不上了呢?这就需要看spark-operator的代码了,经过看代码发现,spark镜像升级后,driver创建的executor pod里container name从“executor”变成了“spark-kubernetes-executor”,spark-operator的webhook给executor pod patch securityContext的时候只检查了"executor"容器名,没检查新的名字,所以securityContext没patch上:
源码部分

5. 问题解决

需要升级spark-operator版本,在新版spark-operator中,会同时检查旧的executor name和新的executor name,就会正常patch容器的securityContext了。我们这次将spark-operator镜像升级到了v1beta2-1.3.7-3.1.1版本。

6. 后记

升级了spark-operator版本后,出现了新的问题,新的spark-operator居然和k8s不兼容了,这个问题请移步:这篇文章查看。

发表评论