如何在 Kubernetes 环境中运行 Spark 集群

处理这么大量的数据,背后的机器可能是数以千计,无法通过人工来监控机器的状态。因此,本文将介绍用 Kubernetes 容器管理工具,并通过简单示例,告诉你如何建立一个 Spark 集群。

准备阶段

1.需要拥有正在运行的 Kubernetes 集群,并使用 Kubectl 为其配置访问权限。如果你还没有可用的 Kubernetes 集群,则可以使用 Minikube 在本地计算机上设置测试集群 。

  • 我们建议将 Minikube 更新为最新版本(编写本文档时为0.19.0),因为某些早期版本可能无法启动具有所有必要组件的 Kubernetes 集群。

2.需要具有适当的权限才能在集群中创建和列出 Pod,ConfigMaps 和 Secrets。想要确认,你可以通过运行 Kubectl Get Pods,Kubectl Get Configmap 以及 Kubectl Get Secrets 列出这些资源。

  • 使用的服务帐户或凭据也必须具有相应的权限,以便编辑 Pod 模板。

3.需要拥有 Kubernetes 支持的 Spark 配置。这可以从稳定版本的 Tarball 或通过建立 Kubernetes 支持的 Spark 来获得。

  • 需要在群集中配置 Kubernetes 的 DNS。

准备镜像和驱动

Kubernetes 要求用户提供的镜像可以部署到容器的 Pod 中。镜像是要建立在一个 Kubernetes 支持的容器中运行的运行时环境。Docker 是一个经常与 Kubernetes 一起使用的容器运行时环境。所以 Spark 提供了一些与 Docker 一起快速入门的支持。

如果你希望使用已经构建好的 Docker 镜像,则可以使用 Kubespark 中发布的镜像 。镜像如下:

如何在 Kubernetes 环境中运行 Spark 集群


你也可以从源代码构建这些 Docker 镜像,或根据需求自定义它们。分布式 Spark 包括基础镜像,驱动程序,执行程序,并分别对应 dockerfiles/spark-base/Dockerfile,dockerfiles/driver/Dockerfile, dockerfiles/executor/Dockerfile,和 dockerfiles/init-container/Dockerfile。

使用这些 Docker 文件来构建 Docker 镜像,然后这些镜像要发送到注册中心进行标记。最后,将镜像推送到注册中心。

例如,如果注册中心主机是 Registry-Host, 正在使用5000端口:

如何在 Kubernetes 环境中运行 Spark 集群


请注意,这个 Spark-Base 是其他镜像的基础镜像。必须在其他镜像之前构建,其他镜像可以按任意顺序构建。

把程序提交到 Kubernetes

Kubernetes 应用程序可以通过 Spark-Submit 执行。

例如,要计算 Pi 的值,假设镜像如上所述设置:

如何在 Kubernetes 环境中运行 Spark 集群


通过 --Master 命令行将参数传递给 Spark-Submit 或通过 Spark.Master 在应用程序的配置中进行设置以便来指定的 Spark 主机必须是具有该格式的 URL k8s://<api_server_url> 。

使用主字符串前缀 K8s:// 将使 Spark 应用程序在 Kubernetes 集群上启动,API 服务器通过 Api_server_url 与之交互 。

如果 URL 中没有指定 HTTP 协议,则默认为 https。

例如,将主服务器设置 K8s://example.com:443 等同于将其设置为 K8s://https://example.com:443,但在不同端口上不使用 TLS 连接时,要将主服务器将设置为 k8s://http://example.com:8443。

如果您有 Kubernetes 集群设置,则可以通过执行 Kubectl cluster-info 发现 Apiserver URL。

如何在 Kubernetes 环境中运行 Spark 集群


在上面的例子中,特定的 Kubernetes 集群可以通过指定 --master k8s://http://127.0.0.1:8080 参数来与 Spark-Submit 一起使用 。

请注意,当前只能在集群模式下执行应用程序,并且驱动程序及其执行程序也要在集群上运行。

最后,请注意,在上面的例子中,我们指定了一个具有特定 URI 的 Jar 包 Local:// 。该 URI 是已经在 Docker 镜像中的示例 Jar 包的位置。下面讨论使用计算机本地磁盘上的依赖关系。

当启用 Kubernetes RBAC 时,默认驱动程序使用的服务帐户可能没有合适的 Pod 编辑权限来启动执行程序 Pod。我们建议添加另一个服务帐户,比如拥有必要权限的 Spark。例如:

如何在 Kubernetes 环境中运行 Spark 集群


这样,可以添加 --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark 到上面的 Spark-Submit 命令行来指定要使用的服务帐户。

依赖管理

从机器提交的应用程序依赖关系需要被发送到资源中转服务器 ,然后驱动程序和执行程序可以与之通信以检索这些依赖关系。

表示运行此服务的最小 Kubernetes 资源的 YAML 文件位于该文件中 conf/kubernetes-resource-staging-server.yaml。这个 YAML 文件配置一个 ConfigMap 的资源中转服务器的 Pod,并通过一个带有固定节点端口的服务公开服务。

使用包含 YAML 文件部署资源中转服务器需要您具有创建部署,服务和配置映射的权限。

要使用默认配置运行资源中转服务器,可以创建 Kubernetes 资源:

如何在 Kubernetes 环境中运行 Spark 集群


然后你可以像下面例子一样计算 Pi 的值:

如何在 Kubernetes 环境中运行 Spark 集群


资源中转服务器的 Docker 镜像也可以从源代码构建,类似于驱动程序和执行程序镜像。

Dockerfile 提供了 dockerfiles/resource-staging-server/Dockerfile。

