一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

 邸彥強(qiáng) 2020-12-09

k8s對(duì)Pods之間如何進(jìn)行組網(wǎng)通信提出了要求,k8s對(duì)集群的網(wǎng)絡(luò)有以下要求:

  • 所有的Pods之間可以在不使用NAT網(wǎng)絡(luò)地址轉(zhuǎn)換的情況下相互通信
  • 所有的Nodes之間可以在不使用NAT網(wǎng)絡(luò)地址轉(zhuǎn)換的情況下相互通信
  • 每個(gè)Pod自己看到的自己的ip和其他Pod看到的一致

k8s網(wǎng)絡(luò)模型設(shè)計(jì)基礎(chǔ)原則:每個(gè)Pod都擁有一個(gè)獨(dú)立的 IP地址,而且 假定所有 Pod 都在一個(gè)可以直接連通的、扁平的網(wǎng)絡(luò)空間中 。 所以不管它們是否運(yùn)行在同 一 個(gè) Node (宿主機(jī))中,都要求它們可以直接通過(guò)對(duì)方的 IP 進(jìn)行訪問(wèn)。設(shè)計(jì)這個(gè)原則的原因 是,用戶不需要額外考慮如何建立 Pod 之間的連接,也不需要考慮將容器端口映射到主機(jī)端口等問(wèn)題。

由于 Kubemetes 的網(wǎng)絡(luò)模型假設(shè) Pod 之間訪問(wèn)時(shí)使用的是對(duì)方 Pod 的實(shí)際地址,所以一個(gè)
Pod 內(nèi)部的應(yīng)用程序看到的自己的 IP 地址和端口與集群內(nèi)其他 Pod 看到的一樣。它們都是 Pod 實(shí)際分配的IP地址 (從dockerO上分配的)。將IP地址和端口在Pod內(nèi)部和外部都保持一致, 我們可以不使用 NAT 來(lái)進(jìn)行轉(zhuǎn)換,地址空間也自然是平的。

鑒于上面這些要求,我們需要解決四個(gè)不同的網(wǎng)絡(luò)問(wèn)題::

  • Docker容器和Docker容器之間的網(wǎng)絡(luò)
  • Pod與Pod之間的網(wǎng)絡(luò)
  • Pod與Service之間的網(wǎng)絡(luò)
  • Internet與Service之間的網(wǎng)絡(luò)

下面我們一一進(jìn)行討論每種網(wǎng)絡(luò)問(wèn)題,以及如何解決。

二、容器和容器之間的網(wǎng)絡(luò)

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

  • 在k8s中每個(gè)Pod中管理著一組Docker容器,這些Docker容器共享同一個(gè)網(wǎng)絡(luò)命名空間。
  • Pod中的每個(gè)Docker容器擁有與Pod相同的IP和port地址空間,并且由于他們?cè)谕粋€(gè)網(wǎng)絡(luò)命名空間,他們之間可以通過(guò)localhost相互訪問(wèn)。
    什么機(jī)制讓同一個(gè)Pod內(nèi)的多個(gè)docker容器相互通信那?其實(shí)是使用Docker的一種網(wǎng)絡(luò)模型:–net=container

container模式指定新創(chuàng)建的Docker容器和已經(jīng)存在的一個(gè)容器共享一個(gè)網(wǎng)絡(luò)命名空間,而不是和宿主機(jī)共享。新創(chuàng)建的Docker容器不會(huì)創(chuàng)建自己的網(wǎng)卡,配置自己的 IP,而是和一個(gè)指定的容器共享 IP、端口范圍等

每個(gè)Pod容器有有一個(gè)pause容器其有獨(dú)立的網(wǎng)絡(luò)命名空間,在Pod內(nèi)啟動(dòng)Docker容器時(shí)候使用 –net=container就可以讓當(dāng)前Docker容器加入到Pod容器擁有的網(wǎng)絡(luò)命名空間(pause容器)

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

三、Pod與Pod之間的網(wǎng)絡(luò)

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

  • k8s中,每個(gè)Pod擁有一個(gè)ip地址,不同的Pod之間可以直接使用改ip與彼此進(jìn)行通訊
  • 在同一個(gè)Node上,從Pod的視角看,它存在于自己的網(wǎng)絡(luò)命名空間中,并且需要與該Node上的其他網(wǎng)絡(luò)命名空間上的Pod進(jìn)行通信。

那么是如何做到的?這多虧了使用linux虛擬以太網(wǎng)設(shè)備或者說(shuō)是由兩個(gè)虛擬接口組成的veth對(duì)使不同的網(wǎng)絡(luò)命名空間鏈接起來(lái),這些虛擬接口分布在多個(gè)網(wǎng)絡(luò)命名空間上(這里是指多個(gè)Pod上)。

為了讓多個(gè)Pod的網(wǎng)絡(luò)命名空間鏈接起來(lái),我們可以讓veth對(duì)的一端鏈接到root網(wǎng)絡(luò)命名空間(宿主機(jī)的),另一端鏈接到Pod的網(wǎng)絡(luò)命名空間。

每對(duì)Veth就像一根接插電纜,連接兩側(cè)并允許流量在它們之間流動(dòng);這種veth對(duì)可以推廣到同一個(gè)Node上任意多的Pod上,如上圖這里展示使用veth對(duì)鏈接每個(gè)Pod到虛擬機(jī)的root網(wǎng)絡(luò)命名空間。

下面我們看如何使用網(wǎng)橋設(shè)備來(lái)讓通過(guò)veth對(duì)鏈接到root命名空間的多個(gè)Pod進(jìn)行通信。

