Kubernetes網(wǎng)絡(luò)的可視化指南
Kubernetes內(nèi)部的網(wǎng)絡(luò)與物理世界中的網(wǎng)絡(luò)沒有太大區(qū)別。有了網(wǎng)絡(luò)基礎(chǔ)知識(shí),你就可以輕松實(shí)現(xiàn)容器Pod和服務(wù)之間的通信。
從使用交換機(jī)、路由器和以太網(wǎng)電纜的物理網(wǎng)絡(luò)轉(zhuǎn)移到使用軟件定義網(wǎng)絡(luò)(SDN)和虛擬接口的虛擬網(wǎng)絡(luò)需要一段輕微的學(xué)習(xí)曲線。當(dāng)然,原則保持不變,但有不同的規(guī)范和最佳實(shí)踐。Kubernetes有自己的一套規(guī)則,如果你處理的是容器和云,這有助于了解Kubernetes網(wǎng)絡(luò)是如何工作的。
Kubernetes網(wǎng)絡(luò)模型有一些需要記住的一般規(guī)則:
- 每個(gè)pod都有自己的IP地址:不需要在Pod之間創(chuàng)建鏈接,也不需要將容器端口映射到主機(jī)端口。
- 不需要NAT:節(jié)點(diǎn)上的Pod應(yīng)該能夠與沒有NAT的所有節(jié)點(diǎn)上的所有Pod通信。
- 代理獲得所有訪問權(quán)限:節(jié)點(diǎn)(系統(tǒng)守護(hù)進(jìn)程、Kubelet)上的代理可以與該節(jié)點(diǎn)中的所有Pod通信。
- 共享命名空間:Pod中的容器共享網(wǎng)絡(luò)命名空間(IP和MAC地址),因此它們可以使用環(huán)回地址相互通信。
Kubernetes網(wǎng)絡(luò)解決了什么問題
Kubernetes網(wǎng)絡(luò)旨在確保Kubernetes中的不同實(shí)體類型可以通信。Kubernetes基礎(chǔ)設(shè)施的布局在設(shè)計(jì)上有很多分離。命名空間、容器和Pod旨在保持組件彼此不同,因此高度結(jié)構(gòu)化的通信計(jì)劃非常重要。
容器到容器的網(wǎng)絡(luò)
容器到容器的網(wǎng)絡(luò)通過Pod網(wǎng)絡(luò)命名空間進(jìn)行。網(wǎng)絡(luò)命名空間允許你擁有獨(dú)立的網(wǎng)絡(luò)接口和路由表,這些接口和路由表與系統(tǒng)的其余部分隔離并獨(dú)立運(yùn)行。每個(gè)Pod都有自己的網(wǎng)絡(luò)命名空間,其中的容器共享相同的IP地址和端口。這些容器之間的所有通信都是通過localhost進(jìn)行的,因?yàn)樗鼈兌际峭幻臻g的一部分。(由圖中的綠線表示。)
Pod到Pod的網(wǎng)絡(luò)
對(duì)于Kubernetes,每個(gè)節(jié)點(diǎn)都有一個(gè)指定的用于Pod的CIDR IP范圍。這確保每個(gè)Pod都能收到集群中其他Pod可以看到的唯一IP地址。創(chuàng)建新Pod時(shí),IP地址從不重疊。與容器到容器的網(wǎng)絡(luò)不同,Pod到Pod的通信使用真實(shí)的IP進(jìn)行,無論你是將Pod部署在同一節(jié)點(diǎn)上還是集群中的不同節(jié)點(diǎn)上。
上圖顯示,為了使Pod相互通信,流量必須在Pod網(wǎng)絡(luò)命名空間和根網(wǎng)絡(luò)命名空間之間流動(dòng)。這是通過虛擬以太網(wǎng)設(shè)備或veth對(duì)(圖中veth0到Pod命名空間1,veth1到Pod命名空間2)連接Pod命名空間和根命名空間來實(shí)現(xiàn)的。虛擬網(wǎng)橋連接這些虛擬接口,允許通信使用地址解析協(xié)議(ARP)在它們之間流動(dòng)。
當(dāng)數(shù)據(jù)從Pod 1發(fā)送到Pod 2時(shí),事件流為:
- Pod 1流量通過eth0流向根網(wǎng)絡(luò)命名空間的虛擬接口veth0。
- 然后,流量通過veth0到達(dá)連接到veth1的虛擬網(wǎng)橋。
- 流量通過虛擬網(wǎng)橋到達(dá)veth1。
- 最后,流量通過veth1到達(dá)Pod 2的eth0接口。
Pod到服務(wù)的網(wǎng)絡(luò)
Pod很動(dòng)態(tài)。它們可能需要根據(jù)需求擴(kuò)大或縮小規(guī)模。在應(yīng)用程序崩潰或節(jié)點(diǎn)故障的情況下,可以再次創(chuàng)建它們。這些事件會(huì)導(dǎo)致Pod的IP地址發(fā)生變化,這將給聯(lián)網(wǎng)帶來挑戰(zhàn)。
Kubernetes通過使用Service功能來解決此問題,該功能執(zhí)行以下操作:
- 在前端分配靜態(tài)虛擬IP地址,以連接與服務(wù)關(guān)聯(lián)的任何后端吊艙。
- 負(fù)載將尋址到此虛擬IP的所有流量平衡到后端Pod集。
- 跟蹤Pod的IP地址,這樣即使Pod IP地址更改,客戶端也不會(huì)有任何問題,因?yàn)樗鼈冎恢苯舆B接到服務(wù)本身的靜態(tài)虛擬IP地址。
集群內(nèi)負(fù)載均衡有兩種方式:
- IPTABLES:在這種模式下,kube-proxy監(jiān)視API服務(wù)器中的更改。對(duì)于每個(gè)新服務(wù),它都會(huì)安裝iptables規(guī)則,這些規(guī)則將流量捕獲到Service的clusterIP和端口,然后將流量重定向到服務(wù)的后端Pod。Pod是隨機(jī)選擇的。此模式可靠,系統(tǒng)開銷較低,因?yàn)長(zhǎng)inux Netfilter處理流量時(shí)不需要在用戶空間和內(nèi)核空間之間切換。
- IPV:IPV構(gòu)建在Netfilter之上,并實(shí)現(xiàn)傳輸層負(fù)載均衡。IPVS使用Netfilter鉤子函數(shù),使用哈希表作為底層數(shù)據(jù)結(jié)構(gòu),并在內(nèi)核空間中工作。這意味著IPVS模式下的kube代理比iptables模式下的kube代理具有更低的延遲、更高的吞吐量和更好的性能來重定向流量。
上圖顯示了從Pod 1到Pod 3的包流通過Service到不同節(jié)點(diǎn)(以紅色標(biāo)記)。前往虛擬網(wǎng)橋的包必須使用默認(rèn)路由(eth0),因?yàn)榫W(wǎng)橋上運(yùn)行的ARP無法理解該服務(wù)。之后,包必須通過iptables進(jìn)行過濾,iptables使用kube代理在節(jié)點(diǎn)中定義的規(guī)則。因此,該圖顯示了當(dāng)前的路徑。
Internet到服務(wù)的網(wǎng)絡(luò)
到目前為止,已經(jīng)討論了如何在集群內(nèi)路由流量。然而,Kubernetes網(wǎng)絡(luò)還有另一面,那就是將應(yīng)用程序暴露于外部網(wǎng)絡(luò)。
你可以通過兩種不同的方式將應(yīng)用程序公開給外部網(wǎng)絡(luò)。
- 出口:當(dāng)你想要將流量從Kubernetes服務(wù)路由到Internet時(shí),請(qǐng)使用此選項(xiàng)。在這種情況下,iptables執(zhí)行源NAT,因此流量似乎來自節(jié)點(diǎn),而不是Pod。
- 入口:這是從外部世界到服務(wù)的傳入流量。入口還允許并阻止使用連接規(guī)則與服務(wù)進(jìn)行的特定通信。通常,有兩種入口解決方案在不同的網(wǎng)絡(luò)堆棧區(qū)域上運(yùn)行:服務(wù)負(fù)載均衡器和入口控制器。
發(fā)現(xiàn)服務(wù)
Kubernetes發(fā)現(xiàn)服務(wù)有兩種方式:
- 環(huán)境變量:在Pod運(yùn)行的節(jié)點(diǎn)上運(yùn)行的kubelet服務(wù)負(fù)責(zé)以{SVCNAME}\u service\u HOST和{SVCNAME}\u service\u PORT的格式為每個(gè)活動(dòng)服務(wù)設(shè)置環(huán)境變量。你必須在客戶端Pod出現(xiàn)之前創(chuàng)建服務(wù)。否則,這些客戶端Pod將不會(huì)填充其環(huán)境變量。
- DNS:DNS服務(wù)實(shí)現(xiàn)為Kubernetes服務(wù),映射到一個(gè)或多個(gè)DNS服務(wù)器Pod,這些Pod與任何其他Pod一樣進(jìn)行調(diào)度。集群中的Pod配置為使用DNS服務(wù),DNS搜索列表包括Pod自己的命名空間和集群的默認(rèn)域。集群感知DNS服務(wù)器(如CoreDNS)監(jiān)視Kubernetes API以獲取新服務(wù),并為每個(gè)服務(wù)創(chuàng)建一組DNS記錄。如果在整個(gè)集群中啟用了DNS,則所有Pod都可以根據(jù)其DNS名稱自動(dòng)解析服務(wù)。Kubernetes DNS服務(wù)器是訪問ExternalName服務(wù)的唯一方式。
發(fā)布服務(wù)的ServiceTypes
Kubernetes服務(wù)提供了一種訪問一組Pod的方法,通常通過使用標(biāo)簽選擇器來定義。這可能是應(yīng)用程序試圖訪問集群中的其他應(yīng)用程序,也可能允許你將集群中運(yùn)行的應(yīng)用程序公開給外部世界。Kubernetes
ServiceTypes允許你指定所需的服務(wù)類型。
不同的ServiceTypes包括:
- ClusterIP:這是默認(rèn)的ServiceType。它使服務(wù)只能從集群內(nèi)訪問,并允許集群內(nèi)的應(yīng)用程序相互通信。沒有外部訪問。
- LoadBalancer:此服務(wù)類型使用云提供商的負(fù)載均衡器對(duì)外公開服務(wù)。來自外部負(fù)載均衡器的流量被定向到后端POD。云提供商決定如何實(shí)現(xiàn)負(fù)載均衡。
- NodePort:這允許外部通信通過在所有節(jié)點(diǎn)上打開特定端口來訪問服務(wù)。然后,發(fā)送到此端口的任何流量都會(huì)轉(zhuǎn)發(fā)到該服務(wù)。
- ExternalName:這種類型的服務(wù)使用ExternalName字段的內(nèi)容,通過返回CNAME記錄及其值,將服務(wù)映射到DNS名稱。未設(shè)置任何類型的代理。
網(wǎng)絡(luò)軟件
只要你了解所使用的技術(shù),Kubernetes內(nèi)部的網(wǎng)絡(luò)與物理世界中的網(wǎng)絡(luò)沒有太大區(qū)別。好好學(xué)習(xí),記住網(wǎng)絡(luò)基礎(chǔ)知識(shí),就可以輕松實(shí)現(xiàn)容器、Pod和服務(wù)之間的通信。