Flink 1.10 Container 環境實戰

做者 | 唐雲(茶幹),阿里巴巴高級開發工程師
整理 | 張壯壯(Flink 社區志願者)node

摘要:本文根據 Apache Flink 系列直播整理而成,由阿里巴巴高級開發工程師唐雲(茶幹)分享。主要內容以下:docker

  1. 容器管理系統的演變
  2. Flink on K8S intro
  3. Flink on K8S實戰分享
  4. Demo

Tips:點擊下方可查看更多 1.10 系列直播視頻~ api

1.10系列直播:
https://ververica.cn/develope...bash

本文第一部分將簡明扼要地介紹容器管理系統的演變;第二部分是 Flink on K8S 簡介,包括集羣的部署模式調度原理等等;第三部分是咱們這一年以來關於 Flink on K8S 的實戰經驗分享,介紹咱們遇到的問題、踩過的坑;最後一部分是 Demo,將手把手演示集羣部署、任務提交等等。網絡

容器管理系統的演變

640 1.jpg

首先是以一個 Kubernetes 非內核開發人員的角度去探討其和 YARN 之間的關係。衆所周知,Apache Hadoop YARN 多是在國內用途最廣的一個調度系統,主要緣由在於 Hadoop HDFS 在國內或者是在整個大數據業界,是一個使用最普遍的存儲系統。所以,基於其上的 YARN 也天然而然成爲了一個廣爲使用的一個調度系統,包括早期的 Hadoop MapReduce。隨着 YARN 2.0 以後 Framework 的開放,Spark on YARN 以及 Flink on YARN 也能夠在 YARN 上進行調度。架構

固然 YARN 自己也存在必定的侷限性。app

  • 如資源隔離,由於 YARN 是以 Java 爲基礎開發的,因此它不少資源方面的隔離有一些受限。
  • 另外對 GPU 支持不夠,固然如今的 YARN 3.0 已經對 GPU 的調度和管理有必定支持,但以前版本對GPU 支持不是很好。

因此在 Apache 基金會以外,CNCF 基金會基於 Native Cloud 調度的 Kubernetes 出現了。運維

從開發人員角度來看,我認爲 Kubernetes 是更像一個操做系統,能夠作很是多的事情。固然這也意味着 Kubernetes 更復雜、學習曲線比較陡峭,你須要理解不少定義和概念。相比之下,YARN 主要管理資源調度部分,對整個操做系統而言,它體量要小不少。固然,不可置否,它也是一個大數據生態的先驅。接下來我會將焦點放在 Kubernetes 上面,探討從 YARN 的 Container 向 Kubernetes 的 Container(或者 POD)的演變過程當中,咱們總結的經驗和教訓。elasticsearch

Flink on K8S intro

部署集羣

640 2.jpg

上圖展現了 Flink Standalone Session on K8S 上調度流程圖,藍色虛線框內是運行在 Kubernetes 集羣內部組件,灰色框的是 Kubernetes 原生所提供的命令或組件,包括 kubectl 和 K8S Master。左側羅列了 Flink 官方文檔上提供的5個 yaml 文件,能夠用來在 K8S 上部署最簡單的 Flink Standalone Session 集羣。tcp

啓動集羣所須要執行的 kubectl 命令以下:

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
  • 首先,它會向 K8S Master 申請建立 Flink ConfigMap,在 ConfigMap 中提供了 Flink 集羣運行所須要的配置,如:flink-conf.yaml 和 log4j.properties;
  • 其次,建立 Flink JobManager 的 service,經過 service 來打通 TaskManager 和 JobManager之間的聯通性;
  • 而後,建立 Flink Jobmanager 的 Deployment,用來啓動 JobMaster,包含的組件有 Dispatcher 和 Resource manager。
  • 最後,建立 Flink TaskManager 的 Deployment,用來啓動 TaskManager,由於 Flink 官方 taskmanager-deployment.yaml 示例中指定了2個副本,因此圖中展現了2個 TM 節點。

另外,還有一個可選操做是建立 JobManager REST service,這樣用戶就能夠經過REST service 來提交做業。

以上就是 Flink Standalone Session 集羣的概念圖。

做業提交

下圖展現了使用 Flink client 向該 Standalone Session 集羣提交做業的流程細節。

640 3.jpg

使用 Flink client 提交做業的命令是:

./bin/flink run -m : ./examples/streaming/WordCount.jar

