您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)”吧!
Linux networking namespace 為進(jìn)程通訊提供了一個(gè)邏輯網(wǎng)絡(luò)棧,包括 network devices、routes、firewall rules。Network namespace(NS)管理實(shí)際是為其中的所有進(jìn)程提供了一個(gè)獨(dú)立的邏輯網(wǎng)絡(luò) Stack。
缺省情況下,Linux 將每個(gè)進(jìn)程掛載在 Root NS 下,這些進(jìn)程通過 eth0 通往外面的世界。
在 Pod 世界里所有其中的容器共享一個(gè) NS,這些容器都有相同的 IP 和 Port 空間,通過 localhost 訪問也是互通的。Shared storage 也是可以訪問的,通過 SharedVolume 掛載到容器中。如下一個(gè) NS per pod 圖例:
先看同一個(gè) Node 下 Pod 之間的 networking 如何實(shí)現(xiàn)?答案是通過Virtual Ethernet Device (or veth pair)
的兩塊 Virtual interfaces,每塊 veth 掛載在一個(gè) NS 上,來(lái)實(shí)現(xiàn)跨 NS 的連接。比如,一塊掛在 Root NS(host)上,另一塊掛在 Pod NS 上,好比一根網(wǎng)線把兩個(gè)在不同網(wǎng)絡(luò)空間的 traffic 連接起來(lái)了,如圖:
有了veth pair
這條網(wǎng)線,Pods 網(wǎng)絡(luò)可以連通到 Root NS 了,但在 Root NS 上如何實(shí)現(xiàn)對(duì)來(lái)自不同 Pod 的 packet 通訊呢?答案是通過Linux Ethernet Bridge
,一個(gè)虛擬的 Layer2 網(wǎng)絡(luò)設(shè)備來(lái)實(shí)現(xiàn)不同 network segments 之間的 Ethernet packet switching。不得不提這個(gè) old-school 協(xié)議:ARP,實(shí)現(xiàn)了 MAC 地址到 IP 地址的發(fā)現(xiàn)協(xié)議。Bridge 廣播 ethframe 到所有連接的設(shè)備(除發(fā)送者外),收到 ARP 回復(fù)后將 packet forward 到對(duì)應(yīng) veth 設(shè)備上。如圖:
進(jìn)入這部分之前,先提及 K8s 在其(Pod)networking 設(shè)計(jì)上的 3 個(gè) fundamental requirements,任何 networking 部分的實(shí)現(xiàn)都必須遵循這三個(gè)需求。
在不使用 NAT 下,所有 Pods 都能和其它任何 Pods 通訊
在不使用 NAT 下,所有 Nodes 都能和所有 Pods 通訊
Pod 所看到自己的 IP 和其它 Pods 看到它的 IP 一定是相同的
簡(jiǎn)要來(lái)看,K8s 網(wǎng)絡(luò)模型要求 Pod IP 在整個(gè)網(wǎng)絡(luò)中都能通達(dá)。具體實(shí)現(xiàn)方案有三方面:
Layer2(Switching)Solution
Layer3(Routing)Solution,如,Calico, Terway
Overlay Solution,如Flannel
這部分下文介紹,目前且認(rèn)為 Pod IP 的網(wǎng)絡(luò)通達(dá)性是確保的。
在 Pod 獲得 IP 之前,kubelet 為每個(gè) Node 分配一個(gè) CIDR 地址段(Classless inter-domain routing),每個(gè) Pod 在其中獲取唯一 IP,CIDR 地址塊的大小對(duì)應(yīng)于每個(gè) Node 的最大 Pod 數(shù)量(默認(rèn) 110 個(gè))。在 Pod IP 和跨 Node 網(wǎng)絡(luò)層部署成功后,從源 Pod1 到目的 Pod4 的通訊如圖:
K8s Service 管理服務(wù)的 Pods 狀態(tài),在 Pod 有變化下管理對(duì)應(yīng) IP 的變化,并管理對(duì)外提供服務(wù)的 Virtual IP 到 Pod IPs 路由訪問,實(shí)現(xiàn)外部對(duì)服務(wù) Virtual IP 的訪問路由到 Pod IP,以此屏蔽外部對(duì)服務(wù)后端的實(shí)現(xiàn)形態(tài)。所以在服務(wù)創(chuàng)建時(shí),會(huì)對(duì)應(yīng)生成一個(gè) Virtual IP(也即是 Cluster IP),任何對(duì)該 Virtual IP 的訪問將打散路由到服務(wù)所屬的 Pods 上。
K8s 的服務(wù)是如何實(shí)現(xiàn)對(duì) Virtual IP 的訪問負(fù)載均衡呢?答案是 netfilter 和 iptables。netfilters 是 Linux built-in networking framework,為 Linux 提供網(wǎng)絡(luò)包過濾、NAT 和 Port translation 等豐富的自定義 handler 實(shí)現(xiàn)。iptables 是運(yùn)行在 Linux user-space 的規(guī)則管理系統(tǒng),為 netfilter 框架提供豐富的包轉(zhuǎn)發(fā)規(guī)則管理。
在 K8s 實(shí)現(xiàn)中 kube-proxy(node deamon)通過 watch apiserver 來(lái)獲得服務(wù)配置的變化,比如,服務(wù)的 Virtual IP 變化、Pod IP 變化(ie, pod up/down)。iptables 規(guī)則隨之變化并將請(qǐng)求路由到服務(wù)對(duì)應(yīng)的 Pod 上,Pod IP 選取是隨機(jī)的,這樣看 iptables 起到了 Pod 負(fù)載均衡作用。在訪問請(qǐng)求 Return path 上,iptables 會(huì)做一次 SNAT 以替換 IP header 的 Pod IP 為服務(wù) Virtual IP,這樣使得 Client 看起來(lái)請(qǐng)求僅在服務(wù) Virtual IP 上進(jìn)行通訊。
從 K8S v1.11 中 IPVS(IP Virtual Server)被引入成為第二種集群內(nèi)負(fù)載均衡方式。IPVS 同樣也是構(gòu)建基于 netfilter 之上,在創(chuàng)建服務(wù)定義時(shí)可指定使用 iptables 或 IPVS。IPVS 是特定適合于服務(wù)負(fù)載均衡的解決方案,提供了非常豐富的均衡算法應(yīng)用場(chǎng)景。
每個(gè)服務(wù)會(huì)設(shè)置一個(gè) DNS 域名,kubelets
為每個(gè)容器進(jìn)行配置--cluster-dns=<dns-service-ip>
,用以解析服務(wù)所對(duì)應(yīng) DNS 域名到對(duì)應(yīng)的 Cluster IP 或 Pod IP。1.12 后 CoreDNS 成為缺省 DNS 方式。服務(wù)支持 3 種類型 DNS records(A record、CNAME、SRV records)。其中常用的是 A Records,比如,在cluster.local
的 DNS name 下,A record 格式如pod-ip-address.my-namespace.pod.cluster.local
,其中 Pod hostname和subdomain 字段可以設(shè)置為標(biāo)準(zhǔn)的 FQDN 格式,比如,custom-host.custom-subdomain.my-namespace.svc.cluster.local
容器網(wǎng)絡(luò)模型在實(shí)現(xiàn)上是由 K8s 的節(jié)點(diǎn) Pod 資源管控(kubelet)和遵從 Container Networking Interface(CNI)標(biāo)準(zhǔn)的插件共同協(xié)作完成的。CNI 插件程序在其中充當(dāng)了"膠水"作用:各種容器網(wǎng)絡(luò)實(shí)現(xiàn)能在一致的操作接口下由 kubelet 統(tǒng)一管控調(diào)度。另外,多個(gè)容器網(wǎng)絡(luò)也能共存于一個(gè)集群內(nèi),為不同 Pod 的網(wǎng)絡(luò)需求提供服務(wù),都是在 kubelet 的統(tǒng)一管控下完成。
Flannel 是 CoreOS 為 K8s networking 開發(fā)的解決方案,也是阿里云 ACK 產(chǎn)品支持的容器網(wǎng)絡(luò)解決方案。Flannel 的設(shè)計(jì)原理很簡(jiǎn)潔,在 host 網(wǎng)絡(luò)之上創(chuàng)建另一個(gè)扁平網(wǎng)絡(luò)(所謂的 overlay),在其上地址空間中給每個(gè) pod 容器設(shè)置一個(gè) IP 地址,并用此實(shí)現(xiàn)路由和通訊。
主機(jī)內(nèi)容器網(wǎng)絡(luò)在 docker bridge docker0
上完成通訊,不再贅述。主機(jī)間通訊使用內(nèi)核路由表和 IP-over-UDP 封裝進(jìn)行實(shí)現(xiàn)。容器 IP 包流經(jīng) docker bridge 會(huì)轉(zhuǎn)發(fā)到flannel0
網(wǎng)卡(TUN)設(shè)備上,進(jìn)而流入到flanneld
進(jìn)程中。flanneld
會(huì)對(duì) packet 目標(biāo) IP 地址所屬的網(wǎng)段信息查詢其對(duì)應(yīng)的下一跳
主機(jī) IP,容器子網(wǎng) CIDR 和所屬主機(jī) IP 的映射(key-value)保存在 etcd 中,flanneld
查詢得到 packet 目標(biāo) IP 所屬的主機(jī) IP 地址后,會(huì)將 IP packet 封裝到一個(gè) UDP payload 中并設(shè)置 UDP packet 目標(biāo)地址為所得到的目標(biāo)主機(jī) IP,最后在 host 網(wǎng)絡(luò)中發(fā)送出 UDP packet。到達(dá)目標(biāo)主機(jī)后,UDP packet 會(huì)流經(jīng)flanneld
并在這里解封出 IP packet,再發(fā)送至flannel0
、docker0
最后到達(dá)目標(biāo)容器 IP 地址上。下圖示意流程:
值得一提是,容器 CIDR 和下一跳主機(jī) IP 的映射條目容量沒有特殊限制。在阿里云 ACK 產(chǎn)品上該條目容量需要在 VPC/vSwitch 控制面中進(jìn)行分發(fā),考慮到整體性能因素,在數(shù)量上做了一定數(shù)量限制(缺省 48 個(gè))。但在自建主機(jī)網(wǎng)絡(luò)部署中,該數(shù)量限制就不會(huì)明顯了,因?yàn)橹鳈C(jī)下一跳主機(jī)網(wǎng)絡(luò)在一個(gè)大二層平面上。
Flannel 新版本 backend 不建議采用 UDP 封裝方式,因?yàn)?traffic 存在 3 次用戶空間與內(nèi)核空間的數(shù)據(jù)拷貝,(如下圖)性能上存在比較大的損耗。新版本推薦用 VxLan 和云服務(wù)商版本的 backends 進(jìn)行優(yōu)化。
Calico 是 L3 Routing 上非常流行容器網(wǎng)絡(luò)架構(gòu)方案。主要組件是 Felix,BIRD 和 BGP Route Reflector。Felix 和 BIRD 均是運(yùn)行在 Node 上的 deamon 程序。架構(gòu)簡(jiǎn)要:
Felix 完成網(wǎng)卡的管理和配置,包括 Routes programming 和 ACLs。實(shí)現(xiàn)路由信息對(duì) Linux kernel FIB 的操作和 ACLs 的管理操作。由于 Felix 功能完整性和運(yùn)行獨(dú)立性非常好,其功能作為 Off-the-shelf 被集成到阿里云 Terway 網(wǎng)絡(luò)插件中,實(shí)現(xiàn)其網(wǎng)絡(luò)策略功能。
BIRD(BGP client)完成內(nèi)核路由 FIB 條目向集群網(wǎng)絡(luò)側(cè)分發(fā),使其路由條目對(duì)所有網(wǎng)絡(luò)節(jié)點(diǎn)中可見,并實(shí)現(xiàn) BGP 路由協(xié)議功能。每一個(gè) BGP client 會(huì)連接到網(wǎng)絡(luò)中其它 BGP client,這對(duì)規(guī)模較大的部署會(huì)是明顯的瓶頸(due to the N^2 increase nature)。鑒于該限制引入了 BGP Route Reflector 組件,實(shí)現(xiàn) BGP clients 路由信息在匯聚層上再進(jìn)行分發(fā)(propagation)。在集群網(wǎng)站中 Reflector 組件可以部署多個(gè),完全能于部署規(guī)模大小來(lái)決定。Reflector 組件僅僅執(zhí)行路由信令和條目的分發(fā),其中不涉及任何數(shù)據(jù)面流量。路由匯聚層分發(fā):
Terway 是阿里云自研 CNI 插件,提供了阿里云 VPC 互通和方便對(duì)接阿里云產(chǎn)品的基礎(chǔ)設(shè)施,沒有 overlay 網(wǎng)絡(luò)帶來(lái)的性能損耗,同時(shí)提供了簡(jiǎn)單易用的 backend 功能。
Terway 功能上可分為三部分:1. CNI 插件,一個(gè)獨(dú)立的 binary 運(yùn)行程序;2. Backend Server(也稱為daemon),程序以獨(dú)立 daemonSet 方式運(yùn)行在每個(gè) Node 上;3. Network Policy,完全集成了 Calico Felix 實(shí)現(xiàn)。
CNI 插件 binary 是通過 daemonSet 部署中 initContainer 安裝到所有節(jié)點(diǎn)上,實(shí)現(xiàn)了ADD
、DEL
、CHECK
三個(gè)接口供 kubelet 調(diào)用。這里以一個(gè) Pod 在創(chuàng)建過程中的網(wǎng)絡(luò) setup 步驟來(lái)說明:
當(dāng)一個(gè) Pod 被調(diào)度到節(jié)點(diǎn)上時(shí),kubelet 監(jiān)聽到 Pod 創(chuàng)建在自己節(jié)點(diǎn)上,通過 runtime(docker...)創(chuàng)建 sandbox 容器來(lái)打通所需 namespace。
kubelet 調(diào)用插件 binary 的cmdAdd
接口,插件程序?qū)涌趨?shù)設(shè)置檢查后,向 backendServer 發(fā)起AllocIP
調(diào)用。
backendServer 程序的networkService
根據(jù) Pod 的網(wǎng)絡(luò)類型進(jìn)行相應(yīng)的 Pod IP 申請(qǐng),支持三種網(wǎng)絡(luò)類型ENIMultiIP
、VPCENI
、VPCIP
:
ENIMultiIP
是 eni 網(wǎng)卡帶多 IP 類型,由networkService
中的ResourceManager
在自己的 IP 地址池中進(jìn)行 IP 地址分配
VPCENI
是為 Pod 創(chuàng)建和掛載一個(gè) eni,由networkService
中的allocateENI
向阿里云 Openapi 發(fā)起對(duì)所屬 ecs 實(shí)例的 eni 創(chuàng)建、掛載,并獲得對(duì)應(yīng) eni IP 地址
VPCIP
是為 Pod 在 VPC 網(wǎng)絡(luò)平面上分配一個(gè) IP 地址,這是在插件程序中通過調(diào)用ipam
接口從 vpc 管控面獲取的 IP 地址
在 backendServer 返回AllocIP
調(diào)用(IP 地址)結(jié)果后,插件調(diào)用不同網(wǎng)絡(luò)類型下的NetnsDriver``Setup
接口實(shí)現(xiàn)來(lái)完成從容器網(wǎng)卡通往主機(jī)網(wǎng)卡的鏈路設(shè)置,其中:
vethDriver
rawNicDriver
(主要實(shí)現(xiàn) VPC 平面網(wǎng)絡(luò)路由設(shè)置,包括缺省路由和網(wǎng)關(guān)等配置)
Create veth pair
Add IP addr for container interface
Add routes
Host side namespace config
Add host routes and rules
ENIMultiIP
和VPCIP
均是采用vethDriver
的鏈路模式,步驟包括:
VPCENI
稍有不同是為每個(gè) Pod 在 VPC 平面上綁定一個(gè) eni,其中包括兩次NetnsDriver
接口調(diào)用:
綜上圖示:
為什么需要支持上述三種網(wǎng)絡(luò)類型?根本上是由阿里云 vpc 網(wǎng)絡(luò)基礎(chǔ)設(shè)施所決定,同時(shí)覆蓋阿里云主流應(yīng)用對(duì) vpc 網(wǎng)絡(luò)資源的使用場(chǎng)景需求。另一方面是對(duì)標(biāo) Amazon AWS 的容器網(wǎng)絡(luò)解決方案,在基于 VPC 和 ENI 的網(wǎng)絡(luò)設(shè)施上能支持同等功能。
ENI 多 IP、VPC ENI 和 VPC IP 的主要區(qū)別在于前兩者下的 Pod 網(wǎng)段和 VPC 網(wǎng)段是相同的,而 VPC IP 的網(wǎng)段和節(jié)點(diǎn)的宿主機(jī)網(wǎng)段不同。這樣使得在 ENI 網(wǎng)絡(luò)環(huán)境下的 IP 路由完全在 VPC 的 L2 網(wǎng)絡(luò)平面上進(jìn)行,而 VPC IP 網(wǎng)絡(luò)需要在 VPC 路由表中進(jìn)行配置 Pod 網(wǎng)段的下一跳主機(jī),和 Flannel 的路由模式類似??梢钥闯觯珽NI 網(wǎng)絡(luò)能帶來(lái)更靈活的路由選擇和更好的路由性能。如下兩個(gè)截圖反映其不同路由特點(diǎn):
VPC ENI 網(wǎng)絡(luò):
VPC IP 網(wǎng)絡(luò):
ENI 多 IP(1 個(gè)主 IP/多個(gè)輔助 IP)網(wǎng)絡(luò)下有 2 種路由模式:veth策略路由
和ipvlan
。兩者本質(zhì)區(qū)別在于使用不同的路由模式,前者使用veth pair
的策略路由,后者使用ipvlan
網(wǎng)絡(luò)路由。策略路由需要在節(jié)點(diǎn)上配置策略路由條目來(lái)保證輔助 IP 的流量經(jīng)過它所屬的彈性網(wǎng)卡。ipvlan
實(shí)現(xiàn)了一個(gè)網(wǎng)卡虛擬出多個(gè)子網(wǎng)卡和不同的 IP 地址,eni 將其輔助 IP 綁定到這些虛擬出來(lái)的子網(wǎng)卡上形成一個(gè)與 vpc 平面打通的 L3 網(wǎng)絡(luò)。這種模式使 ENI 多 IP 的網(wǎng)絡(luò)結(jié)構(gòu)比較簡(jiǎn)單,性能相對(duì)veth策略路由
網(wǎng)絡(luò)也更好。兩種網(wǎng)絡(luò)模式切換通過配置即可完成(缺省是vethpair
):
值得一提的是 Terway 還實(shí)現(xiàn)了 ENI 多 IP 地址資源池的管理和分配機(jī)制。networkService
中的eniIPFactory
為每個(gè) eni 網(wǎng)卡創(chuàng)建一個(gè) goroutine,該 eni 網(wǎng)卡上的 eniIP 的分配釋放都在這個(gè) goroutine 中完成。在創(chuàng)建一個(gè) eniIP 時(shí)掃描已經(jīng)存在的 eni 網(wǎng)卡,如該 eni 還存在空閑的 eniIP,該 goroutine 會(huì)通過ipResultChan
返回給eniIPFactory
一個(gè)分配的 IP。如果所有的 eni 網(wǎng)卡的 eniIP 都分配完畢,會(huì)先創(chuàng)建一個(gè)新的 eni 網(wǎng)卡和對(duì)應(yīng)的 goroutine,首次創(chuàng)建 eni 網(wǎng)卡時(shí)無(wú)需做 IP 分配,直接返回 eni 網(wǎng)卡主 IP 即可。eniIP 釋放是逆向的,在 eni 網(wǎng)卡的最后一個(gè) eniIP 釋放時(shí),整個(gè) eni 網(wǎng)卡資源會(huì)釋放掉。
另外,有一個(gè)startCheckIdleTicker
goroutine 會(huì)定期掃描地址池的MaxPoolSize
和MinPoolSize
水位,在低于和高出水位閥值時(shí)會(huì)對(duì)地址池 eniIP 資源進(jìn)行進(jìn)行創(chuàng)建和釋放,使得地址池 IP 資源處于一個(gè)可控水位范圍中。為了保證資源狀態(tài)一致性,有一個(gè)startGarbageCollectionLoop
goroutine會(huì)定期掃描 IP 地址是否在用或過期狀態(tài),如檢測(cè)到會(huì)進(jìn)行資源 GC 操作。最后,Pod 資源狀態(tài)數(shù)據(jù)都持久化在本地的一個(gè)boltDB
文件中/var/lib/cni/terway/pod.db
,即使 Pod 已經(jīng)在 apiServer 中刪除,GetPod
會(huì)從本地boltDB
中讀取副本數(shù)據(jù)。在 Pod 已經(jīng)刪除但副本還存在 DB 的情況下,GC goroutine檢 測(cè)到會(huì)執(zhí)行清理。截圖簡(jiǎn)述:
到此,相信大家對(duì)“Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。