随着kubernetes的发展,大数据体系拥抱k8s成为了必经之路。
从Spark 2.4 版本开始,Spark 实验性支持 Kubernetes 作为资源管理器。不过虽然是实验性质,但是已经有很多单位将之用于生产环境了,并取得很好的效果,在可移植性,可扩展性,成本等方面都取得了收益。
本文主要解读一下Spark 3.0 对于kubernetes的增强。
本文共分为5个部分,每个部分都有一个功能类别。你将首先看到配置更改,然后是运行时环境和安全性增强。之后,将了解Kubernetes的主要发展之一-pod模板。到文章末尾,将了解到从贡献者的角度来看发生了什么变化。
配置
此类别的第一个重要更改是配置验证。从Apache Spark 3.0开始,与模式_[-._a-zA-Z][-._a-zA-Z0-9]*
_不匹配的Kubernetes属性(带有spark.executorEnv
前缀)将被忽略并显示警告消息如下:
Invalid key: ... a valid environment variable name must consist of alphabetic characters, digits, '_', '-', or '.', and must not start with a digit.
在3.0版本中,可以使用spark.kubernetes.driver.request.cores
属性为 driver 请求特定数量的CPU核。而 executor 的属性(spark.kubernetes.executor.request.cores)自Spark 2.4.0起可用。
除此之外,还添加了一些时间控制属性。使用spark.kubernetes.submission.connectionTimeout
和spark.kubernetes.submission.requestTimeout
,可以控制连接和请求超时,以在客户端模式下启动 executor 程序。还存在两个类似的属性来处理请求 driver 的相同超时(spark.kubernetes.driver.requestTimeout
,spark.kubernetes.driver.connectionTimeout
)。
运行时环境
另一类功能与运行时环境有关。首先,对于PySpark的用户,Python 3是Docker镜像中的默认绑定(仍支持版本2)
// Default change in the config
val PYSPARK_MAJOR_PYTHON_VERSION =
ConfigBuilder("spark.kubernetes.pyspark.pythonVersion")
.doc("This sets the major Python version. Either 2 or 3. (Python2 or Python3)")
.version("2.4.0")
.stringConf
.checkValue(pv => List("2", "3").contains(pv),
"Ensure that major Python version is either Python2 or Python3")
.createWithDefault("3") // was "2" in Spark 2.4.0
如果对绑定感到好奇,可以仔细研究以下的代码:
# /resource-managers/kubernetes/docker/src/main/dockerfiles/spark/entrypoint.sh
if [ "$PYSPARK_MAJOR_PYTHON_VERSION" == "2" ]; then
pyv="$(python -V 2>&1)"
export PYTHON_VERSION="${pyv:7}"
export PYSPARK_PYTHON="python"
export PYSPARK_DRIVER_PYTHON="python"
elif [ "$PYSPARK_MAJOR_PYTHON_VERSION" == "3" ]; then
pyv3="$(python3 -V 2>&1)"
export PYTHON_VERSION="${pyv3:7}"
export PYSPARK_PYTHON="python3"
export PYSPARK_DRIVER_PYTHON="python3"
fi
关于Scala-Spark API,第一个运行时演进涉及JDK版本。你可能已经知道,Apache Spark 3.0直接跳过了版本9和10的兼容性工作之后,添加了对JDK版本11(SPARK-24417)的支持。在Kubernetes部分中实现了这一支持,并提供了一个示例,该示例使用来自 docker-image-tool.sh 的Java 11标记构建的Spark Docker镜像:
$0 -r docker.io/myrepo -t v3.0.0 -b java_image_tag=11-jre-slim build
最后,为了优化测试执行,Apache Spark 3.0测试镜像使用JRE而不是JDK。
安全增强
在下一类别中,可以找到所有重要的安全增强功能。关于容器,最佳实践之一是不在镜像中使用root用户。在以前的版本中,从项目的docker-image-tool.sh构建的镜像使用根目录。它在3.0中进行了更改,因为该脚本设置了可以用-u
参数覆盖的默认用户。
第二个重要演变是关于secret编辑。在Apache Spark 3.0之前,UI和日志中仅显示带有“ secret”或“ password”之类的配置属性的值。在3.0中,针对该Kubernetes服务器身份验证中使用的spark.kubernetes.authenticate.submission.oauthToken
属性,向该列表添加了一个新配置“令牌”。
最后,Apache Spark 3.0还添加了在集群和客户端模式下对Kerberos的支持。回想一下,Kerberos是一种基于票证的网络身份验证协议,用于解决非安全网络中的身份问题。在Apache Spark上下文中,此功能有助于与HDFS或任何其他kerberized服务进行安全通信。
可扩展性
下一个重要功能是可扩展性。 Kubernetes附带了一个称为Pod模板的YAML规范,可用于创建和运行新Pod。 社区选择它作为定制请求的替代方法。在此之前,必须将任何新的Kubernetes选项添加到Apache Spark配置文件中。从长远来看,这可能会增加Kubernetes和Spark之间的差距,并使该项目难以维护。
扩展在Kubernetes上执行的Apache Spark Pod的一种灵活方法是使用这些属性中的Pod模板,即 driver 的spark.kubernetes.driver.podTemplateFile
和 executor 的spark.kubernetes.executor.podTemplateFile
。重要的是要注意,某些模板属性永远不会覆盖Apache Spark配置管理的值,例如,用于命名空间或pod重启策略的属性。
随着Kubernetes的发展,Pod的参数会逐步增加,单纯依靠命令行参数,会变得越来越复杂。对于Pod模板的支持,一是可以降低spark 对于k8s版本的耦合,二是表达力更加丰富。
测试优化
新版本的Apache Spark测试中用更加轻量级更强大的Minio取代了Ceph。
此外,还为secret测试添加了更好的错误消息处理。同样,具有不可预测的Thread.sleep的并发控件也被侦听器和基于CountDownLatch的编排所替代(有关Java类的更多信息,请参见CountDownLatch)。
除此之外,还为Apache Spark 2.4中引入的功能添加了一些额外的集成测试。其中之一涉及持久卷。
结论
按照社区规划,从Apache Spark 3.1.0开始,Kubernetes资源管理器的状态将从试验性变为一般可用性,并会增加很多新功能。在翻译本文的时候,Apache Spark 3.1.0 已经release,是时候将我们的spark 运行到 k8s 中了。