linux以太網(wǎng)橋(Linux Ethernet bridge)是一個(gè)虛擬的2層網(wǎng)絡(luò)設(shè)備,目的是把多個(gè)以太網(wǎng)段鏈接起來(lái),網(wǎng)橋維護(hù)了一個(gè)轉(zhuǎn)發(fā)表,通過(guò)檢查轉(zhuǎn)發(fā)表通過(guò)它傳輸?shù)臄?shù)據(jù)包的目的地并決定是否將數(shù)據(jù)包傳遞到連接到網(wǎng)橋的其他網(wǎng)段,網(wǎng)橋代碼通過(guò)查看網(wǎng)絡(luò)中每個(gè)以太網(wǎng)設(shè)備特有的MAC地址來(lái)決定是傳輸數(shù)據(jù)還是丟棄數(shù)據(jù)。

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

網(wǎng)橋?qū)崿F(xiàn)了ARP協(xié)議用來(lái)根據(jù)給定的ip地址找到對(duì)應(yīng)機(jī)器的數(shù)據(jù)鏈路層的mac地址,一開(kāi)始轉(zhuǎn)發(fā)表為空,當(dāng)一個(gè)數(shù)據(jù)幀被網(wǎng)橋接受后,網(wǎng)橋會(huì)廣播該幀到所有的鏈接設(shè)備(除了發(fā)送方設(shè)備),并且把響應(yīng)這個(gè)廣播的設(shè)備記錄到轉(zhuǎn)發(fā)表;隨后發(fā)往相同ip地址的流量會(huì)直接從轉(zhuǎn)發(fā)表查找正確的mac地址,然后轉(zhuǎn)發(fā)包到對(duì)應(yīng)的設(shè)備。

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

如上圖顯示了兩個(gè)Pod通過(guò)veth對(duì)鏈接到root網(wǎng)絡(luò)命名空間,并且通過(guò)網(wǎng)橋進(jìn)行通信

3.1 同一個(gè)Node中的Pod之間的一次通信

鑒于每個(gè)Pod有自己獨(dú)立的網(wǎng)絡(luò)命名空間,我們使用虛擬以太網(wǎng)設(shè)備把多個(gè)Pod的命名空間鏈接到了root命名空間,并且使用網(wǎng)橋讓多個(gè)Pod之間進(jìn)行通信,下面我們看如何在兩個(gè)pod之間進(jìn)行通信:

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

  • 通過(guò)網(wǎng)橋這里把veth0和veth1組成為一個(gè)以太網(wǎng),他們直接是可以直接通信的,另外這里通過(guò)veth對(duì)讓pod1的eth0和veth0、pod2的eth0和veth1關(guān)聯(lián)起來(lái),從而讓pod1和pod2相互通信。
  • Pod 1通過(guò)自己默認(rèn)的以太網(wǎng)設(shè)備eth0發(fā)送一個(gè)數(shù)據(jù)包,eth0把數(shù)據(jù)傳遞給veth0,數(shù)據(jù)包到達(dá)網(wǎng)橋后,網(wǎng)橋通過(guò)轉(zhuǎn)發(fā)表把數(shù)據(jù)傳遞給veth1,然后虛擬設(shè)備veth1直接把包傳遞給Pod2網(wǎng)絡(luò)命名空間中的虛擬設(shè)備eth0.

3.2 不同Node中的Pod之間通信

k8s網(wǎng)絡(luò)模型需要每個(gè)pod必須通過(guò)ip地址可以進(jìn)行訪問(wèn),每個(gè)pod的ip地址總是對(duì)網(wǎng)絡(luò)中的其他pod可見(jiàn),并且每個(gè)pod看待自己的ip與別的pod看待的是一樣的(雖然他沒(méi)規(guī)定如何實(shí)現(xiàn)),下面我們看不同Node間Pod如何交互

k8s中每個(gè)集群中的每個(gè)Node都會(huì)被分配了一個(gè)CIDR塊(無(wú)類(lèi)別域間路由選擇,把網(wǎng)絡(luò)前綴都相同的連續(xù)地址組成的地址組稱(chēng)為CIDR地址塊)用來(lái)給該Node上的Pod分配IP地址。(保證pod的ip不會(huì)沖突)
另外還需要把pod的ip與所在的nodeip關(guān)聯(lián)起來(lái)()

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image

  • 如上圖Node1(vm1)上的Pod1與Node2(vm2)上Pod4之間進(jìn)行交互。
  • 首先pod1通過(guò)自己的以太網(wǎng)設(shè)備eth0把數(shù)據(jù)包發(fā)送到關(guān)聯(lián)到root命名空間的veth0上,然后數(shù)據(jù)包被Node1上的網(wǎng)橋設(shè)備cbr0接受到,網(wǎng)橋查找轉(zhuǎn)發(fā)表發(fā)現(xiàn)找不到pod4的Mac地址,則會(huì)把包轉(zhuǎn)發(fā)到默認(rèn)路由(root命名空間的eth0設(shè)備),然后數(shù)據(jù)包經(jīng)過(guò)eth0就離開(kāi)了Node1,被發(fā)送到網(wǎng)絡(luò)。
  • 數(shù)據(jù)包到達(dá)Node2后,首先會(huì)被root命名空間的eth0設(shè)備,然后通過(guò)網(wǎng)橋cbr0把數(shù)據(jù)路由到虛擬設(shè)備veth1,最終數(shù)據(jù)表會(huì)被流轉(zhuǎn)到與veth1配對(duì)的另外一端(pod4的eth0)

每個(gè)Node都知道如何把數(shù)據(jù)包轉(zhuǎn)發(fā)到其內(nèi)部運(yùn)行的Pod,當(dāng)一個(gè)數(shù)據(jù)包到達(dá)Node后,其內(nèi)部數(shù)據(jù)流就和Node內(nèi)Pod之間的流轉(zhuǎn)類(lèi)似了。

