全景剖析阿里雲容器網路資料鏈路(四):Terway IPVLAN+EBPF

語言: CN / TW / HK

本系列文章由余凱執筆創作,聯合作者:阿里雲容器服務 謝石 對本文亦有貢獻

近幾年,企業基礎設施雲原生化的趨勢越來越強烈,從最開始的IaaS化到現在的微服務化,客戶的顆粒度精細化和可觀測性的需求更加強烈。容器網路為了滿足客戶更高效能和更高的密度,也一直在高速的發展和演進中,這必然對雲原生網路的可觀測性帶來了極高的門檻和挑戰。為了提高雲原生網路的可觀測性,同時便於客戶和前後線同學增加對業務鏈路的可讀性,ACK產研和AES聯合共建,合作開發ack net-exporter和雲原生網路資料面可觀測性系列,幫助客戶和前後線同學瞭解雲原生網路架構體系,簡化對雲原生網路的可觀測性的門檻,優化客戶運維和售後同學處理疑難問題的體驗 ,提高雲原生網路的鏈路的穩定性。

鳥瞰容器網路,整個容器網路可以分為三個部分:Pod網段,Service網段和Node網段。這三個網路要實現互聯互通和訪問控制,那麼實現的技術原理是什麼?整個鏈路又是什麼,限制又是什麼呢?Flannel, Terway有啥區別?不同模式下網路效能如何?這些,需要客戶在下搭建容器之前,就要依據自己的業務場景進行選擇,而搭建完畢後,相關的架構又是無法轉變,所以客戶需要對每種架構特點要有充分了解。比如下圖是個簡圖,Pod網路既要實現同一個ECS的Pod間的網路互通和控制,又要實現不同ECS Pod間的訪問, Pod訪問SVC 的後端可能在同一個ECS 也可能是其他ECS,這些在不同模式下,資料鏈轉發模式是不同的,從業務側表現結果也是不一樣的。

1.png

本文是[全景剖析容器網路資料鏈路]第四部分部分,主要介紹Kubernetes Terway EBPF+IPVLAN模式下,資料面鏈路的轉轉發鏈路,一是通過了解不同場景下的資料面轉發鏈路,從而探知客戶在不同的場景下訪問結果表現的原因,幫助客戶進一步優化業務架構;另一方面,通過深入瞭解轉發鏈路,從而在遇到容器網路抖動時候,客戶運維以及阿里雲同學可以知道在哪些鏈路點進行部署觀測手動,從而進一步定界問題方向和原因。

Terway IPVLAN+EBPF 模式架構設計

彈性網絡卡(ENI)支援配置多個輔助IP的功能,單個彈性網絡卡(ENI)根據例項規格可以分配6-20個輔助IP,ENI多IP模式就是利用了這個輔助IP分配給容器,從而大幅提高了Pod部署的規模和密度。在網路聯通的方式上,Terway支援選擇Veth pair策略路由和ipvlan l兩種方案,Linux在4.2以上的核心中支援了ipvlan的虛擬網路,可以實現單個網絡卡虛擬出來多個子網絡卡用不同的IP地址,而Terway便利用了這種虛擬網路型別,將彈性網絡卡的輔助IP繫結到IPVlan的子網絡卡上來打通網路,使用這種模式使ENI多IP的網路結構足夠簡單,效能也相對veth策略路由較好。

ipvlan:

https://www.kernel.org/doc/Documentation/networking/ipvlan.txt

2.png

Pod 所使用的的CIDR網段和節點的CIDR是同一個網段

3.png

Pod內部可以看到是有一張網絡卡的,一個是eth0,其中eth0 的IP就是 Pod的IP,此網絡卡的MAC地址和控制檯上的ENI的MAC地址不一致,同時ECS上有多張 ethx的網絡卡,說明ENI附屬網絡卡並不是直接掛在到了Pod的網路名稱空間

4.png 5.png

Pod內有隻有指向eth0的預設路由,說明Pod訪問任何地址段都是從eth0為統一的出入口

6.png

那麼Pod是如何ECS OS進行通訊呢?在OS層面,我們一看到ipvl_x的網絡卡,可以看到是附屬於eth1的,說明在OS層面會給每個附屬網絡卡建立一個ipvl_x的網絡卡,用於建立OS和Pod內的連線隧道。

7.png

ECS OS內對於資料流量是怎麼判斷去哪個容器呢?通過OS Linux Routing 我們可以看到,所有目的是 Pod IP 的流量都會被轉發到Pod對應的ipvl_x虛擬往卡上,到這裡為止,ECS OS 和Pod的網路名稱空間已經建立好完整的出入鏈路配置了。到目前為止介紹了IPVLAN在網路架構上的實現。

8.png