其中 -m 所需的參數 public-node-IP 和 node-port 正是經過 jobmanager-service.yaml 所暴露 REST service 的 IP 和端口。執行該命令就能夠向集羣提交一個 Streaming WordCount 做業。此流程與 Flink Standalone 集羣所運行的環境無關,不管是運行在 K8S 之上,仍是運行在物理機之上,提交做業的流程是一致的。

Standalone Session on K8S 的優缺點:

  • 優勢是無需修改 Flink 源碼,僅僅只需預先定義一些yaml 文件,集羣就能夠啓動,互相之間的通訊徹底不通過 K8S Master;
  • 缺點是資源須要預先申請沒法動態調整,而 Flink on YARN 是能夠在提交做業時聲明集羣所需的 JM 和 TM 的資源。

所以社區在 Flink 1.10 進程中,也是咱們阿里負責調度的同窗,貢獻的整個 native 計算模式的Flink on K8S,也是咱們過去一年在實戰中所總結出來的 Native Kubernetes。

640 4.jpg

它最大的區別就是當用戶經過 Flink client 提交做業時,整個集羣的 JobMaster 經過 K8sResourceManager 向 K8S Master 動態申請資源去建立運行 TaskManager 的 POD,而後 TaskManager 再與 JobMaster 互相之間通訊。有關 Native Kubernetes的細節請參考王陽所分享的《Running Flink on Kubernetes natively》。

總而言之,咱們能夠像使用 YARN 同樣的去使用 K8S,相關的配置項也儘可能作到與 YARN 相似。不過爲了方便講解,接下來我會使用 Standalone Session集羣來展現,而下文介紹的部分功能,在 Flink 1.10 還未實現,預計在 Flink 1.11 完成。

Flink on K8S 實戰分享

日誌蒐集

當咱們在 Flink on K8S 上運行一個做業,有一個功能性問題沒法迴避,就是日誌。若是是運行在 YARN 上,YARN 會幫咱們作這件事,例如在 Container 運行完成時,YARN 會把日誌收集起來傳到 HDFS,供後期查看。可是 K8S 並未提供日誌蒐集與存儲,因此咱們能夠有不少選擇去作日誌(收集、展現)的事情。尤爲是看成業由於異常致使 POD 退出,POD 退出後日志會丟失,這將致使異常排查變得很是困難。

若是是 YARN,咱們能夠用命令 yarn logs -applicationId <applicationId> 來查看相關日誌。可是在 K8S 上怎麼辦?

目前咱們比較常見的作法是使用 fluentd 來蒐集日誌,且已經在部分用戶生產環境有所應用。

640 5.png

fluentd 也是一個 CNCF 項目,經過配置一些規則,好比正則匹配,就能夠將 logs 目錄下的.log 、.out 及 *.gc 日誌按期的上傳到 HDFS 或者是其餘分佈存儲文件系統,以此來解決咱們的日誌收集功能。這也意味着在整個 POD 的裏面,除了 TM 或 JM 以外,咱們須要再啓動一個運行着 fluentd 進程的 Container(sidecar)。

固然,還有其餘辦法,好比一個不須要再增長 Container 的方式:咱們可使用logback-elasticsearch-appender 將日誌發到 Elasticsearch。其實現原理是經過Elasticsearch REST API 支持的 scoket stream 方式,將日誌直接寫入Elasticsearch。

相比於以前的 fluentd 來講,優勢是不須要另啓一個 Container 來專門收集日誌,缺點是沒法蒐集非 log4j 日誌,好比 System.out、System.err 打印的日誌,尤爲是做業發生 core dump,或者發生 crash 時,相關日誌會直接刷到System.out、System.err 裏面。從這個角度來看使用 logback-elasticsearch-appender 寫入 Elasticsearch 的方案也不是那麼完美了。相比之下,fluentd 能夠自由地配置各式各樣的策略來蒐集所須要的日誌信息。

Metrics

日誌能夠幫助咱們觀察整個做業運行的狀況,尤爲是在出問題以後,幫助咱們回溯場景,進行一些排查分析。另一個老生常談也很是重要的問題就是 Metrics 和監控。業界已經有不少種監控系統解決方案,好比在阿里內部使用比較多的 Druid、開源InfluxDB 或者商用集羣版 InfluxDB、CNCF 的 Prometheus 或者 Uber 開源的 M3 等等。