對(duì)于如何來(lái)配置網(wǎng)絡(luò),k8s在網(wǎng)絡(luò)這塊自身并沒(méi)有實(shí)現(xiàn)網(wǎng)絡(luò)規(guī)劃的具體邏輯,而是制定了一套CNI(Container Network Interface)接口規(guī)范,開(kāi)放給社區(qū)來(lái)實(shí)現(xiàn)。

例如AWS,亞馬遜為k8s維護(hù)了一個(gè)容器網(wǎng)絡(luò)插件,使用CNI插件來(lái)讓亞馬遜VPC(虛擬私有云)環(huán)境中的Node與Node直接進(jìn)行交互.

CoreOS的Flannel是k8s中實(shí)現(xiàn)CNI規(guī)范較為出名的一種實(shí)現(xiàn)。

3.2.1 VXLAN

  • UDP幀格式 image.png
  • vlan image.png
k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

  • vxlan協(xié)議格式
    VXLAN 全稱(chēng)是 Virtual eXtensible Local Area Network,虛擬可擴(kuò)展的局域網(wǎng)。它是一種 overlay 技術(shù),通過(guò)三層的網(wǎng)絡(luò)來(lái)搭建虛擬的二層網(wǎng)絡(luò),其幀格式:
    image.png

從這個(gè)報(bào)文中可以看到三個(gè)部分:
1.最外層的 UDP 協(xié)議報(bào)文用來(lái)在底層網(wǎng)絡(luò)上傳輸,也就是 vtep 之間互相通信的基礎(chǔ)
2.中間是 VXLAN 頭部,vtep 接受到報(bào)文之后,去除前面的 UDP 協(xié)議部分,根據(jù)這部分來(lái)處理 vxlan 的邏輯,主要是根據(jù) VNI 發(fā)送到最終的虛擬機(jī)
3.最里面是原始的報(bào)文,也就是虛擬機(jī)看到的報(bào)文內(nèi)容

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

  • VTEP(VXLAN Tunnel Endpoints):vxlan 網(wǎng)絡(luò)的邊緣設(shè)備,用來(lái)進(jìn)行 vxlan 報(bào)文的處理(封包和解包)。vtep 可以是網(wǎng)絡(luò)設(shè)備(比如交換機(jī)),也可以是一臺(tái)機(jī)器(比如虛擬化集群中的宿主機(jī))
  • VNI(VXLAN Network Identifier):VNI 是每個(gè) vxlan 的標(biāo)識(shí),是個(gè) 24 位整數(shù),一共有 2^24 = 16,777,216(一千多萬(wàn)),一般每個(gè) VNI 對(duì)應(yīng)一個(gè)租戶,也就是說(shuō)使用 vxlan 搭建的公有云可以理論上可以支撐千萬(wàn)級(jí)別的租戶
  • Tunnel:隧道是一個(gè)邏輯上的概念,在 vxlan 模型中并沒(méi)有具體的物理實(shí)體對(duì)應(yīng)。隧道可以看做是一種虛擬通道,vxlan 通信雙方(圖中的虛擬機(jī))認(rèn)為自己是在直接通信,并不知道底層網(wǎng)絡(luò)的存在。從整體來(lái)說(shuō),每個(gè) vxlan 網(wǎng)絡(luò)像是為通信的虛擬機(jī)搭建了一個(gè)單獨(dú)的通信通道,也就是隧道

3.2.1 Flannel

Flannel是CoreOS團(tuán)隊(duì)針對(duì)Kubernetes設(shè)計(jì)的一個(gè)網(wǎng)絡(luò)規(guī)劃實(shí)現(xiàn),簡(jiǎn)單來(lái)說(shuō),它的功能有以下幾點(diǎn):

  • 使集群中的不同Node主機(jī)創(chuàng)建的Docker容器都具有全集群唯一的虛擬IP地址。
  • 建立一個(gè)覆蓋網(wǎng)絡(luò)(overlay network),通過(guò)這個(gè)覆蓋網(wǎng)絡(luò),將數(shù)據(jù)包原封不動(dòng)的傳遞到目標(biāo)容器。覆蓋網(wǎng)絡(luò)是建立在另一個(gè)網(wǎng)絡(luò)之上并由其基礎(chǔ)設(shè)施支持的虛擬網(wǎng)絡(luò)。覆蓋網(wǎng)絡(luò)通過(guò)將一個(gè)分組封裝在另一個(gè)分組內(nèi)來(lái)將網(wǎng)絡(luò)服務(wù)與底層基礎(chǔ)設(shè)施分離。在將封裝的數(shù)據(jù)包轉(zhuǎn)發(fā)到端點(diǎn)后,將其解封裝。
  • 創(chuàng)建一個(gè)新的虛擬網(wǎng)卡flannel0接收docker網(wǎng)橋的數(shù)據(jù),通過(guò)維護(hù)路由表,對(duì)接收到的數(shù)據(jù)進(jìn)行封包和轉(zhuǎn)發(fā)(vxlan)。
  • 路由信息一般存放到etcd:多個(gè)node上的Flanneld依賴一個(gè)etcd cluster來(lái)做集中配置服務(wù),etcd保證了所有node上flanned所看到的配置是一致的。同時(shí)每個(gè)node上的flanned監(jiān)聽(tīng)etcd上的數(shù)據(jù)變化,實(shí)時(shí)感知集群中node的變化
  • Flannel首先會(huì)在Node上創(chuàng)建一個(gè)名為flannel0的網(wǎng)橋(vxlan類(lèi)型的設(shè)備),并且在每個(gè)Node上運(yùn)行一個(gè)名為flanneld的代理.每個(gè)node上的flannel代理會(huì)從etcd上為當(dāng)前node申請(qǐng)一個(gè)CIDR地址塊用來(lái)給該node上的pod分配地址。
  • Flannel致力于給k8s集群中的nodes提供一個(gè)3層網(wǎng)絡(luò),他并不控制node中的容器是如何進(jìn)行組網(wǎng)的,僅僅關(guān)心流量如何在node之間流轉(zhuǎn)。image.png
  • 如上圖ip為10.1.15.2的pod1與另外一個(gè)Node上的10.1.20.3的pod2進(jìn)行通信。
  • 首先pod1通過(guò)veth對(duì)把數(shù)據(jù)包發(fā)送到docker0虛擬網(wǎng)橋,網(wǎng)橋通過(guò)查找轉(zhuǎn)發(fā)表發(fā)現(xiàn)10.1.20.3不在自己管理的網(wǎng)段,就會(huì)把數(shù)據(jù)包
    轉(zhuǎn)發(fā)給默認(rèn)路由(這里為flannel0網(wǎng)橋)
  • flannel.0網(wǎng)橋是一個(gè)vxlan設(shè)備,flannel.0收到數(shù)據(jù)包后,由于自己不是目的地10.1.20.3,也要嘗試將數(shù)據(jù)包重新發(fā)送出去。數(shù)據(jù)包沿著網(wǎng)絡(luò)協(xié)議棧向下流動(dòng),在二層時(shí)需要封二層以太包,填寫(xiě)目的mac地址,這時(shí)一般應(yīng)該發(fā)出arp:”who is 10.1.20.3″。但vxlan設(shè)備的特殊性就在于它并沒(méi)有真正在二層發(fā)出這個(gè)arp包,而是由linux kernel引發(fā)一個(gè)”L3 MISS”事件并將arp請(qǐng)求發(fā)到用戶空間的flanned程序。
  • flanned程序收到”L3 MISS”內(nèi)核事件以及arp請(qǐng)求(who is 10.1.20.3)后,并不會(huì)向外網(wǎng)發(fā)送arp request,而是嘗試從etcd查找該地址匹配的子網(wǎng)的vtep信息,也就是會(huì)找到node2上的flanel.0的mac地址信息,flanned將查詢到的信息放入node1 host的arp cache表中,flanneel0完成這項(xiàng)工作后,linux kernel就可以在arp table中找到 10.1.20.3對(duì)應(yīng)的mac地址并封裝二層以太包了:
k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

  • 由于是Vlanx設(shè)備,flannel0還會(huì)對(duì)上面的包進(jìn)行二次封裝,封裝新的以太網(wǎng)mac幀: image.png
  • node上2的eth0接收到上述vxlan包,kernel將識(shí)別出這是一個(gè)vxlan包,于是拆包后將packet轉(zhuǎn)給node上2的flannel.0。flannel.0再將這個(gè)數(shù)據(jù)包轉(zhuǎn)到docker0,繼而由docker0傳輸?shù)絇od2的某個(gè)容器里。

如上圖,總的來(lái)說(shuō)就是建立VXLAN 隧道,通過(guò)UDP把IP封裝一層直接送到對(duì)應(yīng)的節(jié)點(diǎn),實(shí)現(xiàn)了一個(gè)大的 VLAN。

4.Pod與Service之間的網(wǎng)絡(luò)

上面展示了Pod之間如何通過(guò)他們自己的ip地址進(jìn)行通信,但是pod的ip地址是不持久的,當(dāng)集群中pod的規(guī)模縮減或者pod故障或者node故障重啟后,新的pod的ip就可能與之前的不一樣的。所以k8s中衍生出來(lái)Service來(lái)解決這個(gè)問(wèn)題。

k8s中 Service管理了一系列的Pods,每個(gè)Service有一個(gè)虛擬的ip,要訪問(wèn)service管理的Pod上的服務(wù)只需要訪問(wèn)你這個(gè)虛擬ip就可以了,這個(gè)虛擬ip是固定的,當(dāng)service下的pod規(guī)模改變、故障重啟、node重啟時(shí)候,對(duì)使用service的用戶來(lái)說(shuō)是無(wú)感知的,因?yàn)樗麄兪褂玫膕ervice的ip沒(méi)有變。

當(dāng)數(shù)據(jù)包到達(dá)Service虛擬ip后,數(shù)據(jù)包會(huì)被通過(guò)k8s給該servcie自動(dòng)創(chuàng)建的負(fù)載均衡器路由到背后的pod容器。下面我們看看具體是如何做到的

4.1 netfilter

為了實(shí)現(xiàn)負(fù)載均衡,k8s依賴linux內(nèi)建的網(wǎng)絡(luò)框架-netfilter。Netfilter是Linux提供的內(nèi)核態(tài)框架,允許使用者自定義處理接口實(shí)現(xiàn)各種與網(wǎng)絡(luò)相關(guān)的操作。 Netfilter為包過(guò)濾,網(wǎng)絡(luò)地址轉(zhuǎn)換和端口轉(zhuǎn)換提供各種功能和操作,以及提供禁止數(shù)據(jù)包到達(dá)計(jì)算機(jī)網(wǎng)絡(luò)內(nèi)敏感位置的功能。在linux內(nèi)核協(xié)議棧中,有5個(gè)跟netfilter有關(guān)的鉤子函數(shù),數(shù)據(jù)包經(jīng)過(guò)每個(gè)鉤子時(shí),都會(huì)檢查上面是否注冊(cè)有函數(shù),如果有的話,就會(huì)調(diào)用相應(yīng)的函數(shù)處理該數(shù)據(jù)包