對於eni多IP的實現,這個類似於《全景剖析阿里雲容器網路資料鏈路(三)—— Terway ENIIP》原理,Terway Pod是通過daemonset的方式部署在每個節點上的,通過下面命令可以看到每個節點上的Terway Pod。通過terway-cli show factory 命令可以看到節點上的附屬ENI數量、MAC地址以及每個ENI上的IP

9.png

那麼對於SVC來說,是如何實現的呢?看過前面 四個系列的朋友,應該知道對於Pod訪問SVC,容器是利用各種辦法將請求轉發到Pod所在的ECS層面,由ECS內的netfilter模組來實現SVC IP的解析,這固然是個好辦法,但是由於資料鏈路需要從Pod的網路名稱空間切換到ECS的OS的網路名稱空間,中間經過了2次核心協議棧,必然會產生效能損失,如果對高併發和高效能有極致追求,可能並不完全滿足客戶的需求。那麼對於高併發和延遲敏感業務,該如何實現呢?有沒有辦法讓Pod訪問SVC直接在Pod的網路名稱空間中就實現了後端解析,這樣結合IPVLAN這樣至實現了一次核心協議棧。在4.19版本核心中,ebpf的出現,很好的實現了這個需求,這裡不對ebpf做過多說明,感興趣的可以訪問官方連結,小夥伴們只需要知道ebpf是一種可以安全在核心層面執行的安全沙盒,當觸發核心的指定行為,ebpf設定程式會被執行。利用這個特性,我們可以實現在tc層面對訪問SVC IP的資料包進行修改。

官方連結:

https://ebpf.io/what-is-ebpf/

10.png 11.png

例如,同上圖,可以看到叢集內有一個名為nginx的svc,clusterIP是192.168.27.242,後端pod IP是10.0.3.38. 通過cilium bpf lb list 可以看到在ebpf程式中對於clusterIP 192.168.27.242的訪問會被轉到10.0.3.38 這個IP上, 而Pod內只有一個預設路由。此處說明,IPVLAN+EBPF模式下,如果Pod訪問SVC IP,SVCIP在Pod的網路名稱空間內就會被ebpf轉為某個SVC 後端pod的IP,之後資料鏈路被髮出Pod。也就是說SVCIP只會在Pod內被捕獲,在源端ECS,目的端Pod 和目的端的Pod所在ECS都無法被捕獲到。那假如一個SVC後後段有100+ pod, 因為ebpf存在,Pod外無法捕獲到SVCIP,所在一旦出現網路抖動,對於抓包該抓那個後端IP或該在哪個後端Pod出抓包呢?想一想,是不是一個非常頭疼又無解的場景?  目前容器服務和AES共創了ACK Net-Exporter容器網路可觀測性工具,可以針對此場景進行持續化的觀測和問題判斷。

ACK Net-Exporter容器網路:

https://help.aliyun.com/document_detail/449682.html

故Terway IPVLAN+EBPF 模式總體可以歸納為:

  • 4.2以上核心中支援了ipvlan的虛擬網路,可以實現單個網絡卡虛擬出來多個子網絡卡用不同的IP地址,而Terway便利用了這種虛擬網路型別,將彈性網絡卡的輔助IP繫結到IPVlan的子網絡卡上來打通網路,使用這種模式使ENI多IP的網路結構足夠簡單,效能也相對veth策略路由較好。

  • 節點訪問pod 需要經過host 的協議棧,pod和pod 間訪問 不經過host的 協議棧

  • IPVLAN+EBPF模式下,如果Pod訪問SVC IP,SVCIP在Pod的網路名稱空間內就會被ebpf轉為某個SVC 後端pod的IP,之後資料鏈路被髮出Pod。也就是說SVCIP只會在Pod內被捕獲,在源端ECS,目的端Pod 和目的端的Pod所在ECS都無法被捕獲到。

Terway IPVLAN+EBPF 模式容器網路資料鏈路剖析

針對容器網路特點,我們可以將Terway IPVLAN+EBPF模式下的網路鏈路大體分為以Pod IP對外提供服務和以SVC對外提供服務兩個大的SOP場景,進一步細分,可以歸納為12個不同的小的SOP場景。

12.png

對這11個場景的資料鏈路梳理合並,這些場景可以歸納為下面12類典型的場景:

TerwayENI架構下,不同的資料鏈路訪問情況下,可以總結歸納為為12類:

  • 訪問 Pod IP, 同節點訪問Pod

  • 訪問Pod IP,同節點pod間互訪(pod屬於同ENI)

  • 訪問Pod IP,同節點pod間互訪(pod屬於不同ENI)

  • 不同節點間Pod之間互訪

  • 叢集內Pod訪問的SVC ClusterIP(含Terway版本≥1.2.0,訪問ExternalIP),SVC後端Pod和客戶端Pod配屬同一個ENI

  • 叢集內Pod訪問的SVC ClusterIP(含Terway版本≥1.2.0,訪問ExternalIP),SVC後端Pod和客戶端Pod配屬不同ENI(同ECS)

  • 叢集內Pod訪問的SVC ClusterIP(含Terway版本≥1.2.0,訪問ExternalIP),SVC後端Pod和客戶端Pod不屬於不同ECS

  • 叢集內Pod訪問的SVC ExternalIP(Terway版本≤1.2.0),SVC後端Pod和客戶端Pod配屬同一個ENI

  • 叢集內Pod訪問的SVC ExternalIP(Terway版本≤1.2.0),SVC後端Pod和客戶端Pod配屬不同ENI(同ECS)

  • 叢集內Pod訪問的SVC ExternalIP(Terway版本≤1.2.0),SVC後端Pod和客戶端Pod部署於不同ECS

  • 叢集外訪問SVC ExternalIP