而後咱們這裏直接拿 Prometheus 進行討論,由於 Prometheus 與 Kubernetes 均屬於 CNCF 項目,在指標採集領域具有先天優點,從某種程度上來講Prometheus 是 Kubernetes 的一個標配監控採集系統。Prometheus 能夠實現功能不少,不只能夠去作報警,也能夠定一些規則作按期的多精度管理。

640 6.jpg

可是咱們在實際生產中發現一個問題,Prometheus 的水平拓展支持不夠好。你們能夠看到上圖右側部分,Prometheus 所謂的聯邦分佈式架構其實就是多層結構,一層套一層,而後它上面節點負責路由轉發去下一層查詢結果。很明顯,不管部署多少層,越往上的節點越容易成爲性能瓶頸,並且整個集羣的部署也很麻煩。從咱們接觸到的用戶來講,在規模不是很大的時候,單點的 Prometheus 就能夠承擔絕大部分的監控壓力,可是一旦用戶規模很大,好比幾百個節點的 Flink 集羣,咱們就會發現單點 Prometheus 會成了一個很是大的性能瓶頸,沒法知足監控需求。

咱們怎麼作到呢?

640 7.jpg

咱們首先對不一樣 Flink 做業的 metrics 作了一致性哈希,固然確定不會是一個做業的metrics 只發了一個 Prometheus,而是面向做業裏面不一樣 scope 的 metrics,Flink的 metrics 力度從大到小分別是:

  • JobManager/TaskManager metrics
  • Job metrics(checkpoint次數、size和fail次數)
  • task metrics
  • operator metrics(每秒處理多少條record、receive的bytes數目)。

如今方案是先根據不一樣的 scope 去作一致性哈希,發到不一樣的 Prometheus 上,以後再配合 Thanos (滅霸,對就是在《復仇者聯盟3》裏面打完響指後去種瓜的農夫)。我我的理解 Thanos 是一個能夠支持分佈式查詢 Prometheus 的加強組件。因此整個 Prometheus 架構,演變成單個 Prometheus 實例所在的 container 會搭載一個 Thanos sidecar。

固然整個架構會致使一些限制,這個限制也是咱們作一致性哈希的緣由,是由於當 Thanos 與 Prometheus 所搭配部署時,若是有一段 metrics數據,由於某些緣由致使它既在 Prometheus A 裏面,也在 Prometheus B 裏面,那麼在 Thanos query 裏邊它會有必定規則,對數據進行 abandon 處理,即去掉一個以另一個爲準, 這會致使 UI 上 metrics 圖表的線是斷斷續續的,致使體驗很不友好,因此咱們就須要一致性哈希,並經過 Thanos 去作分佈式查詢。

可是整個方案實際運行中仍是有一些性能問題,爲何 Prometheus 在不少業務級 metrics 上去表現其實很不錯,而在 Flink 或者是這種做業級別上,它表現的會有一些壓力呢?其實很重要的一個緣由是做業 metrics 變化是很是急劇的。相比於監控HDFS、Hbase,這些組件的指標是有限的、維度也不高。咱們用一個查詢場景來解釋維度的概念,例如說咱們要查詢在某個 hosts 的某個 job 的某個 task 上全部的 taskmanager_job_task_buffers_outPoolUsage,這些所說的查詢條件,也就是用 tag 去作查詢過濾,那麼就有一個問題是 Flink 的 taskAttempId,這個是一個很是不友好的一個 tag,由於它是一個 uuid 且每看成業發生 failover 的時候,taskAttempId 就會發生變化。

若是做業不斷 failover,而後不停地持久化新的 tag 到 Prometheus,若是 Prometheus 後面接的 DB 須要對 tag 構建一個索引的話,那麼索引的壓力會很是大。例如 InfluxDB 的壓力就會很是大,可能會致使整個內存 CPU 不可用,這樣的結果很是可怕。因此,咱們還須要藉助於社區在 report 這邊把一些高維度的 tag 過濾掉,有興趣的同窗能夠關注下 FLINK-15110。

性能

■ 網絡性能

咱們先介紹 network 性能。不管你用 CNI 或者 Kubernetes 的網絡化插件,不可避免的會出現網絡性能損耗。比較常見的 flannel,在一些測試項目上會有百分之30左右的性能損耗。也不是很穩定,咱們使用時發現做業常常會報PartitionNotFoundException: Partition xx@host not found,也就是下游沒法獲取到上游的 Partition。

640 8.jpg

