溫馨提示×

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

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

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

發(fā)布時(shí)間:2020-07-06 12:42:09 來(lái)源:網(wǎng)絡(luò) 閱讀:241 作者:阿里系統(tǒng)軟件技術(shù) 欄目:云計(jì)算

作者 | 聲東 阿里云售后技術(shù)專(zhuān)家

文章來(lái)源:Docker,點(diǎn)擊查看原文。

以我的經(jīng)驗(yàn)來(lái)講,理解 Kubernetes 集群服務(wù)的概念,是比較不容易的一件事情。尤其是當(dāng)我們基于似是而非的理解,去排查服務(wù)相關(guān)問(wèn)題的時(shí)候,會(huì)非常不順利。

這體現(xiàn)在,對(duì)于新手來(lái)說(shuō),ping 不通服務(wù)的 IP 地址這樣基礎(chǔ)的問(wèn)題,都很難理解;而就算對(duì)經(jīng)驗(yàn)很豐富的工程師來(lái)說(shuō),看懂服務(wù)相關(guān)的 iptables 配置,也是有相當(dāng)?shù)奶魬?zhàn)的。

今天這邊文章,我來(lái)深入解釋一下 Kubernetes 集群服務(wù)的原理與實(shí)現(xiàn),便于大家理解。

Kubernetes 集群服務(wù)的本質(zhì)是什么

概念上來(lái)講,Kubernetes 集群的服務(wù),其實(shí)就是負(fù)載均衡、或反向代理。這跟阿里云的負(fù)載均衡產(chǎn)品,有很多類(lèi)似的地方。和負(fù)載均衡一樣,服務(wù)有它的 IP 地址以及前端端口;服務(wù)后邊會(huì)掛載多個(gè)容器組 Pod 作為其“后端服務(wù)器”,這些“后端服務(wù)器”有自己的 IP 以及監(jiān)聽(tīng)端口。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

當(dāng)這樣的負(fù)載均衡和后端的架構(gòu),與 Kubernetes 集群結(jié)合的時(shí)候,我們可以想到的最直觀的實(shí)現(xiàn)方式,就是集群中某一個(gè)節(jié)點(diǎn)專(zhuān)門(mén)做負(fù)載均衡(類(lèi)似 LVS)的角色,而其他節(jié)點(diǎn)則用來(lái)負(fù)載后端容器組。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

這樣的實(shí)現(xiàn)方法,有一個(gè)巨大的缺陷,就是單點(diǎn)問(wèn)題。Kubernetes 集群是 Google 多年來(lái)自動(dòng)化運(yùn)維實(shí)踐的結(jié)晶,這樣的實(shí)現(xiàn)顯然與其智能運(yùn)維的哲學(xué)相背離的。

自帶通信員

邊車(chē)模式(Sidecar)是微服務(wù)領(lǐng)域的核心概念。邊車(chē)模式,換一句通俗一點(diǎn)的說(shuō)法,就是自帶通信員。熟悉服務(wù)網(wǎng)格的同學(xué)肯定對(duì)這個(gè)很熟悉了。但是可能比較少人注意到,其實(shí) Kubernetes 集群原始服務(wù)的實(shí)現(xiàn),也是基于 Sidecar 模式的。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

在 Kubernetes 集群中,服務(wù)的實(shí)現(xiàn),實(shí)際上是為每一個(gè)集群節(jié)點(diǎn)上,部署了一個(gè)反向代理 Sidecar。而所有對(duì)集群服務(wù)的訪問(wèn),都會(huì)被節(jié)點(diǎn)上的反向代理轉(zhuǎn)換成對(duì)服務(wù)后端容器組的訪問(wèn)?;旧蟻?lái)說(shuō),節(jié)點(diǎn)和這些 Sidecar 的關(guān)系如下圖所示。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

把服務(wù)照進(jìn)現(xiàn)實(shí)

前邊兩節(jié),我們看到了,Kubernetes 集群的服務(wù),本質(zhì)上是負(fù)載均衡,即反向代理;同時(shí)我們知道了,在實(shí)際實(shí)現(xiàn)中,這個(gè)反向代理,并不是部署在集群某一個(gè)節(jié)點(diǎn)上,而是作為集群節(jié)點(diǎn)的邊車(chē),部署在每個(gè)節(jié)點(diǎn)上的。