2.1 場景一:訪問Pod IP,同節點訪問pod

環境

13.png

cn-hongkong.10.0.3.15  節點上存在 nginx-7d6877d777-j7dqz 和 10.0.3.38

核心路由

nginx-7d6877d777-j7dqz  IP地址 10.0.3.38  ,該容器在宿主機表現的PID是329470,該容器網路名稱空間有指向容器eth0的預設路由

14.png

該容器eth0在ECS OS 內是通過ipvlan隧道的方式和ECS的附屬ENI eth1建立的隧道,同時附屬ENI eth1還有個虛擬的ipvl_8@eth1 網絡卡

15.png

通過OS Linux Routing 我們可以看到,所有目的是 Pod IP 的流量都會被轉發到Pod對應的ipvl_x虛擬往卡上,這樣就建立完畢ECS和Pod之間的連線隧道了。

16.png

小結:可以訪問到目的端

nginx-7d6877d777-zp5jg  netns  eth0   可以抓到資料包

17.png

ECS 的   ipvl_8 可以抓到資料包

18.png 19.png

資料鏈路轉發示意圖

  • 不會經過分配給pod的附屬網絡卡

  • 整個鏈路是通過查詢路由表進入ipvl_xxx,不需要經過ENI

  • 整個請求鏈路是node -> ipvl_xxx -> ECS1 Pod1

2.2 場景二:訪問Pod IP,同節點pod間互訪(pod屬於同ENI)

環境

20.png

cn-hongkong.10.0.3.15  節點上存在 nginx-7d6877d777-j7dqz 和  centos-6c48766848-znkl8 兩個pod, IP分別為 10.0.3.38 和 10.0.3.5

21.png

通過 此節點的terway pod, 我們可以 利用 terway-cli show factory 的命令看到 這兩個IP (10.0.3.5 和10.0.3.38)都屬於同一個MAC地址 00:16:3e:04:08:3a ,說明這兩個IP屬於同一個ENI,進而可以推斷出nginx-7d6877d777-j7dqz 和  centos-6c48766848-znkl8  屬於同一個ENI 網絡卡

核心路由

centos-6c48766848-znkl8  IP地址 10.0.3.5,該容器在宿主機表現的PID是2747933,該容器網路名稱空間有指向容器eth0的預設路由, 有且只有一條,說明pod訪問所有地址都需要通過該預設路由

22.png 23.png

nginx-7d6877d777-j7dqz  IP地址 10.0.3.38  ,該容器在宿主機表現的PID是329470,該容器網路名稱空間有指向容器eth0的預設路由

24.png

25.png

該容器eth0在ECS OS 內是通過ipvlan隧道的方式和ECS的附屬ENI eth1建立的隧道,同時附屬ENI eth1還有個虛擬的ipvl_8@eth1 網絡卡

26.png

小結:可以訪問到目的端

centos-6c48766848-znkl8   netns  eth0   可以抓到資料包

27.png

nginx-7d6877d777-zp5jg  netns   eth0 可以抓到資料包

28.png

ipvl_8 網絡卡 並沒有捕獲到相關的資料流量包

29.png 30.png

資料鏈路轉發示意圖

  • 不會經過分配給pod的附屬網絡卡

  • 不會經過任何宿主機ECS的網路空間的中間節點

  • 整個鏈路請求不會經過pod所分配的ENI,直接在OS 的ns中命中 Ip rule 被轉發到對端pod

  • 整個請求鏈路是 ECS1 Pod1 -> ECS1 pod2  (發生在ECS內部), 和IPVS相比,避免了calico網絡卡裝置的兩次轉發,效能是更好的。

2.3 場景三:訪問Pod IP,同節點pod間互訪(pod屬於不同ENI)

環境

cn-hongkong.10.0.3.15  節點上存在 nginx-7d6877d777-j7dqz 和  busybox-d55494495-8t677  兩個pod, IP分別為 10.0.3.38 和 10.0.3.22

31.png

