随着 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 部分中实现了这一支持, 并提供了一个示例, 该示例使用来自 http://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 开始, 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
来源: https://zhuanlan.zhihu.com/p/346676266