image.png

随着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.connectionTimeoutspark.kubernetes.submission.requestTimeout,可以控制连接和请求超时,以在客户端模式下启动 executor 程序。还存在两个类似的属性来处理请求 driver 的相同超时(spark.kubernetes.driver.requestTimeoutspark.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资源管理器的状态将从试验性变为一般可用性,并会增加很多新功能。例如:

  • 更好地处理节点关闭。针对Spark 3.1的此功能将使Kubernetes可以在Spark执行程序发生故障时(由于动态分配或Kubernetes节点发生故障)提前几秒钟获得通知,然后将shuffle和缓存数据文件复制到其他执行程序,以便这项工作不会丢失。
  • 使用远程存储持久存储shuffle数据。此功能将使Spark异步将shuffle文件复制到远程存储(例如S3),这将使shuffle架构在Kubernetes上更健壮(导致最终状态,其中计算和存储资源被完全分解)。

参考文章

What's new in Apache Spark 3.0 - Kubernetes

Running Spark on Kubernetes


iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。