通過 此節點的terway pod, 我們可以 利用 terway-cli show factory 的命令看到 這兩個IP (10.0.3.22 和10.0.3.38)都屬於同一個MAC地址00:16:3e:01:b7:bd 和 00:16:3e:04:08:3a ,說明這兩個IP屬於不同ENI,進而可以推斷出nginx-7d6877d777-j7dqz 和  busybox-d55494495-8t677  屬於不同ENI 網絡卡

32.png

核心路由

busybox-d55494495-8t677   IP地址 10.0.3.22 ,該容器在宿主機表現的PID是2956974,該容器網路名稱空間有指向容器eth0的預設路由, 有且只有一條,說明pod訪問所有地址都需要通過該預設路由

33.png 34.png

nginx-7d6877d777-j7dqz  IP地址 10.0.3.38  ,該容器在宿主機表現的PID是329470,該容器網路名稱空間有指向容器eth0的預設路由

35.png 36.png

該容器eth0在ECS OS 內是通過ipvlan隧道的方式和ECS的附屬ENI eth1建立的隧道,通過mac地址一樣可以看到,nginx-7d6877d777-j7dqz 和  busybox-d55494495-8t677 分別被分配eth1和eth2

37.png

小結:可以訪問到目的端

busybox-d55494495-8t677   netns  eth0   可以抓到資料包

38.png

nginx-7d6877d777-zp5jg netns   eth0 可以抓到資料包

39.png 40.png

資料鏈路轉發示意圖

  • 不會經過分配給pod的附屬網絡卡

  • 不會經過任何宿主機ECS的網路空間的中間節點

  • 整個鏈路是需要從客戶端pod所屬的ENI網絡卡出ECS,再從目的POD所屬的ENI網絡卡進入ECS

  • 整個請求鏈路是 ECS1 POD1 -> ECS1 eth1 -> VPC -> ECS1 eth2 -> ECS1 POD2

2.4 場景四:不同節點間Pod之間互訪

環境

41.png

cn-hongkong.10.0.3.15  節點上存在 nginx-7d6877d777-j7dqz, IP分為 10.0.3.38

cn-hongkong.10.0.3.93  節點上存在 centos-6c48766848-dz8hz, IP分為 10.0.3.127

42.png

通過 此節點的terway pod, 我們可以 利用 terway-cli show factory 的命令看到 nginx-7d6877d777-j7dqz IP 10.0.3.5 屬於cn-hongkong.10.0.3.15   上的 MAC地址 為00:16:3e:04:08:3a 的ENI網絡卡

43.png

通過 此節點的terway pod, 我們可以 利用 terway-cli show factory 的命令看到 centos-6c48766848-dz8hz IP  10.0.3.127 屬於cn-hongkong.10.0.3.93   上的 MAC地址 為 00:16:3e:02:20:f5 的ENI網絡卡

核心路由

centos-6c48766848-dz8hz    IP地址 10.0.3.127   ,該容器在宿主機表現的PID是1720370,該容器網路名稱空間有指向容器eth0的預設路由, 有且只有一條,說明pod訪問所有地址都需要通過該預設路由

44.png 45.png

nginx-7d6877d777-j7dqz  IP地址 10.0.3.38  ,該容器在宿主機表現的PID是329470,該容器網路名稱空間有指向容器eth0的預設路由

46.png

47.png

ECS OS 內是通過ipvlan隧道的方式和ECS的附屬ENI eth1建立的隧道,通過mac地址一樣可以看到兩個pod 分配的ENI地址

centos-6c48766848-dz8hz

48.png

nginx-7d6877d777-j7dqz

49.png

小結:可以訪問到目的端

此處不再對抓包進行展示,從客戶端角度,資料流可以在centos-6c48766848-dz8hz   的網路名稱空間  eth0 ,以及 此pod所部署的ECS 對應的ENI eth1上可以被捕獲到;從服務端角度,資料流可以在nginx-7d6877d777-j7dqz 的網路名稱空間  eth0 ,以及 此pod所部署的ECS對應的ENI eth1上可以被捕獲到。

50.png

資料鏈路轉發示意圖

  • 不會經過任何宿主機ECS的網路空間的中間節點

  • 整個鏈路是需要從客戶端pod所屬的ENI網絡卡出ECS,再從目的POD所屬的ENI網絡卡進入ECS

  • 整個請求鏈路是 ECS1 POD1 -> ECS1 ethx -> VPC -> ECS2 ethy -> ECS2 POD2

2.5場景五:叢集內Pod訪問的SVC ClusterIP(含Terway版本≥1.2.0,訪問ExternalIP),SVC後端Pod和客戶端Pod配屬同一個ENI

環境

51.png

cn-hongkong.10.0.3.15  節點上存在 nginx-7d6877d777-j7dqz 和  centos-6c48766848-znkl8 兩個pod, IP分別為 10.0.3.38 和 10.0.3.5

52.png