提供的 YAML 文件专门将服务规范中的 NodePort 设置为31000。如果端口31000在群集的任何节点上都不可用,则应从服务规范中删除 NodePort 字段,并允许 Kubernetes 群集确定 NodePort。

请确保在提交你的应用程序时,根据 Kubernetes 集群选择的 NodePort 在资源中转服务器 URI 中是可用的端口。

没有资源中转服务器的依赖管理

请注意,此资源中转服务器仅用于提交本地依赖项。如果你的应用程序的依赖关系全部托管在远程位置(如 HDFS 或 HTTP 服务器)中,那么它们可能会被其适当的远程 URI 引用。此外,应用程序依赖关系可以预先安装到定制的 Docker 镜像中。这些依赖关系可以通过在 Local://URI 中引用它们和用 / 或 SPARK_EXTRA_CLASSPATH 在 Dockerfiles 中设置环境变量来添加到类路径中。

访问 Kubernetes 集群

Spark-Submit 也支持通过本地 Kubectl 代理提交 。

可以使用身份验证代理直接与 Api 服务器进行通信,而无需将凭证传递给 Spark-Submit。 本地代理可以通过运行下面的命令启动:

如何在 Kubernetes 环境中运行 Spark 集群


如果我们的本地代理正在监听8001端口,我们会提交如下所示的代码:

如何在 Kubernetes 环境中运行 Spark 集群


Spark 和 Kubernetes 集群之间的通信是使用 Fabric8 Kubernetes-Client 库执行的。当我们拥有 Fabric8 Kubernetes-Client 库不支持的认证提供者时,可以使用上述机制。目前支持使用 X509 客户端证书和 OAuth 令牌进行身份验证。

运行 PySpark

在 Kubernetes 上运行 PySpark 时和在 Yarn 和 Mesos 上启动时使用相同的 Spark-Submit 逻辑。Python 文件可以通过在 --Py-files 设置,

以下是一个示例提交:

如何在 Kubernetes 环境中运行 Spark 集群


Kubernetes 中的动态分配

Kubernetes 上的 Spark 支持集群模式下的动态分配。此模式需要运行外部 Shuffle 服务。这是一个典型的 Daemonset 与 Provisioned Hostpath Volume 。这个 Shuffle 服务可以由属于不同的 SparkJobs 的执行者共享。

这里提供了一个示例配置文件 conf/kubernetes-shuffle-service.yaml ,可以根据需要为特定群集定制配置文件。需要注意的是对于 Shuffle 服务适当地设置 spec.template.metadata.labels 是很重要的,因为在群集中可能有多个 Shuffle 服务实例在运行。这些标签为 Spark 应用程序提供了一种定位指定 Shuffle 服务的方法。

举例来说,如果我们要使用的 Shuffle 服务在默认的命名空间,与 Pods app=spark-shuffle-service 和 Spark-version=2.2.0,我们可以使用这些标签来定位工作启动时指定的 Shuffle 服务。为了运行启用动态分配的作业,该命令可能如下所示:

如何在 Kubernetes 环境中运行 Spark 集群


外部 Shuffle 服务必须安装可以与执行程序 Pod 共享的目录。提供的示例 YAML 规范将 HostPath 卷挂载到外部 Shuffle 服务 Pod,但这些 HostPath 卷也必须挂载到执行程序中。

使用外部随机播放服务时,Spark.local.dir 配置中指定的目录将作为 HostPath 卷挂载到所有执行程序容器中。

为确保不会意外挂载不正确的 HostPath 卷,Spark.Local.Dir 在使用 Kubernetes 时,必须在应用程序的配置中指定值,尽管在使用其他群集管理器时默认为 JVM 的临时目录。

高级

使用 TLS 保护资源中转服务器

资源中转服务器的默认配置不通过 TLS 进行保护。强烈建议将其配置为保护通过中转服务器提交的密钥和 Jar 文件。

YAML 文件 Conf/kubernetes-resource-staging-server.yaml 包含保存资源中转服务器配置的 ConfigMap 资源。

可以在这里调整属性以使资源中转服务器监听 TLS。

请参阅安全性页面以获取与 TLS 相关的可用设置。

资源中转服务器的命名空间是 Kubernetes.ResourceStagingServer ,例如,服务器的密钥库的路径将被设置 Spark.ssl.Kubernetes.ResourceStagingServer.KeyStore。

除了之前链接的安全页面指定的设置之外,资源中转服务器还支持以下附加配置:

如何在 Kubernetes 环境中运行 Spark 集群


请注意,尽管可以在 ConfigMap 中设置属性,但仍然需要考虑将适当的密钥文件安装到资源中转服务器的容器中。

一个常见的机制就是使用 Kubernetes 机密作为秘密卷。请参阅相应的 Kubernetes 文档以获取指导,并相应地调整提供的 YAML 文件中的资源中转服务器规范。

最后,在提交应用程序时,你必须指定一个 TrustStore 或一个 PEM 编码的证书文件,以通过 TLS 与资源中转服务器进行通信。

可以设置 TrustStore,也可以设置 spark.ssl.kubernetes.resourceStagingServer.trustStore 证书文件 spark.ssl.kubernetes.resourceStagingServer.clientCertPem 。

例如,我们的 SparkPi 示例如下所示:

如何在 Kubernetes 环境中运行 Spark 集群


视频链接:https://www.youtube.com/watch?v=UywgL70FQ3s

作者:靳日阳,JFrog 研发工程师

具有多年软件开发经验;对Java主流技术、前沿框架都具有丰富的开发经验;擅长Linux服务器,对优化,部署等有深入研究,熟悉Jenkins,持续集成及交付,DevOps等。

欢迎转载,但转载请注明作者与出处。谢谢!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章