固然,你能夠在 Flink 層去增大一些網絡容錯性,例如把 taskmanager.network.request-backoff.max 調到300秒,默認是10秒,而後把akka 的 timeout 調大一點。

還有一個讓咱們特別頭疼的問題:

640 9.jpg

咱們發現做業運行過程當中常常遇到 Connection reset by peer 問題,緣由是 Flink 在設計時,對網絡的穩定要求很高。由於要保證 Exactly once,若是數據傳輸失敗,那麼 Flink 就要 fail 整個 task 並從新啓動,而後咱們會發現常常會出現使人頭疼的Connection reset by peer 問題,咱們有幾個的解決方案方式:

  • 不要有異構網絡環境(儘可能不要跨機房訪問)
  • 雲服務商的機器配置網卡多隊列 (將實例中的網絡中斷分散給不一樣的CPU處理,從而提高性能)
  • 選取雲服務商提供的高性能網絡插件:例如阿里雲的 Terway
  • Host network,繞開 k8s 的虛擬化網絡(須要必定的開發量)

第一個要排查的問題就是集羣不要有異構網絡環境,由於有可能 Kubernetes 的宿主機在不一樣機房,而後跨機房訪問遇到網絡抖動的時候都就會比較頭疼。而後是雲服務商機器配置網卡多隊列,由於 ECS 虛擬機,它是須要耗必定的 CPU 去作網絡虛擬化。那麼若是網卡不配置成多隊列的話,有可能網卡只用了1到2個 core,而後虛擬化會把這2個 core 用光,用光的話會致使丟包,也就會遇到這種比較頭疼的Connection reset by peer 問題。

還有一種方案是選取雲服務商提供的高性能網絡插件,固然這須要雲服務商支持,好比阿里雲的 Terway,Terway 對外描述是能夠支持與 host network 同樣的性能,而不是像 flannel 會帶來必定的性能損耗。

最後一種,若是沒法使用 Terway,咱們能夠用 host network 來繞開 K8S 虛擬化網絡。不過這種方案首先是對 Flink 有一些開發工做,其次是若是你已經使用了Kubernetes,卻還要使用 host network,從某種意義上來講,有一點奇怪,很不符合 K8S style。固然咱們也在一些沒法用 Terway 的機器,而後又遇到這個頭疼的問題是,也提供了相應工程,部署時採用 host network,而不是使用 overlay 的flannel 方案。

■ 磁盤性能

接下來談磁盤性能,前文提到過:全部虛擬化的東西都會帶來一些性能損耗。對於 RocksDB 須要讀寫本地磁盤的場景,就很頭疼,由於 overlay 的 file system 會有大概30%的性能損耗。

640 10.jpg

那怎麼辦呢?咱們選擇一種方式,就是使用 hostPath。簡單來講,POD 能夠訪問到宿主機的物理盤。上圖右側部分就定義了 hostPath,固然須要預先保證 Flink 鏡像的用戶是具有訪問宿主機目錄權限,因此最好把這裏目錄改爲 777 或者 775。

你們若是想用這個功能的話,能夠查看 Flink-15656,它提供一個 POD 的 template,意味着你能夠自行調整。由於咱們知道 K8S 的功能特別多,特別繁雜,Flink 不可能爲了每個功能都去作個適配。你能夠在 template 裏面,好比定義 hostPath,而後你所寫 POD 的就能夠基於這個模板下面的 hostPath 就能夠去訪問目錄了。

OOM killed

OOM killed 也是個比較頭疼的問題。由於在容器環境下,部署服務的時候,咱們須要預先設置 POD 所需 memory 和 CPU 的資源,而後 Kubernetes 會指定配置去相關 node (宿主機)上面申請調度資源。申請資源除了要設置 request 以外,還有會設置 limit——通常都會打開 limit——它會對申請的 memory 和 CPU 進行限制。

好比說 node 的物理內存是 64G,而後申請運行8個8G內存的 POD,看着好像沒有問題,可是若是對這8個 POD的沒有任何 limit的話,假如每一個用到10G,那麼就會致使 POD 之間出現資源競爭,現象是一個 POD 運行正常另一個 POD 突然被 Kill,因此就要作一個memory limit。memory limit 帶來的問題是:POD 莫名其妙退出,而後查看 Kubernetes 的 event 發現是由於 POD 被 OOM killed 了。我相信若是用過Kubernetes 的同窗確定遇到過相關問題。

咱們是怎麼排查的呢?