通過 此節點的terway pod, 我們可以 利用 terway-cli show factory 的命令看到 這兩個IP (10.0.3.5 和10.0.3.38)都屬於同一個MAC地址 00:16:3e:04:08:3a ,說明這兩個IP屬於同一個ENI,進而可以推斷出nginx-7d6877d777-j7dqz 和  centos-6c48766848-znkl8  屬於同一個ENI 網絡卡

通過describe svc 可以看到 nginx pod 被加入到了 svc nginx 的後端。SVC 的CLusterIP是192.168.27.242。如果是叢集內訪問External IP, 對於 Terway 版本≥ 1.20 來說,叢集內訪問SVC的ClusterIP或External IP,整個鏈路架構是一致的,此小節不在針對External IP單獨說明,統一用ClusterIP作為示例(Terway版本< 1.20 情況下,訪問External IP,會在後續小節說明)。

53.png

核心路由

centos-6c48766848-znkl8  IP地址 10.0.3.5,該容器在宿主機表現的PID是2747933,該容器網路名稱空間有指向容器eth0的預設路由, 有且只有一條,說明pod訪問所有地址都需要通過該預設路由

54.png 55.png

nginx-7d6877d777-j7dqz  IP地址 10.0.3.38  ,該容器在宿主機表現的PID是329470,該容器網路名稱空間有指向容器eth0的預設路由

56.png 57.png

在ACK中,是利用cilium去呼叫ebpf的能力,可以通過下面的命令可以看到 nginx-7d6877d777-j7dqz 和  centos-6c48766848-znkl8 identity ID 分別是 634 和 1592

58.png

通過centos-6c48766848-znkl8 pod,可以找到此pod所在的ECS的Terway pod為terway-eniip-6cfv9,在Terway Pod 中執行下面的cilium bpf lb list | grep -A5 192.168.27.242  命令可以看到 ebpf中對於CLusterIP  192.168.27.242:80  記錄的後端是 10.0.3.38:80 。這上述的一切都是通過EBPF 記錄到了 源端Pod centos-6c48766848-znkl8 pod 的 tc中。

59.png 60.png

通過以上,可以理論推斷出,如果叢集內的pod訪問 SVC的CLusterIP or External IP地址(Terway ≥ 1.20), 資料流會在pod 的網路名稱空間內就被轉化為相應的SVC 的後端 pod IP後,再被從Pod 網路名稱空間的eth0 發出pod,進入到pod所在的ECS,然後通過IPVLAN隧道,轉發到同ECS或通過相應的ENI出ECS。也就是說,我們如果抓包,不管在pod內抓包還是在ECS抓包,都無法捕獲到SVC 的IP,只能捕獲到Pod IP。

EBPF技術讓叢集內訪問避開了ECS OS內部的核心協議棧和減少了部分Pod 核心協議棧,大大提高了網路效能和Pod密度,帶來了不弱於 單獨ENI的網路效能,但是此方式會對我們觀測帶來巨大的改變和影響。試想一下,如果您的叢集記憶體在互相呼叫情況,這個呼叫的IP 是SVC 的IP,加入此SVC後端所引用的Pod有幾十上百個。源端pod呼叫時候出現問題,一般情況下報錯是 ‘connect to failed’ 等類似資訊,傳統的抓包手段是在源端Pod內,目的Pod, ECS上等進行抓包,篩選 SVC IP 來串起來不同包之間的同一個資料流,可是eBPF情況下由於上述技術實現,造成無法捕獲SVC IP,是不是對偶發抖動情況下的觀測帶來了巨大挑戰呢?

小結:可以訪問到目的端

從客戶端Pod centos-6c48766848-znkl8   訪問SVC , 我們可以看到訪問成功

61.png

客戶端的centos-6c48766848-znkl8 網路名稱空間內  eth0   抓包,抓包地址是目的SVC 的IP 和 SVC 的後端POD IP。可以看到只能抓到SVC 後端Pod IP,無法捕獲到SVC IP。

62.png

目的端SVC的後端POD nginx-7d6877d777-zp5jg 網路名稱空間    eth0 抓包,抓包地址是目的SVC 的IP 和 客戶端 POD IP。可以看到只能抓到客戶端Pod IP。

63.png

cilium 提供了一個monitor的功能,我們使用cilium monitor --related-to , 可以看到,源端POD IP 訪問SVCIP 192.168.27.242, 之後被解析到SVC的後端POD IP 10.0.3.38.,說明SVC IP直接在tc層做了轉發,這也解釋了為什麼抓包無法抓到SVC IP,因為抓包是在netdev上抓的,此時已經過了 協議棧和tc。

64.png

後續小節如果涉及SVC IP 的訪問,如有類似,不再做詳細的抓包展示

65.png