在這里把服務(wù)照進(jìn)反向代理這個(gè)現(xiàn)實(shí)的,是 Kubernetes 集群的一個(gè)控制器,即 kube-proxy。關(guān)于 Kubernetes 集群控制器的原理,請(qǐng)參考我另外一篇關(guān)于控制器的文章。簡(jiǎn)單來(lái)說(shuō),kube-proxy 作為部署在集群節(jié)點(diǎn)上的控制器,它們通過(guò)集群 API Server 監(jiān)聽(tīng)著集群狀態(tài)變化。當(dāng)有新的服務(wù)被創(chuàng)建的時(shí)候,kube-proxy 則會(huì)把集群服務(wù)的狀態(tài)、屬性,翻譯成反向代理的配置。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

那剩下的問(wèn)題,就是反向代理,即上圖中 Proxy 的實(shí)現(xiàn)。

一種實(shí)現(xiàn)

Kubernetes 集群節(jié)點(diǎn)實(shí)現(xiàn)服務(wù)反向代理的方法,目前主要有三種,即 userspace、iptables 以及 IPVS。今天我們只深入分析 iptables 的方式,底層網(wǎng)絡(luò)基于阿里云 Flannel 集群網(wǎng)絡(luò)。

過(guò)濾器框架

現(xiàn)在,我們來(lái)設(shè)想一種場(chǎng)景。我們有一個(gè)屋子。這個(gè)屋子有一個(gè)入水管和出水管。從入水管進(jìn)入的水,是不能直接飲用的,因?yàn)橛须s質(zhì)。而我們期望,從出水管流出的水,可以直接飲用。為了達(dá)到目的,我們切開(kāi)水管,在中間加一個(gè)雜質(zhì)過(guò)濾器。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

過(guò)了幾天,我們的需求變了,我們不止要求從屋子里流出來(lái)的水可以直接飲用,我們還希望水是熱水。所以我們不得不再在水管上增加一個(gè)切口,然后增加一個(gè)加熱器。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

很明顯,這種切開(kāi)水管,增加新功能的方式是很丑陋的。因?yàn)樾枨罂赡茈S時(shí)會(huì)變,我們甚至很難保證,在經(jīng)過(guò)一年半載之后,這跟水管還能找得到可以被切開(kāi)的地方。

所以我們需要重新設(shè)計(jì)。首先我們不能隨便切開(kāi)水管,所以我們要把水管的切口固定下來(lái)。以上邊的場(chǎng)景為例,我們確保水管只能有一個(gè)切口位置。其次,我們抽象出對(duì)水的兩種處理方式:物理變化和化學(xué)變化。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

基于以上的設(shè)計(jì),如果我們需要過(guò)濾雜質(zhì),就可以在化學(xué)變化這個(gè)功能模塊里增加一條過(guò)濾雜質(zhì)的規(guī)則;如果我們需要增加溫度的話,就可以在物理變化這個(gè)功能模塊里增加一條加熱的規(guī)則。

以上的過(guò)濾器框架,顯然比切水管的方式,要優(yōu)秀很多。設(shè)計(jì)這個(gè)框架,我們主要做了兩件事情,一個(gè)是固定水管切口位置,另外一個(gè)是抽象出兩種水處理方式。

理解這兩件事情之后,我們可以來(lái)看下 iptables,或者更準(zhǔn)確的說(shuō)法,netfilter 的工作原理。netfilter 實(shí)際上就是一個(gè)過(guò)濾器框架。netfilter 在網(wǎng)絡(luò)包收發(fā)及路由的管道上,一共切了 5 個(gè)口,分別是 PREROUTING,F(xiàn)ORWARD,POSTROUTING,INPUT 以及 OUTPUT;同時(shí) netfilter 定義了包括 nat、filter 在內(nèi)的若干個(gè)網(wǎng)絡(luò)包處理方式。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)
需要注意的是,routing 和 forwarding 很大程度上增加了以上 netfilter 的復(fù)雜程度,如果我們不考慮 routing 和 forwarding,那么 netfilter 會(huì)變得跟我們的水質(zhì)過(guò)濾器框架一樣簡(jiǎn)單。

節(jié)點(diǎn)網(wǎng)絡(luò)大圖

