EMR On VKE 支持将自定义 Docker 镜像作为集群中任务的默认工作负载运行时。使用自定义镜像具有以下优势:
我们以 Spark 集群为例进行说明。EMR On VKE 的 SparkOperator 运行原理如下:
提交任务后,Spark Operator 将使用预先定制或提交任务的任务模板中定义的镜像启动 Driver Pod,之后启动 Executor Pod。所以,我们可以对配置进行更改,来达到 DriverPod 及 Executor Pod 中使用自定义镜像的目的。
EMR On VKE 提供了 Spark 及 Ray 运行作业的基础镜像,其中包含了开源版本所运行的基本依赖。
您可以通过以下命令获取 Spark 及 Ray 的基础镜像:
# Spark 基础镜像 docker pull emr-vke-public-cn-beijing.cr.volces.com/emr/spark:3.5.1-1.0.0.59-1.3.0 # Ray 基础镜像 docker pull emr-vke-public-cn-beijing.cr.volces.com/emr/ray:2.9.3-py3.9-ubuntu20.04-1.2.0
# 请将 xxxx 替换为您需要的镜像版本 FROM emr-vke-public-cn-beijing.cr.volces.com/emr/spark:xxxx # 其他安装命令,如 RUN pip3 install --upgrade boto3 pandas numpy // For python 3
docker build -t $(PUB_TAG_VKE):$(VERSION) .
您可使用 docker inspect 命令查看对应情况。
根据镜像的不同,您可以使用不同的 docker run 命令执行具体的一些简单任务。
您可以通过 Docker push 命令将镜像发布至您账号下的火山引擎镜像中心中,以便在后续作业中使用该镜像:
docker push xxx/spark:3.5.1-customized
为了后续在 VKE 集群中能够正确获取该镜像,请根据您镜像仓库的权限情况为 VKE 集群配置对应的镜像拉取秘钥。
如,您可以使用下述命令生成秘钥:
kubectl create secret docker-registry my-docker-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL -n YOUR_NAMESPACE
目前支持使用 Spark Submit(登录到 SparkOperator 节点)提交作业及使用 kubectl 提交 SparkApplication 作业。我们以 SparkApplication 方式为例进行提交。
使用 kubectl apply -f
提交下述作业:
apiVersion: "sparkoperator.k8s.io/v1beta2" kind: SparkApplication metadata: name: spark-wordcount spec: type: Scala sparkVersion: 3.2.1 mainClass: org.apache.spark.examples.SparkPi mainApplicationFile: "tos://yourTosPath" arguments: - "1000" driver: cores: 1 coreLimit: 1000m memory: 8g image: xxx/spark:3.5.1-customized # 指定 Driver 自定义镜像 executor: cores: 1 coreLimit: 1000m memory: 4g memoryOverhead: 2g instances: 1 image: xxx/spark:3.5.1-customized # 指定 Driver 自定义镜像 imagePullSecrets: - {{ your-secret }} # 指定 vke 下载 docker 镜像的秘钥
注意
您也可以通过修改默认配置的方式来指定 Executor Pod 和 Driver Pod 的镜像地址和下载秘钥。
在Spark on Kubernetes中,镜像的优先级顺序是:
目前 Ray 支持 RayCluster 和 RayJob 方式。RayJob 方式支持指定自定义镜像,提交RayJob作业参考镜像仓库中的使用示例。
当您希望使用 RayCluster 预先启动的 Pod 提交任务时,我们需要修改 Ray 集群中所创建的自定义资源 RayCluster 来实现。CRD 定义头部分如下:
apiVersion: ray.io/v1 kind: RayCluster
您可以通过 kubectl 查看对应信息:
kubectl get raycluster ray-cluster-kuberay -n {您的 EMR 集群 ID} > raycluster.yaml
打开 raycluster.yaml 文件,您可以看到其 Spec 部分定义了对应 rayCluster 的镜像部分如下,替换红色字体部分为您的新镜像。
apiVersion: ray.io/v1 kind: RayCluster metadata: ... spec: headGroupSpec: ... template: ... spec: affinity: {} containers: - env: [] image: xxx/ray:2.9.1-customized imagePullPolicy: IfNotPresent name: ray-head ... securityContext: {} volumeMounts: - mountPath: /tmp/ray name: log-volume imagePullSecrets: - name: {{ your-secret }} ...
apiVersion: ray.io/v1 kind: RayCluster metadata: ... spec: headGroupSpec: ... workerGroupSpecs: - groupName: workergroup ... replicas: 1 template: metadata: ... spec: affinity: {} containers: - env: [] image: xxx/ray:2.9.1-customized imagePullPolicy: IfNotPresent name: ray-worker resources: ... imagePullSecrets: - name: {{ your-secret }}
修改完成后使用 kubectl 使其生效:
kubectl get raycluster {您的 ray cluster 名称} -n {您的 EMR 集群 ID} > raycluster.yaml
之后您需要手动删除对应的 Pod 以便 ray-operator 可以使用新镜像重建集群:
kubectl delete pod ray-cluster-kuberay-head-{可以通过 kubectl get pod 获取} -n {您的 EMR 集群 ID} kubectl delete pod ray-cluster-kuberay-worker-workergroup-{可以通过 kubectl get pod 获取} -n {您的 EMR 集群 ID}