資料鏈路轉發示意圖

  • 不會經過任何宿主機ECS的網路空間的中間節點

  • 整個鏈路請求不會經過pod所分配的ENI,直接在OS 的ns中命中 Ip rule 被轉發到對端pod

  • 整個請求鏈路是 ECS1 Pod1 ->  ECS1 pod2  (發生在ECS內部), 和IPVS相比,避免了calico網絡卡裝置的兩次轉發,效能是更好的。

  • ECS1 Pod1 的 eth0網絡卡無法捕捉到 SVC IP,SVC IP 在 pod 網路名稱空間內已經通過ebpf轉換成了SVC後端Pod的IP

2.6場景六:叢集內Pod訪問的SVC ClusterIP(含Terway版本≥1.2.0,訪問ExternalIP),SVC後端Pod和客戶端Pod配屬不同ENI(同ECS)

環境

66.png

cn-hongkong.10.0.3.15  節點上存在 nginx-7d6877d777-j7dqz 和  busybox-d55494495-8t677  兩個pod, IP分別為 10.0.3.38 和 10.0.3.22

67.png

通過 此節點的terway pod, 我們可以 利用 terway-cli show factory 的命令看到 這兩個IP (10.0.3.22 和10.0.3.38)都屬於同一個MAC地址00:16:3e:01:b7:bd 和 00:16:3e:04:08:3a ,說明這兩個IP屬於不同ENI,進而可以推斷出nginx-7d6877d777-j7dqz 和  busybox-d55494495-8t677  屬於不同ENI 網絡卡

通過describe svc 可以看到 nginx pod 被加入到了 svc nginx 的後端。SVC 的CLusterIP是192.168.27.242。如果是叢集內訪問External IP, 對於 Terway 版本≥ 1.20 來說,叢集內訪問SVC的ClusterIP或External IP,整個鏈路架構是一致的,此小節不在針對External IP單獨說明,統一用ClusterIP作為示例(Terway版本< 1.20 情況下,訪問External IP,會在後續小節說明)。

68.png

核心路由

busybox-d55494495-8t677   IP地址 10.0.3.22 ,該容器在宿主機表現的PID是2956974,該容器網路名稱空間有指向容器eth0的預設路由, 有且只有一條,說明pod訪問所有地址都需要通過該預設路由

69.png 70.png

nginx-7d6877d777-j7dqz  IP地址 10.0.3.38  ,該容器在宿主機表現的PID是329470,該容器網路名稱空間有指向容器eth0的預設路由

71.png72.png

在ACK中,是利用cilium去呼叫ebpf的能力,可以通過下面的命令可以看到 nginx-7d6877d777-j7dqz 和  busybox-d55494495-8t677  identity ID 分別是 634 和 3681

73.png

通過busybox-d55494495-8t677  pod,可以找到此pod所在的ECS的Terway pod為terway-eniip-6cfv9,在Terway Pod 中執行下面的cilium bpf lb list | grep -A5 192.168.27.242  命令可以看到 ebpf中對於CLusterIP  192.168.27.242:80  記錄的後端是 10.0.3.38:80 。這上述的一切都是通過EBPF 記錄到了 源端Pod centos-6c48766848-znkl8 pod 的 tc中。

74.png 75.png

這裡不再過多對於svc ClusterIP的ebpf轉發進行描述,詳細資訊可以參考 2.5 小節中的描述,從上述描述情況,可以得知被訪問的SVC 的IP 在 客戶端 busybox 的網路名稱空間中已經被ebpf轉為svc 的後端pod 的IP,在任何dev上都無法捕獲到客戶端訪問的SVC的IP。故此場景和 2.3 小節的網路架構非常類似,只是在客戶端內會由cilium ebpf轉發的動作

小結

76.png

資料鏈路轉發示意圖

  • 不會經過任何宿主機ECS的網路空間的中間節點

  • 整個鏈路是需要從客戶端pod所屬的ENI網絡卡出ECS再從目的POD所屬的ENI網絡卡進入ECS

  • 整個請求鏈路是 ECS1 POD1 -> ECS1 eth1 -> VPC -> ECS1 eth2 -> ECS1 POD2

  • 在客戶端/服務端Pod內或者ECS的ENI網絡卡都 無法捕捉到 SVC IP,SVC IP 在 客戶端 pod 網路名稱空間內已經通過ebpf轉換成了SVC後端Pod的IP

2.7 場景七:叢集內Pod訪問的SVC ClusterIP,SVC後端Pod和客戶端Pod不屬於不同ECS

環境

77.png

cn-hongkong.10.0.3.15  節點上存在 nginx-7d6877d777-j7dqz, IP分為 10.0.3.38cn-hongkong.10.0.3.93  節點上存在 centos-6c48766848-dz8hz, IP分為 10.0.3.127

78.png

通過 此節點的terway pod, 我們可以 利用 terway-cli show factory 的命令看到 nginx-7d6877d777-j7dqz IP 10.0.3.5 屬於cn-hongkong.10.0.3.15   上的 MAC地址 為00:16:3e:04:08:3a 的ENI網絡卡

79.png

