【Kubernetes系列】第10篇 網路原理解析(下篇)
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維護⽹絡的分配情況。
這⾥我們注意到它和之前我們看到的設施是⼀樣的,只是在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)。
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 service物件中的label選擇器
整個虛擬IP的實現實際上是⼀組iptables(最新版本可以選擇使⽤IPVS,但這是另⼀個討論)規則,由Kubernetes元件kube-proxy管理。這個名字現在實際上是誤導性的。它在v 1.0之前確實是⼀個代理,並且由於其實現是核心空間和⽤戶空間之間的不斷複製,它變得⾮常耗費資源並且速度較慢。現在,它只是⼀個控制器,就像Kubernetes中的許多其它控制器⼀樣,它watch api serverendpoint的更改並相應地更新iptables規則。
Iptables DNAT
有了這些iptables規則,每當資料包發往Service IP時,它就進⾏DNAT(DNAT=⽬標⽹絡地址轉換)操作,這意味著⽬標IP從Service IP更改為其中⼀個Endpoint - Pod IP - 由iptables隨機選擇。這可確保負載均勻分佈在後端Pod中。
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
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69947382/viewspace-2664851/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【Kubernetes系列】第9篇 網路原理解析(上篇)
- mybatis系列第1篇:框架原理MyBatis框架
- kubernetes網路解析
- 【Kubernetes系列】第7篇 CI/CD之元件部署元件
- 【Kubernetes系列】第2篇 基礎概念介紹
- vLan網路原理解析
- [HTTP 系列] 第 1 篇 —— 從 TCP/UDP 到 DNS 解析HTTPTCPUDPDNS
- 【Kubernetes系列】第8篇 CI/CD之全流程實踐
- 網路 - DNS解析過程原理DNS
- kubernetes實踐之二十:網路原理
- 【線上公開課】Kubernetes實戰系列三??原理篇
- 【深度學習原理第4篇】卷積神經網路詳解(CNN)深度學習卷積神經網路CNN
- Andfix熱修復框架原理及原始碼解析-下篇框架原始碼
- OKHttp網路請求原理流程解析HTTP
- 深入解析 Apache BookKeeper 系列:第二篇 — 寫操作原理Apache
- 【Kubernetes系列】第5篇 Ingress controller - traefik元件介紹Controller元件
- 【Kubernetes系列】第6篇 Ingress controller - nginx元件介紹ControllerNginx元件
- 瀏覽器原理系列10篇正式完結瀏覽器
- ES系列(三):網路通訊模組解析
- 【kubernetes】網路虛擬網路卡對veth pair、flannel網路模型實現原理AI模型
- webpack系列之-原理篇Web
- Windows提權系列————下篇Windows
- Android原始碼解析Handler系列第(四)篇 --- 打破Handler那些困惑事兒Android原始碼
- Android原始碼解析Handler系列第(五)篇 ---HandlerThread你用過嗎?Android原始碼thread
- Kubernetes(k8s)底層網路原理刨析K8S
- 卷積神經網路數學原理解析卷積神經網路
- CSS原理解析之模型篇CSS模型
- [blockly 系列] 第 1 篇 環境搭建BloC
- Spark in action on Kubernetes - Spark Operator的原理解析Spark
- 快速Android開發系列網路篇之RetrofitAndroid
- Kubernetes網路概述
- OkHttp原理解析1(框架流程篇)HTTP框架
- 懂你網路系列10之網路安全中的CSRF攻擊
- 第 10 篇 評論介面
- K8S系列第三篇(Docker網路)K8SDocker
- Nuxt3實戰系列之網路請求篇UX
- 快速Android開發系列網路篇之VolleyAndroid
- Kubernetes網路解決方案技術原理深入剖析-Kubernetes商業環境實戰