【Kubernetes系列】第10篇 網路原理解析(下篇)

HankerCloud發表於2019-11-28

03 覆蓋網路


覆蓋⽹絡(overlay network)是將TCP資料包裝在另⼀種⽹絡包⾥⾯進⾏路由轉發和通訊的技術。Overlay⽹絡不是預設必須的,但是它們在特定場景下⾮常有⽤。⽐如當我們沒有⾜夠的IP空間,或者⽹絡⽆法處理額外路由,抑或當我們需要Overlay提供的某些額外管理特性。⼀個常⻅的場景是當雲提供商的路由表能處理的路由數是有限制時,例如AWS路由表最多⽀持50條路由才不⾄於影響⽹絡效能。因此如果我們有超過50個Kubernetes節點, AWS路由表將不夠。這種情況下,使⽤Overlay⽹絡將幫到我們。

本質上來說, Overlay就是在跨節點的本地⽹絡上的包中再封裝⼀層包。你可能不想使⽤Overlay⽹絡,因為它會帶來由封裝和解封所有報⽂引起的時延和複雜度開銷。通常這是不必要的,因此我們應當在知道為什麼我們需要它時才使⽤它。

為了理解Overlay⽹絡中流量的流向,我們拿Flannel做例⼦,它是CoreOS 的⼀個開源項⽬。Flannel透過給每臺宿主機分配⼀個⼦⽹的⽅式為容器提供虛擬⽹絡,它基於Linux TUN/TAP,使⽤UDP封裝IP包來建立overlay⽹絡,並藉助etcd維護⽹絡的分配情況。

Kubernetes Node with route table (透過Flannel Overlay網路進行跨節點的Pod-to-Pod通訊)

這⾥我們注意到它和之前我們看到的設施是⼀樣的,只是在root netns中新增了⼀個虛擬的以太⽹裝置,稱為flannel0。它是虛擬擴充套件⽹絡Virtual Extensible LAN(VXLAN)的⼀種實現,但是在Linux上,它只是另⼀個⽹絡接⼝。

從pod1到pod4(在不同節點)的資料包的流向類似如下:

1)它由pod1中netns的eth0⽹⼝離開,透過vethxxx進⼊root netns。
2)然後被傳到cbr0, cbr0透過傳送ARP請求來找到⽬標地址。
3)資料封裝

3a. 由於本節點上沒有Pod擁有pod4的IP地址,因此⽹橋把資料包傳送給了flannel0,因為節點的路由表上flannel0被配成了Pod⽹段的⽬標地址。

3b. flanneld daemon和Kubernetes apiserver或者底層的etcd通訊,它知道所有的Pod IP,並且知道它們在哪個節點上。因此Flannel建立了Pod IP和Node IP之間的對映(在⽤戶空間)。flannel0取到這個包,並在其上再⽤⼀個UDP包封裝起來,該UDP包頭部的源和⽬的IP分別被改成了對應節點的IP,然後傳送這個新包到特定的VXLAN端⼝(通常是8472)。

【Kubernetes系列】第10篇 網路原理解析(下篇)

Packet-in-packet encapsulation(notice the packet is encapsulated from 3c to 6b in previous diagram)

儘管這個對映發⽣在⽤戶空間,真實的封裝以及資料的流動發⽣在核心空間,因此仍然是很快的。

3c. 封裝後的包透過eth0傳送出去,因為它涉及了節點間的路由流量。

4. 包帶著節點IP資訊作為源和⽬的地址離開本節點。
5. 雲提供商的路由表已經知道了如何在節點間傳送報⽂,因此該報⽂被髮送到⽬標地址node2。
6. 資料解包

6a. 包到達node2的eth0⽹卡,由於⽬標端⼝是特定的VXLAN端⼝,核心將報⽂傳送給了
flannel0。
6b. flannel0解封報⽂,並將其傳送到 root 名稱空間下。從這⾥開始,報⽂的路徑和我們之前在Part1 中看到的⾮Overlay⽹絡就是⼀致的了。
6c. 由於IP forwarding開啟著,核心按照路由表將報⽂轉發給了cbr0。

7. ⽹橋獲取到了包,傳送ARP請求,發現⽬標IP屬於vethyyy。
8. 包跨過管道對到達pod4

這就是Kubernetes中Overlay⽹絡的⼯作⽅式,雖然不同的實現還是會有細微的差別。 有個常⻅的誤區是,當我們使⽤Kubernetes,我們就不得不使⽤Overlay⽹絡。事實是,這完全依賴於特定場景。因此請確保在確實需要的場景下才使⽤

04 動態叢集

由於Kubernetes(更通⽤的說法是分散式系統)天⽣具有不斷變化的特性,因此它的Pod(以及Pod的IP)總是在改變。變化的原因可以是針對不可預測的Pod或節點崩潰⽽進⾏的滾動升級和擴充套件。這使得Pod IP不能直接⽤於通訊。我們看⼀下Kubernetes Service,它是⼀個虛擬IP,並伴隨著⼀組Pod IP作為Endpoint(透過標籤選擇器識別)。它們充當虛擬負載均衡器,其IP保持不變,⽽後端Pod IP可能會不斷變化。

【Kubernetes系列】第10篇 網路原理解析(下篇)

Kubernetes service物件中的label選擇器