| | Incoming ↓+-------------------+| NF_IP_PRE_ROUTING |+-------------------+ | | ↓+------------------+| | +----------------+| routing decision |-------->| NF_IP_LOCAL_IN || | +----------------++------------------+ | | | || +-----------------+ | | local processes | | +-----------------+ | | | | ↓ ↓ +---------------+ +-----------------+ | NF_IP_FORWARD | | NF_IP_LOCAL_OUT | +---------------+ +-----------------+ | | | | ↓ |+------------------+ || | || routing decision |<----------------+| |+------------------+ | | ↓+--------------------+| NF_IP_POST_ROUTING |+--------------------+ | | Outgoing ↓
  • NF_IP_PRE_ROUTING: 接收的數(shù)據(jù)包剛進(jìn)來(lái),還沒(méi)有經(jīng)過(guò)路由選擇,即還不知道數(shù)據(jù)包是要發(fā)給本機(jī)還是其它機(jī)器。
  • NF_IP_LOCAL_IN: 已經(jīng)經(jīng)過(guò)路由選擇,并且該數(shù)據(jù)包的目的IP是本機(jī),進(jìn)入本地?cái)?shù)據(jù)包處理流程。
  • NF_IP_FORWARD: 已經(jīng)經(jīng)過(guò)路由選擇,但該數(shù)據(jù)包的目的IP不是本機(jī),而是其它機(jī)器,進(jìn)入forward流程。
  • NF_IP_LOCAL_OUT: 本地程序要發(fā)出去的數(shù)據(jù)包剛到IP層,還沒(méi)進(jìn)行路由選擇。
  • NF_IP_POST_ROUTING: 本地程序發(fā)出去的數(shù)據(jù)包,或者轉(zhuǎn)發(fā)(forward)的數(shù)據(jù)包已經(jīng)經(jīng)過(guò)了路由選擇,即將交由下層發(fā)送出去。

netfilter是工作在一層?

4.2 iptables

iptables是運(yùn)行在用戶態(tài)的用戶程序,其基于表來(lái)管理規(guī)則,用于定義使用netfilter框架操作和轉(zhuǎn)換數(shù)據(jù)包的規(guī)則。根據(jù)rule的作用分成了好幾個(gè)表,比如用來(lái)過(guò)濾數(shù)據(jù)包的rule就會(huì)放到filter表中,用于處理地址轉(zhuǎn)換的rule就會(huì)放到nat表中,其中rule就是應(yīng)用在netfilter鉤子上的函數(shù),用來(lái)修改數(shù)據(jù)包的內(nèi)容或過(guò)濾數(shù)據(jù)包。目前iptables支持的表有下面這些:

  • Filter:從名字就可以看出,這個(gè)表里面的rule主要用來(lái)過(guò)濾數(shù)據(jù),用來(lái)控制讓哪些數(shù)據(jù)可以通過(guò),哪些數(shù)據(jù)不能通過(guò),它是最常用的表。
  • NAT(*):里面的rule都是用來(lái)處理網(wǎng)絡(luò)地址轉(zhuǎn)換的,控制要不要進(jìn)行地址轉(zhuǎn)換,以及怎樣修改源地址或目的地址,從而影響數(shù)據(jù)包的路由,達(dá)到連通的目的,這是家用路由器必備的功能。
  • Mangle:里面的rule主要用來(lái)修改IP數(shù)據(jù)包頭,比如修改TTL值,同時(shí)也用于給數(shù)據(jù)包添加一些標(biāo)記,從而便于后續(xù)其它模塊對(duì)數(shù)據(jù)包進(jìn)行處理(這里的添加標(biāo)記是指往內(nèi)核skb結(jié)構(gòu)中添加標(biāo)記,而不是往真正的IP數(shù)據(jù)包上加?xùn)|西)。
  • Raw:在netfilter里面有一個(gè)叫做connection tracking的功能,主要用來(lái)追蹤所有的連接,而raw表里的rule的功能是給數(shù)據(jù)包打標(biāo)記,從而控制哪些數(shù)據(jù)包不被connection tracking所追蹤。
  • Security:里面的rule跟SELinux有關(guān),主要是在數(shù)據(jù)包上設(shè)置一些SELinux的標(biāo)記,便于跟SELinux相關(guān)的模塊來(lái)處理該數(shù)據(jù)包。

在k8s中,iptables規(guī)則由kube-proxy控制器配置,該控制器監(jiān)視K8s API服務(wù)器的更改。當(dāng)對(duì)Service或Pod的虛擬IP地址進(jìn)行修改時(shí),iptables規(guī)則也會(huì)更新以便讓service能夠正確的把數(shù)據(jù)包路由到后端Pod。

iptables規(guī)則監(jiān)視發(fā)往Service虛擬IP的流量,并且在匹配時(shí),從可用Pod集合中選擇隨機(jī)Pod IP地址,iptables規(guī)則將數(shù)據(jù)包的目標(biāo)IP地址從Service的虛擬IP更改為選定的Pod的ip??偟膩?lái)說(shuō)iptables已在機(jī)器上完成負(fù)載平衡,并將指向Servcie的虛擬IP的流量轉(zhuǎn)移到實(shí)際的pod的IP。

在從service到pod的路徑上,IP地址來(lái)自目標(biāo)Pod。 在這種情況下,iptables再次重寫(xiě)IP頭以將Pod IP替換為Service的IP,以便Pod認(rèn)為它一直與Service的虛擬IP通信。

4.3 IPVS

k8s的最新版本(1.11)包括了用于集群內(nèi)負(fù)載平衡的第二個(gè)選項(xiàng):IPVS。 IPVS(IP Virtual Server)也構(gòu)建在netfilter之上,并實(shí)現(xiàn)傳輸層負(fù)載平衡(屬于Linux內(nèi)核的一部分)。 IPVS包含在LVS(Linux虛擬服務(wù)器)中,它在主機(jī)上運(yùn)行,并在真實(shí)服務(wù)器集群前充當(dāng)負(fù)載均衡器。 IPVS可以將對(duì)基于TCP和UDP的服務(wù)的請(qǐng)求定向到真實(shí)服務(wù)器,并使真實(shí)服務(wù)器的服務(wù)在單個(gè)IP地址上顯示為虛擬服務(wù)。這使得IPVS非常適合Kubernetes服務(wù)。

