Spark/k8s:如何使用客户端模式在 Kubernetes 上运行 spark提交

Pin*_*lue 6 docker apache-spark kubernetes

我正在尝试在 kubernetes pod 中使用spark-submitwithclient模式向 EMR 提交作业(由于其他一些基础设施问题,我们不允许使用cluster模式)。默认情况下,spark-submit使用hostname该吊舱作为的spark.driver.hosthostname为主机的主机名,以便spark executor解决不了它。并且spark.driver.portpod(容器)也是本地的。

我知道一种将一些 confs 传递给的方法,spark-submit以便spark executor可以与driver,这些配置是:

--conf spark.driver.bindAddress=0.0.0.0 --conf spark.driver.host=$HOST_IP_OF_K8S_WORKER --conf spark.driver.port=32000 --conf spark.driver.blockManager.port=32001

并在 kubernetes 中创建一个服务,以便spark executor可以与driver

apiVersion: v1
kind: Service
metadata:
  name: spark-block-manager
  namespace: my-app
spec:
  selector:
    app: my-app
  type: NodePort
  ports:
    - name: port-0
      nodePort: 32000
      port: 32000
      protocol: TCP
      targetPort: 32000
    - name: port-1
      nodePort: 32001
      port: 32001
      protocol: TCP
      targetPort: 32001
    - name: port-2
      nodePort: 32002
      port: 32002
      protocol: TCP
      targetPort: 32002
Run Code Online (Sandbox Code Playgroud)

但问题是在一个 k8s 工作器上可以运行 1spark-submit个以上的pod,在一个 pod 中甚至可以运行 1个以上的作业。所以在启动 pod 之前,我们需要动态选择 k8s 节点中的几个可用端口并创建一个服务来进行端口映射,然后在启动 pod 的过程中,将这些端口传递给 pod 来告诉spark-submit使用它们。我觉得这有点复杂。

使用hostNetwork: true可能会解决这个问题,但它会在我们的基础设施中引入许多其他问题,所以这不是一个选择。

如果spark-submit可以bindPortdriver.bindAddressdriver.host或支持一样支持概念proxy,那么解决问题会更干净。

有人有类似情况吗?请分享一些见解。

谢谢。

附加上下文 spark version2.4

Pin*_*lue 6

Spark 提交可以采用额外的参数,例如--conf spark.driver.bindAddress, --conf spark.driver.host, --conf spark.driver.port, --conf spark.driver.blockManager.port, --conf spark.port.maxRetries. and用于告诉 Spark Executor 使用此主机和端口连接回 Spark 提交spark.driver.hostdriver.port

\n\n

我们使用hostPortcontainerPort来公开容器内的端口,将端口范围 和hostIP作为环境变量注入到 Pod 中,以便 Spark-submit 知道要使用什么。所以这些额外的参数是:

\n\n
--conf spark.driver.bindAddress=0.0.0.0` # has to be `0.0.0.0` so that it is accessible outside pod\n--conf spark.driver.host=$HOST_IP # k8s worker ip, can be easily injected to the pod\n--conf spark.driver.port=$SPARK_DRIVER_PORT # defined as environment variable\n--conf spark.driver.blockManager.port=$SPARK_DRIVER_PORT # defined as environment variable\n--conf spark.port.maxRetries=$SPARK_PORT_MAX_RETRIES # defined as environment variable\n
Run Code Online (Sandbox Code Playgroud)\n\n

hostPort是 Kubernetes Worker 本地的,这意味着我们不需要担心端口耗尽。k8s调度器可以找到一个主机来运行pod。

\n\n

我们可以在每台主机上保留 40000 到 49000 的端口,并为每个 pod 打开 8 个端口(因为每个 Spark-Submit 需要打开 2 个端口)。端口是根据 pod_id 选择的。由于 Kubernetes 建议每个节点运行的 Pod 数量少于 100 个,因此端口冲突将非常罕见。

\n