640 11.jpg

第一個是咱們能夠在 JVM 端開啓 native 內存追蹤,能夠按期去查看,但這隻能看到 JVM 所申請的 native 內存,包括如 Metaspace,非 JVM 就沒法分析了;還有一個就是萬能的 Jemalloc 和 jeprof 去作按期 dump 內存進行分析。

老實說第2個功能咱們可能用的比較少,由於咱們之前在 YARN 上面會這樣用,就是說發現有的做業內存很大,由於 JVM 對最大內存會作限制,因此確定是 native 這邊出的問題,那麼究竟是哪一個 native 出問題,就能夠 Jemalloc+jeprof 做內存分析。好比咱們以前遇到過用戶本身去解析 config 文件,結果每次都要解壓一下,最後把內存撐爆了。

固然這是一種引發 OOM 的場景,但更多的多是 RocksDB 引起 OOM,固然若是是使用了 RocksDB 這種省 native 內存的 state backend。因此咱們在 Flink 1.10 作了一個功能貢獻給社區,就是對 RocksDB 的 memory 進行管理,由參數state.backend.rocksdb.memory.managed 控制是否進行管理,默認是開啓。

咱們下面這個圖是什麼呢?

640 12.jpg

是在 RocksDB 沒有使用 memory 控制,這裏一共定了4個 state,分別是 value、list、map 和 window,你們能夠看到最頂端的線是 block cache usage 加上RocksDB 的 write buffer 就構成了 RocksDB 當前所使用總內存的大小。你們看到這4個加起來的話差很少超過400M了。

緣由是 Flink 目前的 RocksDB 對 state 數沒有限制,一個 state 的就是一個 Column Family,而 Column Family 就會額外獨佔所用的 write buffer 和 block cache。默認狀況下,一個 Column Family 最多擁有2個64MB write buffer 和一個 8MB block cache,你們能夠算一算,一個 state 就是136MB,四個 state 就是544MB。

若是咱們開啓了 state.backend.rocksdb.memory.managed,咱們會看到4個 state所使用的 block cache 折線走勢基本一致:

640 13.jpg

爲何呢?是由於實現了 cache share 功能。就是說,咱們在一個 state 裏面咱們先建立一個 LRU cache,以後不管是什麼情景都會從 LRU cache 裏面去作內存的分發和調度,而後藉助 LRU cache,最近最少被用的內存會被釋放掉。因此在 Flink 1.10以後,咱們說開啓 state.backend.rocksdb.memory.managed 能夠解決大部分問題。

640 14.jpg

可是,固然萬事都有可是,咱們開發過程當中發現:RocksDB cache share 的功能作的不是特別好。這涉及到一些實現原理細節,好比無法去作 strict cache,若是你開啓的話可能會碰到奇怪的NPE問題,因此說在某些特定場景下可能作的不是很好。這時你可能就要適當增大taskmanager.memory.task.off-heap.size 以提供更多的緩衝空間。

固然咱們首先要知道它大概用多少內存空間。剛纔咱們展現的內存監控圖裏面,是須要打開參數 state.backend.rocksdb.metrics.block-cache-usage:true,打開以後,咱們能夠在 metrics 監控上面去獲取到相關的指標,觀察一下大概超用到多少。好比說1GB一個 state TM 默認的 manager 是 294MB。

因此說你發現好比說你可能超過不少,好比說偶爾會到300MB,或者310MB,你這時候就能夠考慮配置參數taskmanager.memory.task.off-heap.size (默認是0)來再增長一部份內存,好比說再加64MB,表示在 Flink 所申請的 off-heap 裏面再額外開闢出來一塊空間,給RocksDB 作一段 Buffer,以避免他被 OOM killed。這個是目前所能掌握的一個解決方案,但根本的解決方案可能須要跟 RocksDB 社區去一塊兒去協同處理。

咱們也但願若是有同窗遇到相似問題能夠跟咱們進行交流,咱們也很是樂意和你一塊兒去觀察、追蹤相關問題。

Demo

最後一部分演示使用 hostPath 的 demo,大部分 yaml 文件與社區的示例相同,task manager 的部署 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: reg.docker.alibaba-inc.com/chagan/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/
        - name: state-volume
          mountPath: /dump/1/state
        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
      - name: state-volume
        hostPath:
          path: /dump/1/state
          type: DirectoryOrCreate

Q&A 問答

