RAPIDS 和 Kubernetes 入门#
在 4.0 版本中添加。
本指南将介绍如何在 Kubernetes 集群中设置 RAPIDS Accelerator for Apache Spark。在本指南结束时,读者将能够运行一个在 Kubernetes 集群中的 NVIDIA GPU 上运行的示例 Apache Spark 应用程序。
这是一个快速入门指南,使用默认设置,这些设置可能与您的集群不同。
Kubernetes 需要 Docker 镜像才能运行 Spark。通常,所需的一切都在 Docker 镜像中 - Spark、RAPIDS Accelerator for Spark jar 和发现脚本。
您可以从 CUDA dockerhub 找到其他受支持的基础 CUDA 镜像。它的源 Dockerfile 位于 GitLab 存储库 中,该存储库可用于从头开始从 OS 基础镜像构建 docker 镜像。
先决条件#
Ubuntu 22.04
Spark 3.4.0
Upstream Kubernetes Version 1.25
Docker 已安装在客户端机器上
Kubernetes 集群可以访问的 Docker 仓库
RAPIDS Accelerator
请参阅附录以获取访问权限
NGC API 密钥
本指南利用 Cloud Native Stack (CNS) GitHub 安装指南来构建 Kubernetes 集群。要在没有 CNS 的情况下安装,请利用 安装 Kubernetes 的说明来创建具有 NVIDIA GPU 支持的 Kubernetes 集群。
Docker 镜像准备#
在安装了 Docker 的客户端机器上,下载以下软件包和脚本,如下所示。将使用 3.4 版本 Apache Spark。请注意,加速器目前仅支持 Scala 2.12 版本。
以下是用于安装 Apache Spark 的本地副本并配置 docker 镜像的 bash 命令
1mkdir -p ~/spark-rapids/spark
2wget https://archive.apache.org/dist/spark/spark-3.4.0/spark-3.4.0-bin-hadoop3.tgz
3tar -zxvf spark-3.4.0-bin-hadoop3.tgz -C ./spark-rapids/spark --strip-components 1
1cd ~/spark-rapids
将 .jar 复制到当前工作目录中。请参阅访问 NVIDIA AI Enterprise RAPIDS Accelerator 部分以拉取 .jar 文件。
下面提供了一个示例 Dockerfile
1# Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://apache.ac.cn/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15
16FROM nvidia/cuda:12.2.2-devel-ubuntu22.04
17ARG spark_uid=185
18
19# https://forums.developer.nvidia.com/t/notice-cuda-linux-repository-key-rotation/212771
20RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/3bf863cc.pub
21
22# Install tini and java dependencies
23RUN apt-get update && apt-get install -y --no-install-recommends tini openjdk-8-jdk openjdk-8-jre
24ENV JAVA_HOME /usr/lib/jvm/java-1.8.0-openjdk-amd64
25ENV PATH $PATH:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/bin:/usr/lib/jvm/java-1.8.0-openjdk-amd64/bin
26
27# Before building the docker image, first either download Apache Spark 3.1+ from
28# http://spark.apache.ac.cn/downloads.html or build and make a Spark distribution following the
29# instructions in http://spark.apache.ac.cn/docs/3.1.2/building-spark.html (see
30# https://nvidia.github.io/spark-rapids/docs/download.html for other supported versions). If this
31# docker file is being used in the context of building your images from a Spark distribution, the
32# docker build command should be invoked from the top level directory of the Spark
33# distribution. E.g.: docker build -t spark:3.1.2 -f kubernetes/dockerfiles/spark/Dockerfile .
34
35RUN set -ex && \
36 ln -s /lib /lib64 && \
37 mkdir -p /opt/spark/work-dir && \
38 touch /opt/spark/RELEASE && \
39 rm /bin/sh && \
40 ln -sv /bin/bash /bin/sh && \
41 echo "auth required pam_wheel.so use_uid" >> /etc/pam.d/su && \
42 chgrp root /etc/passwd && chmod ug+rw /etc/passwd
43
44COPY spark /opt/spark
45COPY spark/kubernetes/dockerfiles/spark/entrypoint.sh /opt/
46COPY spark/kubernetes/tests /opt/spark/tests
47
48COPY rapids-4-spark_2.12-*.jar /opt/spark/jars
49
50RUN apt-get update && \
51 apt-get install -y python-is-python3 python3-pip && \
52 pip install --upgrade pip setuptools && \
53 # You may install with python3 packages by using pip3.6
54 # Removed the .cache to save space
55 rm -r /root/.cache && rm -rf /var/cache/apt/*
56
57ENV SPARK_HOME /opt/spark
58
59WORKDIR /opt/spark/work-dir
60RUN chmod g+w /opt/spark/work-dir
61
62ENTRYPOINT [ "/opt/entrypoint.sh" ]
63
64# Specify the User that the actual main process will run as
65USER ${spark_uid}
假设存在以下目录结构
$ ls ~/spark-rapids
Dockerfile rapids-4-spark_2.12-23.08.1.jar spark
构建 Dockerfile 并推送到 NGC(可选)
1export IMAGE_NAME=nvcr.io/<your-registry-name>/<container-name>:<tag>
2docker build . -f Dockerfile -t $IMAGE_NAME
3docker push $IMAGE_NAME
docker push $IMAGE_NAME
注意
推送到 NGC 是可选的。请参阅 NGC Private Registry User Guide 以进行设置
从 NGC 拉取 Docker 镜像到 Kubernetes#
通过在以下命令中填写 <ngc-secret-token> 和 <email>,更新 NGC 的 Kubernetes 凭据
kubectl create secret docker-registry ngc-secret --docker-server="nvcr.io/nv-nvaie-tme" --docker-username='$oauthtoken' --docker-password='<ngc-secret-token>' --docker-email='<email>'
注意
如果 Kubernetes 配置中已经存在同名的 secret,则创建 secret 将不起作用。请参阅生成您的 NGC API 密钥
重要
这是身份验证所必需的。请注意,secret 的名称是 ngc-secret,它将在 spark.kubernetes.container.image.pullSecrets 中使用。
在 Kubernetes 集群中运行 Spark 应用程序#
当 CNS 创建集群时,默认启用基于角色的访问控制 (RBAC)。请按照 http://spark.apache.ac.cn/docs/latest/running-on-kubernetes.html#rbac 中的步骤创建一个服务帐户以拉取受保护的镜像。以下是相关命令
kubectl create serviceaccount spark
kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=default:spark --namespace=default
相应地,在 spark-submit 中添加了一个额外的参数
--conf spark.kubernetes.authenticate.driver.serviceAccountName=spark
提交一个简单的测试作业#
这个简单的作业将测试是否可以找到 RAPIDS 插件。
这是一个 spark-submit 作业的示例
1export SPARK_HOME=~/spark-rapids/spark
2export K8SMASTER=k8s://<ip>:<port>
3export SPARK_NAMESPACE=default
4export SPARK_DRIVER_NAME=exampledriver
5export NGC_SECRET_NAME=ngc-secret
6
7$SPARK_HOME/bin/spark-submit \
8 --master $K8SMASTER \
9 --deploy-mode cluster \
10 --name examplejob \
11 --class org.apache.spark.examples.SparkPi \
12 --driver-memory 2G \
13 --conf spark.executor.instances=1 \
14 --conf spark.executor.memory=4G \
15 --conf spark.executor.cores=1 \
16 --conf spark.executor.resource.gpu.amount=1 \
17 --conf spark.executor.resource.gpu.discoveryScript=/opt/spark/examples/src/main/scripts/getGpusResources.sh \
18 --conf spark.executor.resource.gpu.vendor=nvidia.com \
19 --conf spark.plugins=com.nvidia.spark.SQLPlugin \
20 --conf spark.kubernetes.namespace=$SPARK_NAMESPACE \
21 --conf spark.kubernetes.driver.pod.name=$SPARK_DRIVER_NAME \
22 --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
23 --conf spark.kubernetes.container.image=$IMAGE_NAME \
24 --conf spark.kubernetes.container.image.pullSecrets=$NGC_SECRET_NAME \
25 --conf spark.kubernetes.container.image.pullPolicy=Always \
26 local:///opt/spark/examples/jars/spark-examples_2.12-3.4.0.jar 10000
spark-submit 末尾的 10000 是一个输入,用于指定迭代次数。注意 local://
表示 jar 文件位置在 Docker 镜像内部。由于这是 cluster
模式,Spark 驱动程序在 Kubernetes 的 pod 中运行。作业运行时可以看到驱动程序和执行器 pod
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
spark-pi-d11075782f399fd7-exec-1 1/1 Running 0 9s
exampledriver 1/1 Running 0 15s
要查看 Spark 驱动程序日志,请使用以下命令
kubectl logs $SPARK_DRIVER_NAME
如果作业成功运行,则日志输出将包含计算出的 pi 值
Pi 大约是 3.1406957034785172
注意
Exception in thread "main" java.lang.ClassNotFoundException: com.nvidia.spark.SQLPlugin
如果 Spark 驱动程序找不到 RAPIDS Accelerator jar,ClassNotFoundException 是一个常见的错误,会导致如下异常
要在作业运行时查看 Spark 驱动程序 UI,请首先公开驱动程序 UI 端口
kubectl port-forward $SPARK_DRIVER_NAME 4040:4040
注意
您可能需要启用带有端口转发的 ssh 以从远程计算机访问 UI。例如,run ssh -L 4040:localhost:4040 nvidia@<cluster-ip>
然后在公开的端口上打开 Web 浏览器访问 Spark 驱动程序 UI 页面
http://127.0.0.1:4040
要终止 Spark 作业
$SPARK_HOME/bin/spark-submit --kill spark:$SPARK_DRIVER_NAME
要删除驱动程序 pod
kubectl delete pod $SPARK_DRIVER_NAME
需要删除驱动程序 pod 才能重用相同的驱动程序 pod 名称。