通過 此節點的terway pod, 我們可以 利用 terway-cli show factory 的命令看到 centos-6c48766848-dz8hz IP  10.0.3.127 屬於cn-hongkong.10.0.3.93   上的 MAC地址 為 00:16:3e:02:20:f5 的ENI網絡卡

通過describe svc 可以看到 nginx pod 被加入到了 svc nginx 的後端。SVC 的CLusterIP是192.168.27.242。如果是叢集內訪問External IP, 對於 Terway 版本≥ 1.20 來說,叢集內訪問SVC的ClusterIP或External IP,整個鏈路架構是一致的,此小節不在針對External IP單獨說明,統一用ClusterIP作為示例(Terway版本< 1.20 情況下,訪問External IP,會在後續小節說明)。

80.png

核心路由

Pod訪問SVC 的Cluster IP,而SVC的後端Pod 和 客戶端Pod部署在不同ECS上,此架構類似 2.4 小節中的不同ECS節點上的Pod間互訪情況,只不此場景是Pod訪問SVC 的ClusterIP,要注意此處是訪問ClusterIP,如果是訪問External IP,那麼場景會進一步複雜了,本門的後面幾個小節會詳細說明。對於 ClusterIP的ebpf轉發進行描述,詳細資訊可以參考 2.5 小節中的描述,和前面幾個小節一樣,在任何dev上都無法捕獲到客戶端訪問的SVC的IP。

小結

81.png

資料鏈路轉發示意圖

  • 不會經過任何宿主機ECS的網路空間的中間節點

  • 整個鏈路是需要從客戶端pod所屬的ENI網絡卡出ECS再從目的POD所屬的ENI網絡卡進入ECS

  • 整個請求鏈路是 ECS1 POD1 -> ECS1 eth1 -> VPC -> ECS2 eth1 -> ECS2 POD2

  • 在客戶端/服務端Pod內或者ECS的ENI網絡卡都 無法捕捉到 SVC IP,SVC IP 在 客戶端 pod 網路名稱空間內已經通過ebpf轉換成了SVC後端Pod的IP

2.8 場景八:叢集內Pod訪問的SVC ExternalIP(Terway版本≤1.2.0),SVC後端Pod和客戶端Pod配屬同一個ENI

環境

此處環境和 2.5小節 情況類似,不做過多描述,只是此小節是在terway 版本小於1.2.0 情況下,訪問External IP  47.243.139.183

82.png

核心路由

請參考2.5 小節。

由於客戶端Pod和被訪問的SVC的後端Pod同屬於同一個ENI,那麼在terway 版本小於1.2.0 的情況下,訪問External IP,實際上資料鏈路會通過ENI出ECS到External IP 的SLB,在被轉發到同一個ENI上。四層SLB目前是不支援同一個EI同時作為客戶端和服務端,所以會形成迴環,詳細資訊可以參考下面連線:https://help.aliyun.com/document_detail/97467.html#section-krj-kqf-14s

https://help.aliyun.com/document_detail/55206.htm

小結

83.png

資料鏈路轉發示意圖

  • 整個請求鏈路是 ECS1 POD1 -> ECS1 eth1 -> VPC -> SLB -> 中斷

  • Terway版本小於1.2.0時,叢集內訪問external IP,會出ECS ENI到SLB,再由SLB轉發到ECS ENI上,如果源pod所屬的ENI和被轉發的ENI為同一個,將訪問不成功,原因是四層SLB會形成迴環

  • 解決方案(任何一個):

  • 通過SVC annotation將SLB配置為7層監聽

  • 將Terway版本升級之1.2.0以及上,並開啟叢集內負載均衡。Kube-Proxy會短路叢集內訪問ExternalIP、LoadBalancer的流量,即叢集內訪問這些外部地址,實際流量不會到外部,而會被轉為對應後端的Endpoint直接訪問。在Terway IPvlan模式下,Pod訪問這些地址流量由Cilium而不是kube-proxy進行處理, 在Terway v1.2.0之前版本並不支援這種鏈路的短路。在Terway v1.2.0版本釋出後,新建叢集將預設開啟該功能,已建立的叢集不會開啟。(此處就是 2.5小節場景)https://help.aliyun.com/document_detail/197320.htm

https://help.aliyun.com/document_detail/113090.html#p-lim-520-w07

2.9 場景九:叢集內Pod訪問的SVC ExternalIP(Terway版本≤1.2.0),SVC後端Pod和客戶端Pod配屬不同ENI(同ECS)

環境

此處環境和 2.6小節 情況類似,不做過多描述,只是此小節是在terway 版本小於1.2.0 情況下,訪問External IP  47.243.139.183

84.png

核心路由

請參考2.6 和 2.8 小節。

