Kubernetes上的Zeppelin
Zeppelin 可以在由 Kubernetes 管理的集群上运行。当 Zeppelin 在 Pod 中运行时,它会为每个解释器创建 pod。此外,Spark 解释器会自动配置为在 Kubernetes 上以客户端模式使用 Spark。
主要优势是
- 解释器扩展
- Spark 解释器自动在 Kubernetes 上配置 Spark
- 能够自定义Kubernetes yaml文件
- Spark UI 访问
先决条件
- Zeppelin >= 0.9.0 的 Docker 镜像
- Spark >= 2.4.0 的 Docker 镜像(如果使用 Spark 解释器)
- 一个正在运行的Kubernetes集群,并使用kubectl配置了访问权限
- Kubernetes DNS 已在您的集群中配置
您的Kubernetes集群中有足够的CPU和内存。我们建议使用4个CPU和6GB内存,以便能够启动带有少量执行器的Spark解释器。
如果您正在使用minikube,请检查您的集群容量(
kubectl describe node),并在必要时增加容量$ minikube delete # otherwise configuration won't apply $ minikube config set cpus <number> $ minikube config set memory <number in MB> $ minikube start $ minikube config view
快速开始
首先,我们从GitHub克隆Zeppelin仓库:
git clone https://github.com/apache/zeppelin.git
cd zeppelin
# you can check out to your desired version/branch
# git checkout tags/v0.10.1
# just make sure you check the version inside "./pom.xml"
现在我们将创建zeppelin-distribution镜像。这可能需要一些时间,并且此镜像将用作即将需要的镜像的基础:
docker build -t zeppelin-distribution:latest -f ./Dockerfile .
接下来,我们将构建我们的 zeppelin-server 镜像:
cd scripts/docker/zeppelin-server
# Looking at the "./pom.xml" we can see the version is 0.11.2
# Let's set the correct version in our Dockerfile:
# vi Dockerfile
# ARG version="0.11.2"
# Once you saved the Dockerfile with the correct version we can build our image:
docker build -t zeppelin-server:0.11.2 -f ./Dockerfile .
我们构建的最后一个镜像是 zeppelin-interpreter:
cd scripts/docker/zeppelin-interpreter
docker build -t zeppelin-interpreter:0.11.2 -f ./Dockerfile .
所以我们现在应该有以下图片:
# sudo if you are on Linux and Docker requires root
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
zeppelin-interpreter 0.11.2 4f77fe989eed 3 minutes ago 622MB
zeppelin-server 0.11.2 4f77fe989eed 3 minutes ago 622MB
zeppelin-distribution latest bd2fb4b321d2 40 minutes ago 1.27GB
提醒:请调整zeppelin-server.yaml的YAML文件中的图像。
在Kubernetes集群上启动Zeppelin,
kubectl apply -f zeppelin-server.yaml
端口转发 Zeppelin 服务器端口,
kubectl port-forward zeppelin-server 8080:80
并浏览 localhost:8080。
尝试运行一些段落,看看每个解释器是否作为 Pod 运行(使用 kubectl get pods),而不是本地进程。
要关闭,
kubectl delete -f zeppelin-server.yaml
Spark 解释器
构建Spark Docker镜像以使用Spark解释器。 下载Spark二进制发行版并运行以下命令。 需要Spark 2.4.0或更高版本。
# if you're using minikube, set docker-env
$ eval $(minikube docker-env)
# build docker image
$ <spark-distribution>/bin/docker-image-tool.sh -m -t 2.4.0 build
运行 docker images 并检查是否创建了 spark:2.4.0。
在 zeppelin-server.yaml 中配置 zeppelin-server-conf ConfigMap 的 sparkContainerImage。
创建笔记并配置执行器数量(默认1)
%spark.conf
spark.executor.instances 5
然后启动你的spark解释器
%spark
sc.parallelize(1 to 100).count
...
当SparkInterpreter的spark.master属性以k8s://开头时(默认情况下,当Zeppelin使用zeppelin-server.yaml启动时为k8s://https://kubernetes.default.svc),Spark执行器将自动在您的Kubernetes集群中创建。
通过点击段落上的SPARK JOB可以访问Spark UI。
查看这里了解更多关于在Kubernetes上运行Spark的信息。
手动构建Zeppelin镜像
要构建您自己的Zeppelin镜像,首先使用-Pbuild-distr标志构建Zeppelin项目。
$ ./mvnw package -DskipTests -Pbuild-distr <your flags>
二进制包将在zeppelin-distribution/target目录下创建。将创建的包文件移动到scripts/docker/zeppelin/bin/目录下。
$ mv zeppelin-distribution/target/zeppelin-*.tar.gz scripts/docker/zeppelin/bin/
scripts/docker/zeppelin/bin/Dockerfile 从互联网下载包。修改文件以从文件系统添加包。
...
# Find following section and comment out
#RUN echo "$LOG_TAG Download Zeppelin binary" && \
# wget -O /tmp/zeppelin-${Z_VERSION}-bin-all.tgz http://archive.apache.org/dist/zeppelin/zeppelin-${Z_VERSION}/zeppelin-${Z_VERSION}-bin-all.tgz && \
# tar -zxvf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
# rm -rf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
# mv /zeppelin-${Z_VERSION}-bin-all ${ZEPPELIN_HOME}
# Add following lines right after the commented line above
ADD zeppelin-${Z_VERSION}.tar.gz /
RUN ln -s /zeppelin-${Z_VERSION} /zeppelin
...
然后构建docker镜像。
# configure docker env, if you're using minikube
$ eval $(minikube docker-env)
# change directory
$ cd scripts/docker/zeppelin/bin/
# build image. Replace <tag>.
$ docker build -t <tag> .
最后,将刚刚创建的自定义镜像设置为image,并在zeppelin-server.yaml文件中的zeppelin-server容器规范中设置ZEPPELIN_K8S_CONTAINER_IMAGE环境变量。
目前,Zeppelin服务器和解释器pod中都在使用单个docker镜像。因此,
| Pod | 实例数量 | 镜像 | 备注 |
|---|---|---|---|
| Zeppelin 服务器 | 1 | Zeppelin docker 镜像 | 用户使用 kubectl 命令创建/删除 |
| Zeppelin 解释器 | n | Zeppelin docker 镜像 | Zeppelin 服务器创建/删除 |
| Spark执行器 | m | Spark Docker镜像 | Spark解释器创建/删除 |
目前,Zeppelin docker 镜像的大小相当大。Zeppelin 项目计划在未来为每个单独的解释器提供轻量级镜像。
它是如何工作的
Kubernetes上的Zeppelin
k8s/zeppelin-server.yaml 提供了运行 Zeppelin Server 的少量 sidecar 和配置。
一旦 Zeppelin Server 在 Kubernetes 中启动,它会自动配置自己以使用 K8sStandardInterpreterLauncher。
启动器使用位于k8s/interpreter/目录下的模板在Pod中创建每个解释器。
目录中的模板按字母顺序应用。模板由jinjava渲染,
并且所有解释器属性都可以在模板内部访问。
Spark 在 Kubernetes 上
当解释器组是spark时,Zeppelin会自动设置必要的Spark配置以在Kubernetes上使用Spark。
它使用客户端模式,因此Spark解释器Pod作为Spark驱动程序工作,Spark执行器在单独的Pod中启动。
可以通过手动设置Spark解释器的spark.master属性来覆盖此自动配置。
访问Spark UI(或在解释器Pod中运行的服务)
Zeppelin 服务器 Pod 有一个反向代理作为边车,它将流量分配到 Zeppelin 服务器和运行在其他 Pod 中的 Spark UI。
它假设 和 *. 都指向 nginx 代理地址。
被定向到 ZeppelinServer,*. 被定向到解释器 Pods。
是访问在解释器 Pod 中运行的任何应用程序的约定。
例如,当您的服务域名为 local.zeppelin-project.org 时,Spark 解释器 Pod 正在以名称 spark-axefeg 运行,并且 Spark UI 正在端口 4040 上运行,
4040-spark-axefeg.local.zeppelin-project.org
是访问Spark UI的地址。
默认服务域是 local.zeppelin-project.org:8080。local.zeppelin-project.org 和 *.local.zeppelin-project.org 配置为解析 127.0.0.1。
它允许使用 kubectl port-forward zeppelin-server 8080:80 访问 Zeppelin 和 Spark UI。
如果您喜欢使用您的自定义域名
- 在Kubernetes集群中为
k8s/zeppelin-server.yaml中定义的zeppelin-server服务的http端口配置Ingress。 - 配置DNS记录,使您的服务域名和通配符子域名指向您的Ingress的IP地址。
- 修改
k8s/zeppelin-server.yaml文件中的zeppelin-server-confConfigMap的serviceDomain。 - 应用更改(例如
kubectl apply -f k8s/zeppelin-server.yaml)
持久化 /notebook 和 /conf 目录
默认情况下,Notebook 和配置不会被持久化。请配置卷并更新 k8s/zeppelin-server.yaml 以在必要时使用卷来持久化 /notebook 和 /conf 目录。
自定义
Zeppelin 服务器 Pod
编辑 k8s/zeppelin-server.yaml 并应用。
解释器 Pod
由于解释器 Pod 是由 ZeppelinServer 使用 k8s/interpreter 目录下的模板创建/删除的,要进行自定义,
- 准备
k8s/interpreter目录并进行自定义(编辑或创建新的yaml文件),在Kubernetes卷中。 - 修改
k8s/zeppelin-server.yaml并将准备好的卷目录k8s/interpreter挂载到/zeppelin/k8s/interpreter/。 - 应用修改后的
k8s/zeppelin-server.yaml。 - 运行一个段落将使用修改后的yaml文件创建一个解释器。
解释器pod也可以通过解释器设置进行自定义。以下是一些属性:
| 属性名称 | 默认值 | 描述 |
|---|---|---|
zeppelin.k8s.interpreter.namespace |
default |
指定当前解释器的命名空间。用户可以为不同的解释器设置不同的命名空间。为了最小化权限,默认情况下解释器pod只能在default命名空间中创建。如果用户需要在其他命名空间中创建解释器pod,则需要在k8s/zeppelin-server.yaml中添加相应的rolebinding。 |
zeppelin.k8s.interpreter.serviceAccount |
default |
使用的Kubernetes服务账户。 |
zeppelin.k8s.interpreter.container.image |
apache/zeppelin: |
要使用的解释器镜像。 |
zeppelin.k8s.interpreter.cores |
(可选) | 使用的CPU核心数量。 |
zeppelin.k8s.interpreter.memory |
(可选) | 使用的内存,例如 1g。 |
zeppelin.k8s.interpreter.gpu.type |
(可选) | 设置当解释器pod需要调度gpu资源时请求的gpu类型,例如 nvidia.com/gpu。 |
zeppelin.k8s.interpreter.gpu.nums |
(可选) | 使用的GPU数量。 |
zeppelin.k8s.interpreter.imagePullSecrets |
(可选) | 设置拉取镜像时使用的Kubernetes密钥列表,以逗号分隔,例如 mysecret1,mysecret2 |
zeppelin.k8s.interpreter.container.imagePullPolicy |
(可选) | 设置解释器镜像的拉取策略,例如 Always |
zeppelin.k8s.spark.container.imagePullPolicy |
(可选) | 设置spark镜像的拉取策略,例如 Always |
zeppelin.spark.uiWebUrl |
//-. |
用户访问Spark UI的URL。默认值是一个包含三个变量的jinjava模板。 |
zeppelin.k8s.spark.useIngress |
(可选) | 如果为true,则在创建spark解释器时将创建Ingress。因此,用户可以通过Ingress访问Spark UI。 |
zeppelin.k8s.spark.ingress.host |
-. |
如果 zeppelin.k8s.spark.useIngress 是 true,则配置 Ingress 的 host 值。默认值是一个包含三个变量的 jinjava 模板。用户可以通过自定义的 zeppelin.k8s.spark.ingress.host 访问 Spark UI。 |
未来工作
- 更小的解释器 Docker 镜像。
- 阻止解释器 Pod 之间的通信。
- Spark Interpreter Pod 对同一命名空间中的任何 pod/service 具有 Role CRUD 权限。这应该仅限于 Spark executors Pod。
- 当Zeppelin在Kubernetes上运行时,默认情况下为每个笔记解释器模式
开发
在开发过程中,不必每次都构建Zeppelin的发行包和Docker镜像,Zeppelin可以在本地运行(例如在IDE的调试模式下),并且能够通过配置以下环境变量来使用K8sStandardInterpreterLauncher运行解释器。
| 环境变量 | 值 | 描述 |
|---|---|---|
ZEPPELIN_RUN_MODE |
k8s |
使Zeppelin在Kubernetes上运行解释器 |
ZEPPELIN_K8S_PORTFORWARD |
true |
启用从本地Zeppelin实例到在Kubernetes上运行的Interpreters的端口转发 |
ZEPPELIN_K8S_CONTAINER_IMAGE |
|
使用的Zeppelin解释器docker镜像 |
ZEPPELIN_K8S_SPARK_CONTAINER_IMAGE |
|
使用的Spark docker镜像 |
ZEPPELIN_K8S_NAMESPACE |
|
要使用的Kubernetes命名空间 |
KUBERNETES_AUTH_TOKEN |
|
用于创建资源的Kubernetes认证令牌 |