現(xiàn)在我們看一下 Kubernetes 集群節(jié)點(diǎn)的網(wǎng)絡(luò)全貌。橫向來(lái)看,節(jié)點(diǎn)上的網(wǎng)絡(luò)環(huán)境,被分割成不同的網(wǎng)絡(luò)命名空間,包括主機(jī)網(wǎng)絡(luò)命名空間和 Pod 網(wǎng)絡(luò)命名空間;縱向來(lái)看,每個(gè)網(wǎng)絡(luò)命名空間包括完整的網(wǎng)絡(luò)棧,從應(yīng)用到協(xié)議棧,再到網(wǎng)絡(luò)設(shè)備。

在網(wǎng)絡(luò)設(shè)備這一層,我們通過(guò) cni0 虛擬網(wǎng)橋,組建出系統(tǒng)內(nèi)部的一個(gè)虛擬局域網(wǎng)。Pod 網(wǎng)絡(luò)通過(guò) veth 對(duì)連接到這個(gè)虛擬局域網(wǎng)內(nèi)。cni0 虛擬局域網(wǎng)通過(guò)主機(jī)路由以及網(wǎng)口 eth0 與外部通信。

在網(wǎng)絡(luò)協(xié)議棧這一層,我們可以通過(guò)編程 netfilter 過(guò)濾器框架,來(lái)實(shí)現(xiàn)集群節(jié)點(diǎn)的反向代理。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

實(shí)現(xiàn)反向代理,歸根結(jié)底,就是做 DNAT,即把發(fā)送給集群服務(wù) IP 和端口的數(shù)據(jù)包,修改成發(fā)給具體容器組的 IP 和端口。

參考 netfilter 過(guò)濾器框架的圖,我們知道,在 netfilter 里,可以通過(guò)在 PREROUTING,OUTPUT 以及 POSTROUGING 三個(gè)位置加入 NAT 規(guī)則,來(lái)改變數(shù)據(jù)包的源地址或目的地址。

因?yàn)檫@里需要做的是 DNAT,即改變目的地址,這樣的修改,必須在路由(ROUTING)之前發(fā)生以保證數(shù)據(jù)包可以被路由正確處理,所以實(shí)現(xiàn)反向代理的規(guī)則,需要被加到 PREROUTING 和 OUTPUT 兩個(gè)位置。

其中,PREOURTING 的規(guī)則,用來(lái)處理從 Pod 訪問(wèn)服務(wù)的流量。數(shù)據(jù)包從 Pod 網(wǎng)絡(luò) veth 發(fā)送到 cni0 之后,進(jìn)入主機(jī)協(xié)議棧,首先會(huì)經(jīng)過(guò) netfilter PREROUTING 來(lái)做處理,所以發(fā)給服務(wù)的數(shù)據(jù)包,會(huì)在這個(gè)位置做 DNAT。經(jīng)過(guò) DNAT 處理之后,數(shù)據(jù)包的目的地址變成另外一個(gè) Pod 的地址,從而經(jīng)過(guò)主機(jī)路由,轉(zhuǎn)發(fā)到 eth0,發(fā)送給正確的集群節(jié)點(diǎn)。

而添加在 OUTPUT 這個(gè)位置的 DNAT 規(guī)則,則用來(lái)處理從主機(jī)網(wǎng)絡(luò)發(fā)給服務(wù)的數(shù)據(jù)包,原理也是類(lèi)似,即經(jīng)過(guò)路由之前,修改目的地址,以方便路由轉(zhuǎn)發(fā)。

升級(jí)過(guò)濾器框架

在過(guò)濾器框架一節(jié),我們看到 netfilter 是一個(gè)過(guò)濾器框架。netfilter 在數(shù)據(jù)“管到”上切了 5 個(gè)口,分別在這 5 個(gè)口上,做一些數(shù)據(jù)包處理工作。雖然固定切口位置以及網(wǎng)絡(luò)包處理方式分類(lèi)已經(jīng)極大的優(yōu)化了過(guò)濾器框架,但是有一個(gè)關(guān)鍵的問(wèn)題,就是我們還是得在管道上做修改以滿足新的功能。換句話說(shuō),這個(gè)框架沒(méi)有做到管道和過(guò)濾功能兩者的徹底解耦。