由於客戶端Pod和被訪問的SVC的後端Pod雖然同屬於同一個ECS,但是不屬於同一個ENI,那麼在terway 版本小於1.2.0 的情況下,訪問External IP,實際上資料鏈路會通過客戶端pod ENI出ECS到External IP 的SLB,在被轉發到另一個一個ENI上。雖然從外部感知上看 兩個客戶端Pod和SVC的後端Pod都是在同一個ECS,但是由於屬於不同ENI,所以不會形成迴環,可以訪問成功,此處的結果和2.8 小節完全不同,需要注意。

小結

85.png

資料鏈路轉發示意圖

  • 整個請求鏈路是 ECS1 POD1 -> ECS1 eth1 -> VPC -> SLB -> ECS1 eth2 -> ECS1 POD2

  • Terway版本小於1.2.0時,叢集內訪問external IP,會出ECS ENI到SLB,再由SLB轉發到ECS ENI上,如果源pod所屬的ENI和被轉發的ENI為同一個,將訪問不成功,原因是四層SLB會形成迴環

  • 如果源pod所屬的ENI和被轉發的ENI為是同一個節點上的不同ENI,可以訪問成功

2.10 場景十:叢集內Pod訪問的SVC ExternalIP(Terway版本≤1.2.0),SVC後端Pod和客戶端Pod部署於不同ECS

環境

此處環境和 2.6小節 情況類似,不做過多描述,只是此小節是在terway 版本小於1.2.0 情況下,訪問External IP  47.243.139.183

86.png

核心路由

請參考2.7  和 2.9 小節。

此處和2.7的架構場景相似,都是客戶端Pod和SVC的後端Pod不屬於不同的ECS節點, 客戶端去訪問SVC 的External IP。只有Terway 的版本不同,2.7小節 Terway 版本是≥1.2.0,此小節是<1.2.0,僅僅是Terway 版本和eniconfig的不同,兩者訪問鏈路一個會經過SLB,一個則不會經過SLB,這一點需要關注。置於不同的原因是因為1.2.0 Terway 版本之後開啟叢集內負載均衡,對於訪問ExternalIP 會被負載到Service網段,具體資訊請見 2.8 小節。

小結

87.png

資料鏈路轉發示意圖

  • 整個請求鏈路是 ECS1 POD1 -> ECS1 eth1 -> VPC -> SLB -> ECS2 eth1 -> ECS2 POD2

  • Terway版本小於1.2.0時,叢集內訪問external IP,會出ECS ENI到SLB,再由SLB轉發到ECS ENI上,如果源pod所屬的ENI和被轉發的ENI為同一個,將訪問不成功,原因是四層SLB會形成迴環

2.11 場景十一:叢集外訪問SVC ExternalIP

環境

88.png

cn-hongkong.10.0.3.15  節點上存在 nginx-7d6877d777-j7dqz, IP分為 10.0.3.34通過describe svc 可以看到 nginx pod 被加入到了 svc nginx 的後端。SVC 的CLusterIP是192.168.27.242。

89.png

核心路由

在SLB控制檯,可以看到 lb-j6cj07oi6uc705nsc1q4m 虛擬伺服器組的後端伺服器組是兩個後端nginx pod 的的ENI eni-j6cgs979ky3evp81j3n8

90.png

從叢集外部角度看,SLB的後端虛擬伺服器組是SVC的後端Pod所屬的ENI網絡卡,內網的IP 地址就是Pod的地址

小結

91.png

資料鏈路轉發示意圖

  • ExternalTrafficPolicy 為Local或Cluster模式下, SLB只會將 pod分配的ENI掛在到SLB的虛擬伺服器組

  • 資料鏈路:client ->  SLB  -> Pod ENI + Pod Port  ->  ECS1 Pod1 eth0

總結

本篇文章主要聚焦ACK 在Terway IPVLAN+EBPF模式下,不同SOP場景下的資料鏈路轉發路徑。伴隨著客戶對效能極致追求的需求,在Terway IPVLAN+EBPF相比Terway ENI,有更高的Pod密度;相比Terway ENIIP,有更高的效能,但因此也帶了網路鏈路的複雜性和可觀測性帶來了調整,此場景可以分為11個SOP場景,並對這11個場景的轉發鏈路,技術實現原理,雲產品配置等一一梳理並總結,這對我們遇到Terway IPVLAN架構下的鏈路抖動、最優化配置,鏈路原理等提供了初步指引方向。在Terway IPVLAN模式下,利用EBPF和IPVLAN隧道,避免了資料鏈路在ECS OS核心協議棧的轉發,這必然帶來了更高的效能,同時也有ENIIP模式一樣的多IP共享ENI的方式來保證Pod密度。但是隨著業務場景越來越趨於複雜,業務的ACL管控也更加趨於Pod維度去管理,比如需要針對Pod維度進行安全ACL規則設定的需求等。下一系列我們將進入到Terway ENI-Trunking模式的全景解析——《ACK全景剖析阿里雲容器網路資料鏈路(五)—— Terway ENI-Trunking》。

點選此處檢視阿里雲容器服務