溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

發(fā)布時(shí)間:2022-01-07 14:51:05 來(lái)源:億速云 閱讀:135 作者:iii 欄目:云計(jì)算

本篇內(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)”吧!

Pod 之間 Container-to-Container networking

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 通往外面的世界。

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

在 Pod 世界里所有其中的容器共享一個(gè) NS,這些容器都有相同的 IP 和 Port 空間,通過 localhost 訪問也是互通的。Shared storage 也是可以訪問的,通過 SharedVolume 掛載到容器中。如下一個(gè) NS per pod 圖例:

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

同 Node 中 Pod-to-Pod networking

先看同一個(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)了,如圖:

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

有了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è)備上。如圖:

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

跨 Node 之間 Pod-to-Pod networking

進(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 的通訊如圖:

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

Pod-to-Service networking

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)景。

使用 DNS

每個(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

CNI

容器網(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)一管控下完成。

Overlay networking: Flannel

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ā)送至flannel0docker0最后到達(dá)目標(biāo)容器 IP 地址上。下圖示意流程:

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

值得一提是,容器 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)化。

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

L3 networking: Calico

Calico 是 L3 Routing 上非常流行容器網(wǎng)絡(luò)架構(gòu)方案。主要組件是 Felix,BIRD 和 BGP Route Reflector。Felix 和 BIRD 均是運(yùn)行在 Node 上的 deamon 程序。架構(gòu)簡(jiǎn)要:

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xià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ā):

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

L3 networking:Terway

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

    • ENIMultiIPVPCIP均是采用vethDriver的鏈路模式,步驟包括:

    • VPCENI稍有不同是為每個(gè) Pod 在 VPC 平面上綁定一個(gè) eni,其中包括兩次NetnsDriver接口調(diào)用:

綜上圖示:

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

為什么需要支持上述三種網(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ò):

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

VPC IP 網(wǎng)絡(luò):

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xiàn)

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è)startCheckIdleTickergoroutine 會(huì)定期掃描地址池的MaxPoolSizeMinPoolSize水位,在低于和高出水位閥值時(shí)會(huì)對(duì)地址池 eniIP 資源進(jìn)行進(jìn)行創(chuàng)建和釋放,使得地址池 IP 資源處于一個(gè)可控水位范圍中。為了保證資源狀態(tài)一致性,有一個(gè)startGarbageCollectionLoopgoroutine會(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)述:

Kubernetes容器網(wǎng)絡(luò)模型怎么實(shí)現(xià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í)!

向AI問一下細(xì)節(jié)

免責(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)容。

AI