本文基于 Flink-1.13 介紹 Flink on Kubernetes 的部署模式,重點講述 Session 和 Native Session 模式。
1.Flink on Kubernetes 的背景
Kubernetes 簡介:
Kubernetes 項目來源于 Google 內部 Borg 項目,于 2014 年發布到開源社區。Kubernetes 已經成長為容器管理領域的事實標準。在大數據相關領域,包括 Spark、Hive、Kafka 等項目正在遷移到 Kubernetes。
Flink 選擇 Kubernetes 的主要原因是結合 Flink 和 Kubernetes 的長穩性。
① Flink 特性:提供的實時服務是需要長時間、穩定地運行,常應用于電信網絡質量監控、實時風控、實時推薦等穩定性要求較高的場景;
② Kubernetes 優勢:為應用提供了部署、管理能力,同時保證其穩定運行。Kubernetes 具有很好的生態,可以集成各種運維工具,例如 prometheus、主流日志采集工具等。Kubernetes 具有很好的擴縮容機制,可以大大提高資源利用率。
2.Flink Session 和 Application 模式
2.1 Session 模式
Session 模式簡介
預先構建 Flink 集群,且該集群長期處于運行狀態,但不能自動擴縮容。用戶通過 client 提交作業到運行中的 JobManager,而 JobManager 將任務分配到運行中的 TaskManager。
優點:
Flink 集群是預先啟動運行的。用戶提交作業的時候,作業可以立即分配到 TaskManager,即作業啟動速度快。
缺點:
① 資源利用率低,提前確定 TaskManager 數量,如果作業需要的資源少,則大量 TaskManager 處于閑置狀態。反正 TaskManager 資源不足。
② 作業隔離性差,多個作業的任務存在資源競爭,相互影響。如果一個作業異常導致 TaskManager 掛了,該 TaskManager 上的全部作業都會被重啟。
部署指導
參考:Flink on Standalone Kubernetes Reference
① 集群配置
集群配置通過 configmap 掛載到容器中
flink-configuration-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: flink-config
labels:
app: flink
data:
flink-conf.yaml: |+
jobmanager.rpc.address: flink-jobmanager
taskmanager.numberOfTaskSlots: 1
blob.server.port: 6124
jobmanager.rpc.port: 6123
taskmanager.rpc.port: 6122
jobmanager.heap.size: 1024m
taskmanager.memory.process.size: 1024m
log4j.properties: |+
log4j.rootLogger=INFO, file
log4j.logger.akka=INFO
log4j.logger.org.apache.kafka=INFO
log4j.logger.org.apache.hadoop=INFO
log4j.logger.org.apache.zookeeper=INFO
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.file=${log.file}
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
log4j.logger.org.apache.flink.shaded.akka.org.jboss.netty.channel.DefaultChannelPipeline=ERROR, file
② Deployment 文件
把 Flink 鏡像上傳到私有鏡像倉。編輯 jobmanager-service.yaml、jobmanager-deployment.yaml、taskmanager-deployment.yaml
jobmanager-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: flink-jobmanager
spec:
replicas: 1
selector:
matchLabels:
app: flink
component: jobmanager
template:
metadata:
labels:
app: flink
component: jobmanager
spec:
containers:
- name: jobmanager
image: flink:latest
workingDir: /opt/flink
command: ["/bin/bash", "-c", "$FLINK_HOME/bin/jobmanager.sh start;\
while :;
do
if [[ -f $(find log -name '*jobmanager*.log' -print -quit) ]];
then tail -f -n +1 log/*jobmanager*.log;
fi;
done"]
ports:
- containerPort: 6123
name: rpc
- containerPort: 6124
name: blob
- containerPort: 8081
name: ui
livenessProbe:
tcpSocket:
port: 6123
initialDelaySeconds: 30
periodSeconds: 60
volumeMounts:
- name: flink-config-volume
mountPath: /opt/flink/conf
securityContext:
runAsUser: 9999 # refers to user _flink_ from official flink image, change if necessary
volumes:
- name: flink-config-volume
configMap:
name: flink-config
items:
- key: flink-conf.yaml
path: flink-conf.yaml
- key: log4j.properties
path: log4j.properties
taskmanager-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: flink-taskmanager
spec:
replicas: 2
selector:
matchLabels:
app: flink
component: taskmanager
template:
metadata:
labels:
app: flink
component: taskmanager
spec:
containers:
- name: taskmanager
image: flink:latest
workingDir: /opt/flink
command: ["/bin/bash", "-c", "$FLINK_HOME/bin/taskmanager.sh start; \
while :;
do
if [[ -f $(find log -name '*taskmanager*.log' -print -quit) ]];
then tail -f -n +1 log/*taskmanager*.log;
fi;
done"]
ports:
- containerPort: 6122
name: rpc
livenessProbe:
tcpSocket:
port: 6122
initialDelaySeconds: 30
periodSeconds: 60
volumeMounts:
- name: flink-config-volume
mountPath: /opt/flink/conf/
securityContext:
runAsUser: 9999 # refers to user _flink_ from official flink image, change if necessary
volumes:
- name: flink-config-volume
configMap:
name: flink-config
items:
- key: flink-conf.yaml
path: flink-conf.yaml
- key: log4j.properties
path: log4j.properties
jobmanager-service.yaml
apiVersion: v1
kind: Service
metadata:
name: flink-jobmanager
spec:
type: ClusterIP
ports:
- name: rpc
port: 6123
- name: blob
port: 6124
- name: ui
port: 8081
selector:
app: flink
component: jobmanager
③ 執行 yaml
通過 kubectl create -f 命令創建 Flink 集群
kubectl create -f flink-configuration-configmap.yaml
kubectl create -f jobmanager-service.yaml
kubectl create -f jobmanager-deployment.yaml
kubectl create -f taskmanager-deployment.yaml
2.2 Application 模式
Application 模式簡介
每個作業獨占一個 Flink 集群,當作業完成后,集群也會被回收。
注意:
① Flink 鏡像需要包含作業即Application 依賴的 Class
② 啟動作業的時候需要指定 Main 函數入口類
優點:
一個作業獨占一個集群,作業的隔離性好。
缺點:
資源利用率低,提前確定 TaskManager 數量,如果作業需要的資源少,則大量 TaskManager 處于閑置狀態。反之 TaskManager 資源不足。同時,JobManager 不能復用。
3.Flink Native Session 模式
3.1 Native Session 模式簡介
類似 Session 模式,需要預先構建 JobManager。不同點是用戶通過 Flink Client 向 JobManager 提交作業后,根據作業需要的 Slot 數量,JobManager 直接向 Kubernetes 申請 TaskManager 資源,最后把作業提交到 TaskManager 上。
3.2 優缺點分析
優點:
TaskManager 的資源是實時的、按需進行的創建,對資源的利用率更高。
缺點:
作業真正運行起來的時間較長,因為需要等待 TaskManager 創建。
3.3 部署指導
① 集群配置
集群配置通過 configmap 掛載到容器中,如上 2.1 所示。
新增如下配置:
flink-configuration-configmap.yaml
kubernetes.cluster-id: my-first-flink-cluster
execution.attached: true
② 配置 jobmanager-deployment.yaml
如上 2.1 所示,需要把啟動腳本修改為 ./bin/kubernetes-session.sh
jobmanager-deployment.yaml
// 忽略...
spec:
containers:
- name: jobmanager
image: flink:latest
workingDir: /opt/flink
command: ["/bin/bash", "-c", "$FLINK_HOME/bin/kubernetes-session.sh;\
while :;
do
if [[ -f $(find log -name '*jobmanager*.log' -print -quit) ]];
then tail -f -n +1 log/*jobmanager*.log;
fi;
done"]
// 忽略...
③ 執行 yaml
通過 kubectl create -f 命令創建 Flink 集群
kubectl create -f flink-configuration-configmap.yaml
kubectl create -f jobmanager-service.yaml
kubectl create -f jobmanager-deployment.yaml
4.Flink Native Application 模式
4.1 Native Application 模式簡介
類似 Application 模式,每個作業獨占一個 Flink 集群,當作業完成后,集群也會被回收。不同點是 Native 特性,即 Flink 直接與 Kubernetes 進行通信并按需申請資源,無需用戶指定 TaskManager 資源的數量。
4.2 優缺點分析
優點:
① 一個作業獨占一個集群,作業的隔離性好。
② 資源利用率相對較高,按需申請 JobManager 和 TaskManager。
缺點:
① 一個作業獨占一個集群,JobManager 不能復用。
② 作業啟動較慢,在作業提交后,才開始創建 JobManager 和 TaskManager。
5.Flink 運行模式總結
模式 | 隔離性 | 作業啟動時間 | 資源利用率 | 資源按需創建 |
---|---|---|---|---|
Session | 弱,作業共享集群 | 較短,立即啟動 | 較低,集群長期存在 | 否 |
Application | 強,作業獨享集群 | 最長,等待集群創建完成 | 一般,作業結束后釋放資源 | 否 |
Native Session | 弱,作業共享集群 | 一般,等待 TaskManager 創建 | 較低,TaskManager 按需申請 | 是 |
Native Application | 強,作業獨占集群 | 一般, 等待集群創建完成 | 最好,集群按需創建 | 是 |