聲明Kubernetes服務(wù)時(shí),您可以指定是否要使用iptables或IPVS完成群集內(nèi)負(fù)載平衡。 IPVS專(zhuān)門(mén)用于負(fù)載平衡,并使用更高效的數(shù)據(jù)結(jié)構(gòu)(哈希表),與iptables相比,允許幾乎無(wú)限的規(guī)模。在創(chuàng)建IPVS負(fù)載時(shí),會(huì)發(fā)生以下事情:在Node上創(chuàng)建虛擬IPVS接口,將Service的IP地址綁定到虛擬IPVS接口,并為每個(gè)Service額IP地址創(chuàng)建IPVS服務(wù)器。將來(lái),期望IPVS成為集群內(nèi)負(fù)載平衡的默認(rèn)方法。

4.4 Pod到Service的一個(gè)包的流轉(zhuǎn)

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image

  • 如上圖當(dāng)從一個(gè)Pod發(fā)送數(shù)據(jù)包到Service時(shí)候,數(shù)據(jù)包先從Pod1所在的虛擬設(shè)備eth0離開(kāi)pod1,并通過(guò)veth對(duì)的另外一端veth0傳遞給網(wǎng)橋cbr0,網(wǎng)橋找不到service對(duì)應(yīng)ip的mac地址,所以把包轉(zhuǎn)發(fā)給默認(rèn)路由,也就是root命名空間的eth0
  • 在root命名空間的設(shè)備eth0接受到數(shù)據(jù)包前,數(shù)據(jù)包會(huì)經(jīng)過(guò)iptables進(jìn)行過(guò)濾,iptables接受數(shù)據(jù)包后會(huì)使用kube-proxy在Node上安裝的規(guī)則來(lái)響應(yīng)Service或Pod的事件,將數(shù)據(jù)包的目的地址從Service的IP重寫(xiě)為Service后端特定的Pod IP(本例子中是pod4).
  • 現(xiàn)在數(shù)據(jù)包的目的ip就不再是service的ip地址了,而是pod4的ip地址。
  • iptables利用Linux內(nèi)核的conntrack來(lái)記住所做的Pod選擇,以便將來(lái)的流量路由到同一個(gè)Pod(禁止任何擴(kuò)展事件)。 從本質(zhì)上講,iptables直接在Node上進(jìn)行了集群內(nèi)負(fù)載均衡,然后流量使用我們已經(jīng)檢查過(guò)的Pod-to-Pod路由流到Pod。

4.5 Service到Pod的一個(gè)包的流轉(zhuǎn)

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image

  • 收到此數(shù)據(jù)包的Pod將會(huì)回發(fā)包到源Pod,回包的源IP識(shí)別為自己的IP(比如這里為Pod4的ip),將目標(biāo)IP設(shè)置為最初發(fā)送數(shù)據(jù)包的Pod(這里為pod1的ip)。
  • 數(shù)據(jù)包進(jìn)入目標(biāo)Pod(這里為Pod1)所在節(jié)點(diǎn)后,數(shù)據(jù)包流經(jīng)iptables,它使用conntrack記住它之前做出的選擇,并將數(shù)據(jù)包的源IP重寫(xiě)為Service的IP。 從這里開(kāi)始,數(shù)據(jù)包通過(guò)網(wǎng)橋流向與Pod1的命名空間配對(duì)的虛擬以太網(wǎng)設(shè)備,并流向我們之前看到的Pod1的以太網(wǎng)設(shè)備。

5.Internet與Service之間的網(wǎng)絡(luò)

到目前為止,我們已經(jīng)了解了如何在Kubernetes集群中路由流量。下面我們希望將服務(wù)暴露給外部使用(互聯(lián)網(wǎng))。 這需要強(qiáng)調(diào)兩個(gè)相關(guān)的問(wèn)題:(1)從k8s的service訪問(wèn)Internet,以及(2)從Internet訪問(wèn)k8s的service.

5.1 k8s流量到Internet

從Node到公共Internet的路由流量是特定于網(wǎng)絡(luò)的,實(shí)際上取決于網(wǎng)絡(luò)配置。為了使本節(jié)更具體,下面使用AWS VPC討論具體細(xì)節(jié)。

在AWS中,k8s集群在VPC內(nèi)運(yùn)行,其中每個(gè)Node都分配了一個(gè)可從k8s集群內(nèi)訪問(wèn)的私有IP地址。要使群集外部的流量可訪問(wèn),需要將Internet網(wǎng)關(guān)連接到VPC。 Internet網(wǎng)關(guān)有兩個(gè)目的:在VPC路由表中提供可以路由到Internet的流量的目標(biāo),以及為已分配公共IP地址的任何實(shí)例執(zhí)行網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT)。 NAT轉(zhuǎn)換負(fù)責(zé)將群集專(zhuān)用的節(jié)點(diǎn)內(nèi)部IP地址更改為公共Internet中可用的外部IP地址。

通過(guò)Internet網(wǎng)關(guān),Node可以將流量路由到Internet。不幸的是,有一個(gè)小問(wèn)題。 Pod具有自己的IP地址,該IP地址與承載Pod的Node的IP地址不同,并且Internet網(wǎng)關(guān)上的NAT轉(zhuǎn)換僅適用于Node的 IP地址,因?yàn)樗恢繬ode上正在運(yùn)行那些Pod - Internet網(wǎng)關(guān)不是容器感知的。讓我們?cè)俅慰纯磌8s如何使用iptables解決這個(gè)問(wèn)題。

本質(zhì)都是使用NAT來(lái)做

