Kubernetes 上运行 Spark 和 OzoneFS

本页介绍如何通过以下组件在 Spark 中使用 Ozone 对象存储:

  • OzoneFS (兼容 Hadoop 的文件系统)
  • Hadoop 2.7 (包含在 Spark 发行包中)
  • Kubernetes 的 Spark 调度器
  • 本地 Spark 客户端

准备

下载 Spark 和 Ozone 的最新发行包并解压,本方法使用 spark-2.4.6-bin-hadoop2.7 进行了测试。

你还需要准备以下内容:

  • 用来上传下载 spark+ozone 镜像的仓库(本文档中使用 Docker Hub)
  • 自定义镜像的名称,形如 repo/name(本文档中使用 myrepo/ozone-spark
  • 专门的 Kubernetes 命名空间(本文档中使用 yournamespace

为 driver 创建 docker 镜像

创建 Spark driver/executor 基础镜像

首先使用 Spark 的镜像创建工具创建一个镜像。 在 Spark 发行包中运行以下命令:

./bin/docker-image-tool.sh -r myrepo -t 2.4.6 build

注意: 如果你使用 Minikube,需要加上 -m 参数来使用 Minikube 镜像的 docker 进程。

./bin/docker-image-tool.sh -m -r myrepo -t 2.4.6 build

./bin/docker-image-tool.sh 是 Spark 用来创建镜像的官方工具,上面的步骤会创建多个名为 myrepo/spark 的 Spark 镜像,其中的第一个镜像用作接下来步骤的基础镜像。

定制镜像

创建一个用于定制镜像的目录。

从集群中拷贝 ozone-site.xml

kubectl cp om-0:/opt/hadoop/etc/hadoop/ozone-site.xml .

从 Ozone 目录中拷贝 ozonefs.jar使用 hadoop2 版本!

<configuration>
    <property>
        <name>fs.AbstractFileSystem.o3fs.impl</name>
        <value>org.apache.hadoop.fs.ozone.OzFs</value>
     </property>
</configuration>

kubectl cp om-0:/opt/hadoop/share/ozone/lib/hadoop-ozone-filesystem-hadoop2-VERSION.jar hadoop-ozone-filesystem-hadoop2.jar



编写新的 Dockerfile 并构建镜像:

FROM myrepo/spark:2.4.6 ADD core-site.xml /opt/hadoop/conf/core-site.xml ADD ozone-site.xml /opt/hadoop/conf/ozone-site.xml ENV HADOOP_CONF_DIR=/opt/hadoop/conf ENV SPARK_EXTRA_CLASSPATH=/opt/hadoop/conf ADD hadoop-ozone-filesystem-hadoop2.jar /opt/hadoop-ozone-filesystem-hadoop2.jar


```bash
docker build -t myrepo/spark-ozone

对于远程的 Kubernetes 集群,你可能需要推送镜像:

docker push myrepo/spark-ozone

创建桶并获取 OzoneFS 路径

下载任意文本文件并保存为 /tmp/alice.txt

kubectl port-forward s3g-0 9878:9878
aws s3api --endpoint http://localhost:9878 create-bucket --bucket=test
aws s3api --endpoint http://localhost:9878 put-object --bucket test --key alice.txt --body /tmp/alice.txt

记下 Ozone 文件系统的 URI,在接下来的 spark-submit 命令中会用到它。

创建服务账号

kubectl create serviceaccount spark -n yournamespace
kubectl create clusterrolebinding spark-role --clusterrole=edit --serviceaccount=yournamespace:spark --namespace=yournamespace

运行任务

运行如下的 spark-submit 命令,但需要对下列的值进行修改:

  • kubernetes master url(你可以查看 ~/.kube/config 来获取实际值)
  • kubernetes namespace(本例中为 yournamespace
  • serviceAccountName (如果你按照上面的步骤做了,使用 spark 即可)
  • container.image (在本例中该值为 myrepo/spark-ozone,在上一步中这个镜像被推送至镜像仓库)
  • 输入文件的位置(o3fs://…),使用上面 ozone s3 path <桶名> 命令输出中的字符串即可)
bin/spark-submit \
    --master k8s://https://kubernetes:6443 \
    --deploy-mode cluster \
    --name spark-word-count \
    --class org.apache.spark.examples.JavaWordCount \
    --conf spark.executor.instances=1 \
    --conf spark.kubernetes.namespace=yournamespace \
    --conf spark.kubernetes.authenticate.driver.serviceAccountName=spark \
    --conf spark.kubernetes.container.image=myrepo/spark-ozone \
    --conf spark.kubernetes.container.image.pullPolicy=Always \
    --jars /opt/hadoop-ozone-filesystem-hadoop2.jar \
    local:///opt/spark/examples/jars/spark-examples_2.11-2.4.0.jar \
    o3fs://test.s3v.ozone-om-0.ozone-om:9862/alice.txt

使用 kubectl get pod 命令查看可用的 spark-word-count-... pod。

使用 kubectl logs spark-word-count-1549973913699-driver 命令查看计算结果。

输出的结果类似如下:

...
name: 8
William: 3
this,': 1
SOUP!': 1
`Silence: 1
`Mine: 1
ordered.: 1
considering: 3
muttering: 3
candle: 2
...