flink on k8s 目前有两种模式:
- Kubernetes:用户通过
定义 flink 的 k8s 资源描述文件
,由kubectl
命令启动,最终以 standalone session cluster 或 standalone job cluster 模式运行。其中 standalone session cluster 运行多个作业;standalone job cluster 只运行一个作业。 - Native Kubernetes:用户通过
flink run
命令直接提交作业,由 flink 客户端(内置 k8s client)将集群资源描述信息(包括ConfigMap(例如 HADOOP_CONF) 描述等)提交到 k8s ApiServer,从而启动 flink 集群并运行 flink 作业。具体原理查看第 6 节。
flink-1.11 新增了 k8s job cluster 和 native k8s Application 模式。本文只介绍 native k8s session 和 native k8s application 模式。
1.环境需求
- Kubernetes 版本 >= 1.9
- 用户需要有在 k8s 集群上的相关权限(list/create/delete pods/delete services),需要准备好 KubeConfig 文件,默认会使用( ~/.kube/config,也可以在运行时通过
kubernetes.config.file
指定). 可以运行kubectl auth can-i <list|create|edit|delete> pods
来测试当前用户是否有相关权限。 - 配置好 Kubernetes DNS 服务 (最好测试一下域名解析能否成功)
- 准备好 k8s 用户账号,并配置好 RBAC 权限(create, delete pods). flink 镜像默认是以 flink 账号运行 flink 程序的
- 准备 flink 集群的 image 镜像:可以使用官方镜像,也可以自己打镜像
- flink-1.11 客户端
- hadoop conf 文件(可选, 访问 HDFS 文件系统时需要)
2.Flink Kubernetes Session
2.1 启动 Flink Session
注意
:要确保 flink-conf.yaml
中的 env.java.home
配置被注释,否则无法启动成功!
# env.java.home: /usr/local/java
先在 k8s 上启动 Flink Session
# -Dkubernetes.container.image=localhost:5000/flink:1.11.1-scala_2.11 指定镜像,如果不指定该配置,会使用默认配置的官方镜像(flink:latest)
# -Dkubernetes.jobmanager.service-account=flink 指定有 k8s 权限的账号,jobmanager 用该账号为 taskmanager 申请 k8s 的 pod
./bin/kubernetes-session.sh -Dkubernetes.container.image=localhost:5000/flink:1.11.1-scala_2.11 -Dkubernetes.jobmanager.service-account=flink
可以根据需要添加配置,flink on k8s 的所有相关配置在这里.
例如:启动一个有 2 个 cpu 核心,4GB 内存的 TaskManager
./bin/kubernetes-session.sh \
-Dkubernetes.cluster-id=<ClusterId> \
-Dtaskmanager.memory.process.size=4096m \
-Dkubernetes.taskmanager.cpu=2 \
-Dtaskmanager.numberOfTaskSlots=4 \
-Dkubernetes.container.image=localhost:5000/flink:1.11.1-scala_2.11 \
-Dkubernetes.service.exposed.type=NodePort
其余配置则使用 conf/flink-conf.yaml 中的配置,所有配置在这里
如果没有指定 kubernetes.cluster-id
, flink 客户端会随机生成一个 UUID。
2.2 向 Flink Session 提交作业
通过 -e kubernetes-session
指定部署到之前启动的 k8s 集群,并且可以通过 -D 指定参数
./bin/flink run -d -e kubernetes-session -Dkubernetes.jobmanager.service-account=flink -Dkubernetes.cluster-id=<ClusterId> examples/streaming/WindowJoin.jar
2.3 访问 Job Manager UI 界面
这里涉及 k8s 相关概念,由于 k8s 有自己的 ‘防火墙’,用户需要定义组件的端口暴露规则,将端口映射到宿主机,k8s 目前提供了 4 种端口映射方式:
- ClusterIP:组件 ip 和端口只能在 k8s 集群内访问。如果你想访问 jobmanager ui 或者向该 session 集群提交任务,需要启动一个本地代理:
kubectl port-forward service/<ServiceName> 8081
- NodePort:静态端口,通过宿主机
<NodeIP>:<NodePort>
就可以直接访问 jobmanager UI。NodeIP 可以用 Kubernetes ApiServer 替换。作业提交成功后,<NodeIP>:<NodePort>
可以在提交 job 的客户端日志中找到。 - LoadBalancer:使用云提供商的负载均衡器在外部暴露服务。 由于云提供商和 Kubernetes 需要一些时间来准备负载均衡器,因为你可能在客户端日志中获得一个 NodePort 的 JobManager Web 界面。 你可以使用
kubectl get services/<ClusterId>
获取 EXTERNAL-IP, 然后手动构建负载均衡器 JobManager Web 界面 http://:8081 - ExternalName:映射服务到一个 DNS 域名,当前 flink 版本还不支持
通常在自建 k8s 集群情况下,我们直接使用 NodePort 模式就可以了。
2.4 连接 k8s session
可以使用以下命令连接启动的 k8s session
./bin/kubernetes-session.sh -Dkubernetes.cluster-id=<ClusterId> -Dexecution.attached=true
2.5 停止 flink k8s Session
echo 'stop' | ./bin/kubernetes-session.sh -Dkubernetes.cluster-id=<ClusterId> -Dexecution.attached=true
2.6 资源清理
依赖 k8s 机制进行清理,删除 k8s 服务即可回收所有占用的 k8s 资源(当然服务也停了)
kubectl delete service/<ClusterID>