5.1.1 Node到Internet

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image

  • 如上圖中,數(shù)據(jù)包源自Pod1的網(wǎng)絡(luò)命名空間,并通過(guò)veth對(duì)連接到root命名空間。
  • 一旦root命名空間,數(shù)據(jù)包就會(huì)從網(wǎng)橋cbr0流傳到到默認(rèn)設(shè)備eth0,因?yàn)閿?shù)據(jù)包上的目的IP與連接到網(wǎng)橋的任何網(wǎng)段都不匹配,在到達(dá)root命名空間的以太網(wǎng)設(shè)備eth0之前,iptables會(huì)修改數(shù)據(jù)包。
  • 在這種情況下,數(shù)據(jù)包的源IP地址是Pod1的ip地址,如果我們將源保持為Pod1,則Internet網(wǎng)關(guān)將拒絕它,因?yàn)榫W(wǎng)關(guān)NAT僅了解連接到vm的IP地址。解決方案是讓iptables執(zhí)行源NAT - 更改數(shù)據(jù)包源 - 以便數(shù)據(jù)包看起來(lái)來(lái)自VM而不是Pod。
  • 有了正確的源IP,數(shù)據(jù)包現(xiàn)在可以離開(kāi)VM,并到達(dá)Internet網(wǎng)關(guān)。 Internet網(wǎng)關(guān)將執(zhí)行另一個(gè)NAT,將源IP從VM內(nèi)部IP重寫(xiě)為Internet IP。最后,數(shù)據(jù)包將到達(dá)公共互聯(lián)網(wǎng)。在回來(lái)數(shù)據(jù)包的路上,數(shù)據(jù)包遵循相同的路徑,任何源IP都會(huì)與發(fā)送時(shí)候做相同的修改操作,以便系統(tǒng)的每一層都接收它理解的IP地址:Node,以及Pod命名空間中中的Pod IP。

5.2 Internet到k8s

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

讓Internet流量進(jìn)入k8s集群,這特定于配置的網(wǎng)絡(luò),可以在網(wǎng)絡(luò)堆棧的不同層來(lái)實(shí)現(xiàn):

  • (1) NodePort
  • (2)Service LoadBalancer
  • (3)Ingress控制器。

5.2.1 第四層流量入口:NodePort

讓外網(wǎng)訪問(wèn)k8s內(nèi)部的服務(wù)的第一個(gè)方法是創(chuàng)建一個(gè)NodePort類(lèi)型的Service,
對(duì)于NodePort類(lèi)型的Service,k8s集群中的每個(gè)Node都會(huì)打開(kāi)一個(gè)端口(所有Node上的端口相同),并將該端口上收到的流量重定向到具體的Service。

對(duì)于NodePort類(lèi)型的Service,我們可以通過(guò)任何Node的ip和端口號(hào)來(lái)訪問(wèn)NodePort服務(wù)。

創(chuàng)建NodePort類(lèi)型的服務(wù):

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

如下圖,服務(wù)暴露在兩個(gè)節(jié)點(diǎn)的端口30123上,到達(dá)任何一個(gè)端口的鏈接會(huì)被重定向到一個(gè)隨機(jī)選擇的Pod。

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

如何做到的?

NodePort是靠kube-proxy服務(wù)通過(guò)iptables的nat轉(zhuǎn)換功能實(shí)現(xiàn)的,kube-proxy會(huì)在運(yùn)行過(guò)程中動(dòng)態(tài)創(chuàng)建與Service相關(guān)的iptables規(guī)則,這些規(guī)則實(shí)現(xiàn)了NodePort的請(qǐng)求流量重定向到kube-proxy進(jìn)程上對(duì)應(yīng)的Service的代理端口上。

kube-proxy接受到Service的請(qǐng)求訪問(wèn)后,會(huì)從service對(duì)應(yīng)的后端Pod中選擇一個(gè)進(jìn)行訪問(wèn)(RR)

但 NodePort 還沒(méi)有完全解決外部訪問(wèn) Service 的所有問(wèn)題,比如負(fù)載均衡問(wèn)題,假如我們 的集群中有 10 個(gè) Node,則此時(shí)最好有一個(gè)負(fù)載均衡器,外部的請(qǐng)求只需訪問(wèn)此負(fù)載均衡器的 IP 地址,由負(fù)載均衡器負(fù) 責(zé)轉(zhuǎn)發(fā)流量到后面某個(gè) Node 的 NodePort 上

5.2.2 第四層流量入口:LoadBalancer

該方式是NodePort方式的擴(kuò)展,這使得Service可以通過(guò)一個(gè)專(zhuān)用的負(fù)載均衡器來(lái)訪問(wèn),這個(gè)是由具體云服務(wù)提供商來(lái)提供的,負(fù)載均衡器將流量重定向到所有節(jié)點(diǎn)的端口上,如果云提供商不支持負(fù)載均衡,則退化為NodePort類(lèi)型

創(chuàng)建k8s service時(shí),可以選擇指定LoadBalancer。 LoadBalancer的實(shí)現(xiàn)由云控制器提供,該控制器知道如何為您的service創(chuàng)建負(fù)載均衡器。 創(chuàng)建service后,它將公布負(fù)載均衡器的IP地址。 作為最終用戶,可以開(kāi)始將流量定向到負(fù)載均衡器以開(kāi)始與提供的service進(jìn)行通信。

創(chuàng)建一個(gè)負(fù)載均衡服務(wù):

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

借助AWS,負(fù)載均衡器可以識(shí)別其目標(biāo)組中的Node,并將平衡群集中所有節(jié)點(diǎn)的流量。 一旦流量到達(dá)Node,之前在整個(gè)群集中為Service安裝的iptables規(guī)則將確保流量到達(dá)感興趣的Service的Pod上。

