李翔
(中遠(yuǎn)海運(yùn)科技股份有限公司 上海市 200135)
以Docker 為基礎(chǔ)的Kubernetes 容器集群近幾年發(fā)展迅猛,它極大地簡(jiǎn)化了容器集群的創(chuàng)建、集成、部署、運(yùn)維流程,從而推動(dòng)了容器技術(shù)在云端的大規(guī)模使用[1],越來(lái)越多的企業(yè)開始采用Kubernetes 集群來(lái)承載業(yè)務(wù)系統(tǒng)和運(yùn)維系統(tǒng)。對(duì)于在公有云(如AWS 、Google Cloud、阿里云等)中部署的Kubernetes 集群,負(fù)載均衡由云服務(wù)商提供,可以與公有云的內(nèi)部網(wǎng)絡(luò)實(shí)現(xiàn)完整集成,在集群內(nèi)部可以獲取負(fù)載均衡地址,并進(jìn)行管理。
對(duì)于部署于企業(yè)內(nèi)部機(jī)房的私有Kubernetes 集群,負(fù)載均衡就成為了一個(gè)難題。由于企業(yè)的內(nèi)部機(jī)房往往建設(shè)較早,缺乏相關(guān)的集成管理接口,從集群原生角度較難實(shí)現(xiàn)完整集成。通常的做法是將Kubernetes 集群中的服務(wù)以NodePort 方式進(jìn)行發(fā)布,在集群外部通過(guò)負(fù)載均衡的軟硬件(如F5、HAProxy 等)進(jìn)行負(fù)載均衡。此種方式雖然能實(shí)現(xiàn)負(fù)載均衡,但還存在一系列的問(wèn)題,例如:
(1)負(fù)載均衡IP 的管理獨(dú)立于Kubernetes 集群之外,為了保證負(fù)載均衡的正常工作,需要購(gòu)買專門的硬件(F5 等)或部署專門的軟件集群(HAProxy、Nginx 等);
(2)使用NodePort 方式提供服務(wù),相較Service/LoadBalance方式,因增加了數(shù)據(jù)傳輸鏈路的復(fù)雜度,傳輸性能會(huì)略有下降。有文獻(xiàn)指出,性能損失約7%[1]。
由開源社區(qū)實(shí)現(xiàn)的MetalLB,以原生方式在集群中實(shí)現(xiàn)了負(fù)載均衡IP 的動(dòng)態(tài)管理和流量分發(fā),為私有化集群的數(shù)據(jù)交換提供了一種新的方案。
Docker 使用了一個(gè)比較簡(jiǎn)單的網(wǎng)絡(luò)模型,即內(nèi)部的網(wǎng)橋加內(nèi)部的保留 IP,容器與外部網(wǎng)絡(luò)的數(shù)據(jù)交互通過(guò)網(wǎng)橋(docker0)來(lái)完成。在Kubernetes 集群中,采用了被稱為CNI(Container Network Interface)的網(wǎng)絡(luò)標(biāo)準(zhǔn)來(lái)完成通信。集群管理員通過(guò)采用不同的CNI插件(如Calico、Flannel、Weave 等)來(lái)完成網(wǎng)絡(luò)的構(gòu)建。
在單一主機(jī)中,Pod之間使用docker0網(wǎng)橋來(lái)直接進(jìn)行網(wǎng)絡(luò)交互,但在跨主機(jī),以及集群內(nèi)外部之間的數(shù)據(jù)交互,主要有兩種解決方案:
(1)通過(guò)修改系統(tǒng)底層的網(wǎng)絡(luò)配置,加入容器網(wǎng)絡(luò)IP 地址等,此方案通常需要與SDN(Software Define Networking)結(jié)合,以實(shí)現(xiàn)網(wǎng)絡(luò)的動(dòng)態(tài)配置;
(2)不修改底層的網(wǎng)絡(luò)配置,復(fù)用原有的網(wǎng)絡(luò)平面,采用如下兩種策略實(shí)現(xiàn)網(wǎng)絡(luò)互通:
在“一帶一路”倡議助推我國(guó)圖書出版業(yè)產(chǎn)業(yè)持續(xù)升級(jí)、合作模式不斷創(chuàng)新,帶動(dòng)外國(guó)作家創(chuàng)作與講述中國(guó)故事與中國(guó)主題并傳播中國(guó)文化的過(guò)程中,外國(guó)作家及作品對(duì)“一帶一路”文化進(jìn)行現(xiàn)代闡釋的積極意義不言而喻。
圖1:Kubernetes 集群網(wǎng)絡(luò)簡(jiǎn)圖
1.修改主機(jī)路由:將容器網(wǎng)絡(luò)加入主機(jī)路由表,通過(guò)路由轉(zhuǎn)發(fā)實(shí)現(xiàn)三層互通。支持此方案的網(wǎng)絡(luò)插件有Calico、Flannel 等;
2.采用隧道傳輸:對(duì)容器數(shù)據(jù)包進(jìn)行封裝,使用主機(jī)的網(wǎng)絡(luò)傳輸至目標(biāo)主機(jī),目標(biāo)主機(jī)收到數(shù)據(jù)包后進(jìn)行拆包,再傳遞給對(duì)應(yīng)的容器。常見(jiàn)的隧道協(xié)議有ipip、VxLAN 等,支持此方案的網(wǎng)絡(luò)插件有Flannel 等。
Service 從本質(zhì)上來(lái)說(shuō),是一種內(nèi)部的負(fù)載均衡實(shí)現(xiàn)。它擁有一個(gè)虛擬IP(Cluster IP),以及一個(gè)用于集群內(nèi)部訪問(wèn)的域名。Service 代理了功能相同的一系列Pod 組成的后端的訪問(wèn),所有到達(dá)Service 的請(qǐng)求會(huì)按照負(fù)載均衡策略分發(fā)至不同的Pod。當(dāng)Pod產(chǎn)生異常或有新Pod 上線時(shí),Service 也能動(dòng)態(tài)調(diào)整分發(fā)策略。
依據(jù)不同的類型,Service 可以提供不同的網(wǎng)絡(luò)服務(wù)。常見(jiàn)的類型有:
(1)ClusterIP:此方式用于集群的內(nèi)部訪問(wèn),這也是Service的默認(rèn)類型;
(2)NodePort:將服務(wù)與主機(jī)端口進(jìn)行綁定,通過(guò)主機(jī)IP+端口的方式,可在集群與相應(yīng)的Pod 進(jìn)行交互,這也是Kubernetes集群向外部提供服務(wù)的常見(jiàn)方法;
(3)LoadBalancer:負(fù)載均衡服務(wù),此服務(wù)也用于向集群外部提供服務(wù),但需要與主機(jī)所在的底層網(wǎng)絡(luò)進(jìn)行交互,實(shí)現(xiàn)二層/三層數(shù)據(jù)交換。
Kube-Proxy 組件是實(shí)現(xiàn)整套Service 機(jī)制的核心,此組件通過(guò)Kubernetes 集群的ApiServer 對(duì)集群中的Pod/Service 進(jìn)行監(jiān)控,通過(guò)監(jiān)控相關(guān)的定義、配置等實(shí)現(xiàn)Service 的功能。
圖2:Service
由章節(jié)1 可知,若需要集群外部通過(guò)負(fù)載均衡IP 來(lái)訪問(wèn)Service,需要解決兩個(gè)問(wèn)題:
(1)外部請(qǐng)求如何到達(dá)集群主機(jī)節(jié)點(diǎn);
(2)數(shù)據(jù)包到達(dá)主機(jī)節(jié)點(diǎn)后,如何正確交付給對(duì)應(yīng)的Service。
在基于IP 的以太網(wǎng)中,數(shù)據(jù)包的分發(fā)主要有兩種策略:
(1)對(duì)于同一子網(wǎng)的數(shù)據(jù)包,操作系統(tǒng)會(huì)查找自身的ARP/NDP 表,將IP 地址轉(zhuǎn)換成MAC 地址后進(jìn)行二層交換;
(2)對(duì)于不同子網(wǎng)的數(shù)據(jù)包,操作系統(tǒng)會(huì)查找自身的路由表,選擇合適的路由將數(shù)據(jù)包發(fā)送給對(duì)應(yīng)的網(wǎng)關(guān),實(shí)現(xiàn)三層交換。
為此,只需將負(fù)載均衡地址采用ARP 或者路由,實(shí)現(xiàn)二層/三層的綁定后,集群內(nèi)外的數(shù)據(jù)包交互即可順利進(jìn)行。
對(duì)于問(wèn)題2,由章節(jié)1.2 中的介紹可知,Service 是由kubeproxy 來(lái)實(shí)現(xiàn)的,數(shù)據(jù)包到達(dá)集群節(jié)點(diǎn)主機(jī)后,只需交付給kubeproxy,通過(guò)端口號(hào)正確識(shí)別并轉(zhuǎn)發(fā)至對(duì)應(yīng)的服務(wù),即可實(shí)現(xiàn)與內(nèi)部訪問(wèn)集群相同的效果。
MetalLB 組件通過(guò)在各集群節(jié)點(diǎn)中使用DaemonSet 部署Speaker 組件,通過(guò)發(fā)送ARP/NDP 廣播包(二層)或與核心路由器進(jìn)行BGP 配對(duì)(三層),實(shí)現(xiàn)負(fù)載均衡IP 綁定,完成集群內(nèi)外的數(shù)據(jù)交換。
在ARP 模式下,MetalLB 組件會(huì)選擇一臺(tái)集群節(jié)點(diǎn)(物理機(jī)或虛擬機(jī))作為外部網(wǎng)絡(luò)的應(yīng)答節(jié)點(diǎn),通過(guò)向主機(jī)網(wǎng)絡(luò)發(fā)送ARP/NDP 廣播包,實(shí)現(xiàn)負(fù)載均衡IP 與MAC 的綁定。到達(dá)此主機(jī)的數(shù)據(jù)包會(huì)進(jìn)入kube-proxy,再分發(fā)到相應(yīng)的Pod。
在ARP 模式下,所有的外部請(qǐng)求均只到達(dá)一個(gè)主機(jī)節(jié)點(diǎn),交付kube-proxy 后再進(jìn)行集群內(nèi)的分發(fā),此工作模式與keepalived 類似。若此應(yīng)答節(jié)點(diǎn)出現(xiàn)故障,MetalLB 會(huì)重新選擇一個(gè)應(yīng)答主機(jī)節(jié)點(diǎn),在新應(yīng)答節(jié)點(diǎn)中繼續(xù)發(fā)送ARP/NDP 廣播,實(shí)現(xiàn)IP 地址的切換。
由于此模式基于網(wǎng)絡(luò)二層交換,對(duì)硬件設(shè)備沒(méi)有任何的附加需求。但是,負(fù)載均衡的IP 地址需要與集群主機(jī)的底層網(wǎng)絡(luò)處于相同子網(wǎng)中。
在BGP 模式下,MetalLB 將自身虛擬為多個(gè)路由器(每臺(tái)集群節(jié)點(diǎn)為一臺(tái)路由),與集群節(jié)點(diǎn)底層網(wǎng)絡(luò)中的核心路由器之間使用BGP 協(xié)議進(jìn)行配對(duì)。通過(guò)廣播自身的負(fù)載均衡IP,在核心路由器中建立相應(yīng)的動(dòng)態(tài)路由。
當(dāng)核心路由啟用多路徑支持時(shí),此模式可以實(shí)現(xiàn)“真正”的負(fù)載均衡,即集群外的數(shù)據(jù)包由核心路由分發(fā)至不同的集群節(jié)點(diǎn),交由kube-proxy 后再分發(fā)至相應(yīng)Pod。
由于基于BGP 的路由分發(fā)是無(wú)狀態(tài)的,一個(gè)Session 中的多個(gè)數(shù)據(jù)包可能會(huì)被路由至不同的集群節(jié)點(diǎn)。所幸的是,Kubernetes 的Service 提供了sessionAffinity 的設(shè)置,對(duì)于有session stick 的場(chǎng)景,可以通過(guò)啟用sessionAffinity 來(lái)保證來(lái)自相同用戶的數(shù)據(jù)包到達(dá)同一個(gè)Pod。
BGP 的路由分發(fā)是基于對(duì)協(xié)議、原地址、目標(biāo)地址等參數(shù)的hash 來(lái)進(jìn)行路由選擇。當(dāng)后端的集群節(jié)點(diǎn)發(fā)生故障而下線時(shí),整個(gè)集群的活躍連接可能會(huì)出現(xiàn)“閃斷”的情況,即,客戶端將收到“Connection reset by peer”的錯(cuò)誤提示。為此,一方面可以考慮在核心路由器中啟用ECMP hash 算法來(lái)降低影響,另一方面在應(yīng)用中增加出錯(cuò)重連機(jī)制,保證數(shù)據(jù)的可靠交換。
BGP 模式工作基于IP 交換,工作在網(wǎng)絡(luò)第三層,故負(fù)載均衡的IP 可以與集群節(jié)點(diǎn)的IP 處于不同子網(wǎng)內(nèi)。但是,此模式需要底層網(wǎng)絡(luò)的路由設(shè)備支持BGP 協(xié)議,在網(wǎng)絡(luò)硬件設(shè)備上有一定的限制。
參照官方的說(shuō)明文檔,在內(nèi)部的Kubernetes 集群中部署了MetalLB 組件??紤]部署的復(fù)雜性以及對(duì)網(wǎng)絡(luò)基礎(chǔ)設(shè)施的要求,采用了基于ARP 的二層均衡方案。
在私有Kuberntes 集群中部署MetalLB,僅需通過(guò)kubectl,部署相關(guān)的yaml 文件即可。在部署之前,需配置負(fù)載均衡地址池。此外,對(duì)于1.14.2 版本以上啟用了IPVS 的Kubernetes 集群,還需要啟用kube-proxy 的嚴(yán)格APR 模式。
MetalLB 地址池配置文件內(nèi)容如下:
使用如下語(yǔ)句在Kubernetes 集群中部署MetalLB:
觀察到相關(guān)組件均正常運(yùn)行后,即可對(duì)Service 進(jìn)行調(diào)整,將ServiceType 更改為“LoadBalancer”方式,結(jié)果如圖2 所示。
可以看到,在外部Endpoint 中已經(jīng)獲取到了指定負(fù)載均衡IP地址池范圍內(nèi)的IP 地址,并已正常顯示在Service 中。通過(guò)訪問(wèn)相應(yīng)的IP 地址,服務(wù)聯(lián)通正常。
本文介紹了Kubernetes 集群的網(wǎng)絡(luò)基本架構(gòu)知識(shí),對(duì)開源組件MetalLB 的工作原理、不同的負(fù)載均衡模式進(jìn)行了說(shuō)明,最后在公司內(nèi)部的私有化集群中以ARP 模式部署了MetalLB 組件,實(shí)現(xiàn)了集群對(duì)負(fù)載均衡的支持。
從MetalLB 的工作原理分析,其本質(zhì)仍然為一個(gè)“外部”的負(fù)載均衡實(shí)現(xiàn),一個(gè)與Kubernetes 集成的“HAProxy”負(fù)載集群。通過(guò)與Kubernetes API 交互,MetalLB 能夠?qū)崟r(shí)獲取Service 相關(guān)配置信息,動(dòng)態(tài)配置網(wǎng)絡(luò)發(fā)現(xiàn)和轉(zhuǎn)發(fā),同時(shí)反饋Load Balancer 的狀態(tài)。從網(wǎng)絡(luò)性能角度考慮,因工作原理仍然是將相關(guān)數(shù)據(jù)包交付給Kube-proxy,與NodePort 方式無(wú)異。但從管理的便捷性和集成度上說(shuō),采用MetalLB 的負(fù)載均衡方式實(shí)現(xiàn)了基于集群的統(tǒng)一管理,大大減輕了管理人員的工作量。
截止目前,MetalLB 組件已在私有集群中穩(wěn)定運(yùn)行了一年多,各項(xiàng)性能指標(biāo)均達(dá)到了預(yù)期要求。