整個虛擬IP的實現實際上是⼀組iptables(最新版本可以選擇使⽤IPVS,但這是另⼀個討論)規則,由Kubernetes元件kube-proxy管理。這個名字現在實際上是誤導性的。它在v 1.0之前確實是⼀個代理,並且由於其實現是核心空間和⽤戶空間之間的不斷複製,它變得⾮常耗費資源並且速度較慢。現在,它只是⼀個控制器,就像Kubernetes中的許多其它控制器⼀樣,它watch api serverendpoint的更改並相應地更新iptables規則。


【Kubernetes系列】第10篇 網路原理解析(下篇)

Iptables DNAT

有了這些iptables規則,每當資料包發往Service IP時,它就進⾏DNAT(DNAT=⽬標⽹絡地址轉換)操作,這意味著⽬標IP從Service IP更改為其中⼀個Endpoint - Pod IP - 由iptables隨機選擇。這可確保負載均勻分佈在後端Pod中。

【Kubernetes系列】第10篇 網路原理解析(下篇)

conntrack表中的5元組條⽬

當這個DNAT發⽣時,這個資訊儲存在conntrack中——Linux連線跟蹤表(iptables規則5元組轉譯並完成儲存:protocol, srcIP, srcPort, dstIP, dstPort)。這樣當請求回來時,它可以un-DNAT,這意味著將源IP從Pod IP更改為Service IP。這樣,客戶端就不⽤關⼼後臺如何處理資料包流。

因此透過使⽤Kubernetes Service,我們可以使⽤相同的端⼝⽽不會發⽣任何衝突(因為我們可以將端⼝重新對映到Endpoint)。這使服務發現變得⾮常容易。我們可以使⽤內部DNS並對服務主機名進⾏硬編碼。

我們甚⾄可以使⽤Kubernetes提供的service主機和端⼝的環境變數來完成服務發現。

專家建議:採取第⼆種⽅法,你可節省不必要的DNS調⽤,但是由於環境變數存在建立順序的侷限性(環境變數中不包含後來建立的服務),推薦使⽤DNS來進⾏服務名解析。

4.1 出站流量

到⽬前為⽌我們討論的Kubernetes Service是在⼀個叢集內⼯作。但是,在⼤多數實際情況中,應⽤程式需要訪問⼀些外部api/website。通常,節點可以同時具有私有IP和公共IP。對於互聯⽹訪問,這些公共和私有IP存在某種1:1的NAT,特別是在雲環境中。對於從節點到某些外部IP的普通通訊,源IP從節點的專⽤IP更改為其出站資料包的公共IP,⼊站的響應資料包則剛好相反。但是,當Pod發出與外部IP的連線時,源IP是Pod IP,雲提供商的NAT機制不知道該IP。因此它將丟棄具有除節點IP之外的源IP的資料包。

因此你可能也猜對了,我們將使⽤更多的iptables!這些規則也由kube-proxy新增,執⾏SNAT(源⽹絡地址轉換),即IP MASQUERADE(IP偽裝)。它告訴核心使⽤此資料包發出的⽹絡接⼝的IP,代替源Pod IP同時保留conntrack條⽬以進⾏反SNAT操作。

4.2 入站流量

到⽬前為⽌⼀切都很好。Pod可以互相交談,也可以訪問互聯⽹。但我們仍然缺少關鍵部分 - 為⽤戶請求流量提供服務。截⾄⽬前,有兩種主要⽅法可以做到這⼀點:

  • NodePort /雲負載均衡器(L4 - IP和端⼝)

將服務型別設定為NodePort預設會為服務分配範圍為30000-33000d的nodePort。即使在特定節點上沒有運⾏Pod,此nodePort也會在每個節點上開啟。此NodePort上的⼊站流量將再次使⽤iptables傳送到其中⼀個Pod(該Pod甚⾄可能在其它節點上!)。

雲環境中的LoadBalancer服務型別將在所有節點之前建立雲負載均衡器(例如ELB),命中相同的nodePort。

  • Ingress(L7 - HTTP / TCP)

許多不同的⼯具,如Nginx, Traefik, HAProxy等,保留了http主機名/路徑和各⾃後端的對映。通常這是基於負載均衡器和nodePort的流量⼊⼝點,其優點是我們可以有⼀個⼊⼝處理所有服務的⼊站流量,⽽不需要多個nodePort和負載均衡器。

4.3 網站策略

可以把它想象為Pod的安全組/ ACL。NetworkPolicy規則允許/拒絕跨Pod的流量。確切的實現取決於⽹絡層/CNI,但⼤多數只使⽤iptables。

結束語:

⽬前為⽌就這樣了。在前⾯的部分中,我們研究了Kubernetes⽹絡的基礎以及overlay⽹絡的⼯作原理。現在我們知道Service抽象是如何在⼀個動態叢集內起作⽤並使服務發現變得⾮常容易。我們還介紹了出站和⼊站流量的⼯作原理以及⽹絡策略如何對叢集內的安全性起作⽤。

參考⽂章:

1、An illustrated guide to Kubernetes Networking - part1

2、An illustrated guide to Kubernetes Networking - part2

3、An illustrated guide to Kubernetes Networking - part3

【Kubernetes系列】第10篇 網路原理解析(下篇)


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69947382/viewspace-2664851/,如需轉載,請註明出處,否則將追究法律責任。

相關文章