為了實(shí)現(xiàn)管道和過(guò)濾功能兩者的解耦,netfilter 用了表這個(gè)概念。表就是 netfilter 的過(guò)濾中心,其核心功能是過(guò)濾方式的分類(lèi)(表),以及每種過(guò)濾方式中,過(guò)濾規(guī)則的組織(鏈)。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)
把過(guò)濾功能和管道解耦之后,所有對(duì)數(shù)據(jù)包的處理,都變成了對(duì)表的配置。而管道上的5個(gè)切口,僅僅變成了流量的出入口,負(fù)責(zé)把流量發(fā)送到過(guò)濾中心,并把處理之后的流量沿著管道繼續(xù)傳送下去。

如上圖,在表中,netfilter 把規(guī)則組織成為鏈。表中有針對(duì)每個(gè)管道切口的默認(rèn)鏈,也有我們自己加入的自定義鏈。默認(rèn)鏈?zhǔn)菙?shù)據(jù)的入口,默認(rèn)鏈可以通過(guò)跳轉(zhuǎn)到自定義鏈來(lái)完成一些復(fù)雜的功能。這里允許增加自定義鏈的好處是顯然的。為了完成一個(gè)復(fù)雜過(guò)濾功能,比如實(shí)現(xiàn) Kubernetes 集群節(jié)點(diǎn)的反向代理,我們可以使用自定義鏈來(lái)模塊化我們規(guī)則。

用自定義鏈實(shí)現(xiàn)服務(wù)的反向代理

集群服務(wù)的反向代理,實(shí)際上就是利用自定義鏈,模塊化地實(shí)現(xiàn)了數(shù)據(jù)包的 DNAT 轉(zhuǎn)換。KUBE-SERVICE 是整個(gè)反向代理的入口鏈,其對(duì)應(yīng)所有服務(wù)的總?cè)肟冢籏UBE-SVC-XXXX 鏈?zhǔn)蔷唧w某一個(gè)服務(wù)的入口鏈,KUBE-SERVICE 鏈會(huì)根據(jù)服務(wù) IP,跳轉(zhuǎn)到具體服務(wù)的 KUBE-SVC-XXXX 鏈;而 KUBE-SEP-XXXX 鏈代表著某一個(gè)具體 Pod 的地址和端口,即 endpoint,具體服務(wù)鏈 KUBE-SVC-XXXX 會(huì)以一定算法(一般是隨機(jī)),跳轉(zhuǎn)到 endpoint 鏈。

Kubernetes 從懵圈到熟練:集群服務(wù)的三個(gè)要點(diǎn)和一種實(shí)現(xiàn)

而如前文中提到的,因?yàn)檫@里需要做的是 DNAT,即改變目的地址,這樣的修改,必須在路由之前發(fā)生以保證數(shù)據(jù)包可以被路由正確處理。所以 KUBE-SERVICE 會(huì)被 PREROUTING 和 OUTPUT 兩個(gè)默認(rèn)鏈所調(diào)用。

總結(jié)

通過(guò)這篇文章,大家應(yīng)該對(duì) Kubernetes 集群服務(wù)的概念以及實(shí)現(xiàn),有了更深層次的認(rèn)識(shí)。我們基本上需要把握三個(gè)要點(diǎn):

  • 服務(wù)本質(zhì)上是負(fù)載均衡;
  • 服務(wù)負(fù)載均衡的實(shí)現(xiàn)采用了與服務(wù)網(wǎng)格類(lèi)似的 Sidecar 的模式,而不是 LVS 類(lèi)型的獨(dú)占模式;
  • kube-proxy 本質(zhì)上是一個(gè)集群控制器。除此之外,我們思考了過(guò)濾器框架的設(shè)計(jì),并在此基礎(chǔ)上,理解使用 iptables 實(shí)現(xiàn)的服務(wù)負(fù)載均衡的原理。

原文鏈接:https://yq.aliyun.com/articles/710873

“ 阿里巴巴云原生微信公眾號(hào)(ID:Alicloudnative)關(guān)注微服務(wù)、Serverless、容器、Service Mesh等技術(shù)領(lǐng)域、聚焦云原生流行技術(shù)趨勢(shì)、云原生大規(guī)模的落地實(shí)踐,做最懂云原生開(kāi)發(fā)者的技術(shù)公眾號(hào)?!?/strong>

向AI問(wèn)一下細(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