最新發布的 Flink 中支持了 native Kubernetes 的部署方式,可以根據需要動態的增加、減少pod,非常值得測試,目前還處於beta階段,且目前支持 Flink-Session 的部署方式
前提
1、1.9版本或者以上的K8s集羣,且啓用了DNS
2、能夠操作pod、service的 KubeConfig
3、有RBAC權限的service Account,用於創建,刪除pod
部署
解壓flink tar包後,執行如下命令:
./bin/kubernetes-session.sh
啓動成功後可根據日誌輸出打印的 URL 訪問 flink 的頁面,也可以根據 flink 啓動的ClsuterIP/LoadBalancer service 裏的 CLUSTER-IP:8081 來訪問。
默認flink native k8s 啓動的 job master pod 日誌是打印到 pod 裏 /opt/flink/log 目錄下的,如果想通過 kubectl log 查看日誌,可以在 conf/log4j.properties 添加相關配置:
log4j.rootLogger=INFO, file, console
# Log all infos to the console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
然後啓動時添加 -Dkubernetes.container-start-command-template
的參數就可以通過kubectl logs 查看日誌了:
./bin/kubernetes-session.sh -Dkubernetes.container-start-command-template="%java% %classpath% %jvmmem% %jvmopts% %logging% %class% %args%"
然後就可以提交相關job了:
./bin/flink run -d -e kubernetes-session -Dkubernetes.cluster-id=<ClusterId> examples/streaming/WindowJoin.jar
通過不斷提交 job,然後 cancel 掉 job,發現 native k8s 的部署方式可以根據需要動態增加/刪除 pod,相比於之前要事先設定好taskmanager的數量來得方便,也可以更有效的利用資源
採坑
在測試過程中,原先配置的jobmanager.heap.size: 600m
,發現pod一直沒啓動成功,describe pod 和查看 pod 日誌後發現 jvm 的啓動內存設置的都是0
Start command : /bin/bash -c $JAVA_HOME/bin/java -classpath $FLINK_CLASSPATH -Xms0m -Xmx0m -Dlog.file=/opt/flink/log/jobmanager.log -Dlogback.configurationFile=file:/opt/flink/conf/logback.xml -Dlog4j.cint.KubernetesSessionClusterEntrypoint
Invalid maximum heap size: -Xmx0m
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
查看相關源碼後發現對於 Yarn、Mesos、K8s 模式啓動的 container 中除了 Flink 的相關進程外還會預留其他 jvm內存,默認最小預留600m,所以上面配置的jobmanager.heap.size: 600m
時,經過下面的計算邏輯後剩餘的 jobmanager 的 jvm 的值就爲0了,所以啓動失敗。
/**
* Calculate heap size after cut-off. The heap size after cut-off will be used to set -Xms and -Xmx for jobmanager
* start command.
*
* 代碼在:org.apache.flink.runtime.clusterframework.BootstrapTools#calculateHeapSize
*/
public static int calculateHeapSize(int memory, Configuration conf) {
final float memoryCutoffRatio = conf.getFloat(ResourceManagerOptions.CONTAINERIZED_HEAP_CUTOFF_RATIO);
final int minCutoff = conf.getInteger(ResourceManagerOptions.CONTAINERIZED_HEAP_CUTOFF_MIN);
if (memoryCutoffRatio > 1 || memoryCutoffRatio < 0) {
throw new IllegalArgumentException("The configuration value '"
+ ResourceManagerOptions.CONTAINERIZED_HEAP_CUTOFF_RATIO.key()
+ "' must be between 0 and 1. Value given=" + memoryCutoffRatio);
}
if (minCutoff > memory) {
throw new IllegalArgumentException("The configuration value '"
+ ResourceManagerOptions.CONTAINERIZED_HEAP_CUTOFF_MIN.key()
+ "' is higher (" + minCutoff + ") than the requested amount of memory " + memory);
}
int heapLimit = (int) ((float) memory * memoryCutoffRatio);
if (heapLimit < minCutoff) {
heapLimit = minCutoff;
}
return memory - heapLimit;
}
上面的計算邏輯代碼中涉及到兩個配置參數:
containerized.heap-cutoff-ratio
:爲安全起見,Job Master容器中要刪減的內存containerized.heap-cutoff-min
:要從Job Master容器(YARN / Mesos / Kubernetes)中刪除用於其他JVM內存使用的堆空間百分比。
過程參考:
官網-Flink native k8s 部署模式
官網-Flink相關參數配置
《Flink 1.10 Native Kubernetes 原理與實踐》