一、Flink 如何在 K8S 的 POD 中與 HDFS 交互?

其與 HDFS 交互很簡單,只要把相關依賴打到鏡像裏面就好了。就是說你把 flink-shaded-hadoop-2-uber-{hadoopVersion}-{flinkVersion}.jar 放到 flink-home/lib目錄下,而後把一些 hadoop 的配置好比 hdfs-site.xml、 core-site.xml 等放到能夠訪問的目錄下,Flink 天然而然就能夠訪問了。這其實和在一個非 HDFS 集羣的節點上,要去訪問 HDFS 是同樣的。

二、Flink on K8S 怎麼保證 HA?

其實 Flink 集羣的 HA 與是否運行在 K8S 之上沒什麼關係,社區版的 Flink 集羣 HA須要 ZooKeeper 參與。HA 須要 ZooKeeper 去實現 checkpoint Id counter、須要ZooKeeper 去實現 checkpoint stop、還包括 streaming graph 的 stop,因此說HA 的核心就變成如何在 Flink on K8S 的集羣之上,提供 ZooKeeper 的服務,ZooKeeper 集羣能夠部署在 K8S 上或者物理機上。同時社區也有嘗試在 K8S 裏面借用 etcd 去支持提供一套 HA 方案,目前真正工業級的 HA,暫時只有 zookeeper 這一種實現。

三、Flink on K8S 和 Flink on YARN,哪一個方案更優?怎樣選擇?

Flink on YARN 是目前比較成熟的一套系統,可是它有點重,不是雲原生(cloud native)。在服務上雲的大趨勢下,Flink on K8S 是一個光明的將來。Flink on YARN 是一個過去很是成熟一套體系,可是它在新的需求、新的挑戰之下,可能缺少一些應對措施。例如對不少細緻的 GPU 調度,pipeline 的建立等等,概念上沒有K8S 作得好。

若是你只是簡單運行一個做業,在 Flink on YARN 上能夠一直穩定運行下去,它也比較成熟,相比之下 Flink on K8S 夠新、夠潮、方便迭代。不過目前 Flink on K8S 已知的一些問題,好比學習曲線比較陡峭,須要一個很好的 K8S 運維團隊去支撐。另外,K8S 自己虛擬化帶來的性能影響,正如先前介紹的不管是磁盤,仍是網絡,很難避免必定的性能損耗,這個多是稍微有點劣勢的地方,固然相比這些劣勢,虛擬化(容器化)帶來的優勢更明顯。

四、 /etc/hosts 文件如何配置的?我理解要跟 HDFS 交互,須要把 HDFS 節點 IP 和 host,映射寫到 /etc/hosts 文件。

經過經過 Volume 掛載 ConfigMap 內容並映射到 /etc/hosts 來解決,或者無需修改 /etc/hosts 轉而依賴 CoDNS。

五、Flink on K8S 故障排查困難,大家是怎麼解決的?

首先 Flink on K8S 與 Flink on YARN 的故障排查有什麼區別呢?主要是 K8S 自己可能會有問題,這就是稍微麻煩的地方。K8S 能夠認爲是一個操做系統,可能有不少複雜的組件在裏面。YARN 是一個用 Java 實現的資源調度器,這時更可能是宿主機故障致使集羣異常。面對 K8S 可能出問題,我我的感受是相比 YARN 來講要難查一些。由於它有不少組件,可能 DNS 解析出問題,就須要去查看 CoDNS 日誌;網絡出問題或者是磁盤出問題你要去查看 kube event;POD 異常退出,須要去查看 event POD 退出的緣由。實話實話,確實須要必定的門檻,最好是須要運維支持。

但若是是說 Flink 故障排查,這在 K8S 或是 YARN 排查手段都同樣,

  • 查看日誌,檢測是否有 exception;
  • 若是是性能就須要用 jstack,查看 CPU、調用棧卡在哪裏;
  • 若是發現老是有 OOM 風險,或者老年代老是打的很滿,或者 GC 頻繁,或者Full GC 致使 Stop the world,就須要 jmap 查看哪塊佔內存,分析是否存在內存泄露

這些排查方法是與平臺是無關的,是一個放之四海而皆準的排查流程。固然須要注意POD 鏡像中可能會缺乏一些 Debug 工具,因此建議你們在搭建 Flink on K8S 集羣時,構建私有鏡像,在構建的過程當中安裝好相應的 Debug 工具。

相關文章
相關標籤/搜索