下面看下LoadBalancer到Service的一個(gè)數(shù)據(jù)包的流轉(zhuǎn)過(guò)程:

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image

  • 我們來(lái)看看LoadBalancer在實(shí)踐中是如何運(yùn)作的。部署Service后,正在使用的云提供商將會(huì)創(chuàng)建一個(gè)新的負(fù)載均衡器(1)。
  • 由于負(fù)載均衡器不能識(shí)別容器,因此一旦流量到達(dá)負(fù)載均衡器,它就會(huì)把數(shù)據(jù)包發(fā)送到在構(gòu)成群集的某個(gè)Node中(2)。每個(gè)Node上的iptables規(guī)則將來(lái)自負(fù)載均衡器的傳入流量重定向到正確的Pod(3)
  • 這些iptables規(guī)則是在service創(chuàng)建時(shí)候創(chuàng)建。從Pod到請(qǐng)求方的響應(yīng)將返回Pod的IP,但請(qǐng)求方需要具有負(fù)載均衡器的IP地址。這就需要iptables和conntrack用于在返回路徑上正確地重寫(xiě)IP。

上圖顯示了承載Pod的三個(gè)Node前面的網(wǎng)絡(luò)負(fù)載平衡器。首先流量被傳到的Service的負(fù)載均衡器(1)。一旦負(fù)載均衡器收到數(shù)據(jù)包(2),它就會(huì)隨機(jī)選擇一個(gè)VM。這里我們故意選擇了沒(méi)有Pod運(yùn)行的node:node 2。在這里,node上運(yùn)行的iptables規(guī)則將使用kube-proxy安裝在集群中的內(nèi)部負(fù)載平衡規(guī)則將數(shù)據(jù)包定向到正確的Node 中的Pod。 iptables執(zhí)行正確的NAT并將數(shù)據(jù)包轉(zhuǎn)發(fā)到正確的Pod(4)。

需要注意的是每個(gè)服務(wù)需要?jiǎng)?chuàng)建自己獨(dú)有的負(fù)載均衡器,下面要講解的一種方式所有服務(wù)只需要一個(gè)公開(kāi)服務(wù)。

5.2.3 第七層流量入口:Ingress Controller

這是一個(gè)與上面提到的兩種方式完全不同的機(jī)制,通過(guò)一個(gè)公開(kāi)的ip地址來(lái)公開(kāi)多個(gè)服務(wù),第7層網(wǎng)絡(luò)流量入口是在網(wǎng)絡(luò)堆棧的HTTP / HTTPS協(xié)議范圍內(nèi)運(yùn)行,并建立在service之上。

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

如上圖,不像負(fù)載均衡器每個(gè)服務(wù)需要一個(gè)公開(kāi)ip,ingress所有服務(wù)只需要一個(gè)公網(wǎng)ip,當(dāng)客戶端向Ingress發(fā)送http請(qǐng)求時(shí)候,ingress會(huì)根據(jù)請(qǐng)求的主機(jī)名和路徑?jīng)Q定請(qǐng)求轉(zhuǎn)發(fā)到那個(gè)服務(wù)。

創(chuàng)建Ingress資源:

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

如上定義了一個(gè)單一規(guī)則的Ingress,確保Ingress控制器接受的所有請(qǐng)求主機(jī)kubia.example.com的http請(qǐng)求被發(fā)送到端口80上的kubia-nodeport服務(wù)上。

工作原理:
如下圖,客戶端首先對(duì)kubia.example.com執(zhí)行DNS查找,DNS服務(wù)器返回Ingress控制器的IP,客戶端拿到IP后,向Ingress控制器發(fā)送Http請(qǐng)求,并在Host投中指定kubia.example.com??刂破鹘邮艿秸?qǐng)求后從Host頭部就知道該訪問(wèn)那個(gè)服務(wù),通過(guò)與該Service關(guān)聯(lián)的endpoint對(duì)象查詢Pod ip,并將請(qǐng)求轉(zhuǎn)發(fā)到某一個(gè)Pod。

這里Ingress并沒(méi)把請(qǐng)求轉(zhuǎn)發(fā)給Service,而是自己選擇一個(gè)一個(gè)Pod來(lái)訪問(wèn)。

k8s中docker,pod,service之間網(wǎng)絡(luò)通信模型

image.png

第7層負(fù)載均衡器的一個(gè)好處是它們具有HTTP感知能力,因此它們了解URL和路徑。 這允許您按URL路徑細(xì)分服務(wù)流量。 它們通常還在HTTP請(qǐng)求的X-Forwarded-For標(biāo)頭中提供原始客戶端的IP地址。

本文參考自:https://blog.csdn.net/liangzhiyang/article/details/106349195

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多

    精品al亚洲麻豆一区| 日本欧美三级中文字幕| 99香蕉精品视频国产版| 男人和女人黄 色大片| 国产精品午夜一区二区三区| 国产毛片对白精品看片| 九九热国产这里只有精品| 日韩精品视频免费观看| 老司机精品线观看86| 欧美一级片日韩一级片| 99国产一区在线播放| 成年午夜在线免费视频| 中文字幕中文字幕在线十八区| 91人妻人人澡人人人人精品| 日本和亚洲的香蕉视频| 欧美日韩成人在线一区| 亚洲一区二区精品国产av| 插进她的身体里在线观看骚| 亚洲午夜福利视频在线| 欧美欧美日韩综合一区| 欧美成人免费夜夜黄啪啪 | 精品久久久一区二区三| 黑色丝袜脚足国产一区二区| 欧美日韩国产一级91| 精品欧美一区二区三久久| 亚洲av熟女一区二区三区蜜桃| 风间中文字幕亚洲一区| 久久综合九色综合欧美| 视频一区二区三区自拍偷| 国产精品美女午夜视频| 国产精品久久精品毛片| 亚洲国产av精品一区二区| 操白丝女孩在线观看免费高清| 久久91精品国产亚洲| 欧美日韩国产精品黄片| 蜜臀人妻一区二区三区| 91人妻人澡人人爽人人精品| 亚洲少妇一区二区三区懂色| 青青草草免费在线视频| 91欧美视频在线观看免费| 不卡一区二区高清视频|