您好,登錄后才能下訂單哦!
Flannel-UDP在kubernetes中如何工作,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
Kubernetes是用于大規模管理容器化應用程序出色的編排工具。但是,您可能知道,使用kubernetes并非易事,尤其是后端網絡實現。我在網絡中遇到了許多問題,花了我很多時間弄清楚它是如何工作的。
我想以最簡單的實現為例,來解釋kubernetes的網絡工作。
下圖顯示了kubernetes集群的簡單圖像:
Kubernetes管理Linux機器集群(可能是ECS之類的云VM或物理服務器),在每臺主機上,kubernetes運行任意數量的Pod,在每個Pod中可以有任意數量的容器。用戶的應用程序正在這些容器之一中運行。
對于kubernetes,Pod是最小的管理單元,并且一個Pod中的所有容器共享相同的網絡名稱空間,這意味著它們具有相同的網絡接口并且可以使用*localhost
*相互連接
在官方文件中說kubernetes網絡模式要求:
我們可以按照上述要求將所有容器替換為Pod,因為容器與Pod網絡共享。
基本上,這意味著所有Pod都應該能夠與群集中的其他Pod自由通信,即使它們位于不同的主機中,并且它們也使用自己的IP地址相互識別,就像基礎主機不存在一樣。此外,主機也應該能夠使用自己的IP地址與任何Pod通信,而無需任何地址轉換。
Kubernetes不提供任何默認的網絡實現,而是僅定義模型,并由其他工具來實現。如今有很多實現,Flannel是其中之一,也是最簡單的之一。在以下各節中,我將解釋Flannel的UDP模式實現。
Flannel是由CoreOS創建的,用于Kubernetes網絡,也可以用作其他目的的通用軟件定義網絡解決方案。
為了滿足kubernetes的網絡要求,flannel的想法很簡單:創建另一個在主機網絡之上運行的扁平網絡,這就是所謂的覆蓋網絡overlay network。在此覆蓋網絡中,所有容器(Pod)將被分配一個IP地址,它們通過直接調用彼此的IP地址來相互通信。
為了幫助解釋,我在AWS上使用了一個小型的測試kubernetes集群,該集群中有3個Kubernetes節點。網絡如下所示:
此群集中有三個網絡:
AWS VPC網絡:所有實例都在一個VPC子網中172.20.32.0/19
。它們已經在此范圍內分配了ip地址,所有主機都可以彼此連接,因為它們位于同一LAN中。
Flannel overlay network:flannel創建了另一個網絡100.96.0.0/16
,它是一個更大的網絡,可以容納65536個地址,并且遍及所有kubernetes節點,將在此范圍內為每個Pod分配一個地址,稍后我們將看到flannel如何實現此目的。
主機內docker網絡:在每個主機內部,flannel為該主機中的所有pod分配了一個網絡100.96.x.0/24
,它可以容納256地址。docker橋接接口docker0
將使用此網絡創建新容器。
通過這種設計,每個容器都有其自己的IP地址,都屬于覆蓋子網100.96.0.0/16
。同一主機內的容器可以通過docker bridge網絡接口Docker0
相互通信,這很簡單,因此在本文中我將跳過。為了在主機上與覆蓋網絡中的其他容器進行跨主機通信,flannel使用內核路由表和UDP封裝來實現該功能,以下各節對此進行了說明。
假設具有IP地址的節點1中的容器(我們將其稱為容器1)100.96.1.2
要使用IP地址連接到節點2中的容器(我們將其稱為容器2)100.96.2.3
,讓我們看看覆蓋網絡如何啟用數據包通過。
第一個container-1使用創建一個IP數據包src: 100.96.1.2 -> dst: 100.96.2.3
,該數據包將作為容器的網關進入docker0網橋。
在每個主機中,flannel運行一個名為的守護進程flanneld
,它在內核的路由表中創建一些路由規則,這是節點1的路由表的樣子:
admin@ip-172-20-33-102:~$ ip route
default via 172.20.32.1 dev eth0
100.96.0.0/16 dev flannel0 proto kernel scope link src 100.96.1.0
100.96.1.0/24 dev docker0 proto kernel scope link src 100.96.1.1
172.20.32.0/19 dev eth0 proto kernel scope link src 172.20.33.102
如我們所見,數據包的目標地址100.96.2.3
位于更大的覆蓋網絡中100.96.0.0/16
,因此它與第二條規則匹配,現在內核知道應該將數據包發送到flannel0
。
flannel0
TUN是由我們的flanneld
守護進程創建的TUN設備,TUN是在Linux內核中實現的軟件接口,它可以在用戶程序和內核之間傳遞原始ip數據包。它在兩個方向上起作用:
flannel0
設備時,該數據包將直接發送到內核,內核將根據其路由表對數據包進行路由flannel0
設備時,內核會將數據包直接發送到創建該設備的
flanneld
進程,該進程是守護進程。當內核將數據包發送到TUN設備時,它將直接進入flanneld
進程,它看到目標地址為100.96.2.3
,盡管從圖中可以看出該地址屬于在Node 2上運行的容器,但是如何flanneld
知道呢?
Flannel碰巧將某些信息存儲在名為etcd的鍵值存儲服務中,如果您知道kubernetes,則不應感到驚訝。在flannel,我們可以將其視為常規鍵值存儲。
Flannel將子網映射信息存儲到etcd服務中,我們可以使用以下etcdctl
命令查看它:
admin@ip-172-20-33-102:~$ etcdctl ls /coreos.com/network/subnets
/coreos.com/network/subnets/100.96.1.0-24
/coreos.com/network/subnets/100.96.2.0-24
/coreos.com/network/subnets/100.96.3.0-24
admin@ip-172-20-33-102:~$ etcdctl get /coreos.com/network/subnets/100.96.2.0-24
{"PublicIP":"172.20.54.98"}
因此,每個flanneld
進程查詢etcd都知道每個子網屬于哪個主機,并將目標ip地址與etcd中存儲的所有子網密鑰進行比較。在本例中,該地址100.96.2.3
將與子網匹配100.96.2.0-24
,并且如我們所見,存儲在此鍵中的值表示Node ip為172.20.54.98
。
現在flanneld
知道了目的地址,然后將原始IP數據包包裝到UDP數據包中,以其自己的主機ip作為源地址,而目標主機的IP作為目的地址。在每個主機中,該flanneld
進程將偵聽默認的UDP端口:8285
。因此,只需要將UDP數據包的目標端口設置為8285
,然后通過網絡發送它。
UDP數據包到達目標主機后,內核的IP堆棧會將數據包發送到flanneld
進程,因為那是用戶進程在UDP端口上偵聽:8285
。然后flanneld
將獲得UDP數據包的有效負載,該數據包是由原始容器生成的原始IP數據包,只需將其寫入TUN設備flannel0
,然后該數據包將直接傳遞到內核,這就是TUN的工作方式。
與節點1相同,路由表將決定此數據包的去向,讓我們看一下節點2的路由表:
admin@ip-172-20-54-98:~$ ip route
default via 172.20.32.1 dev eth0
100.96.0.0/16 dev flannel0 proto kernel scope link src 100.96.2.0
100.96.2.0/24 dev docker0 proto kernel scope link src 100.96.2.1
172.20.32.0/19 dev eth0 proto kernel scope link src 172.20.54.98
IP數據包的目標地址是100.96.2.3
,內核將采用最精確的匹配,這是第三條規則。數據包將發送到docker0
設備。就像docker0
橋接設備一樣,此主機中的所有容器都連接到該橋接器,最終目的地容器2將看到并接收到該數據包。
最終,我們的數據包完成了一種傳遞到目標的方式,當contianer-2將數據包發送回容器1時,反向路由將以完全相同的方式工作。這就是跨主機容器通信的工作方式。
在以上解釋中,我們遺漏了一點。這就是我們如何配置docker使用較小的子網100.96.x.0/24
?
碰巧flanneld
會將其子網信息寫入主機中的文件中:
admin@ip-172-20-33-102:~$ cat /run/flannel/subnet.env
FLANNEL_NETWORK=100.96.0.0/16
FLANNEL_SUBNET=100.96.1.1/24
FLANNEL_MTU=8973
FLANNEL_IPMASQ=true
該信息將用于配置docker守護程序的選項,因此docker可以將FLANNEL_SUBNET
用作其橋接網絡,然后主機容器網絡將起作用:
dockerd --bip = $ FLANNEL_SUBNET --mtu = $ FLANNEL_MTU
較新版本的flannel不建議將UDP封裝用于生產,它表示僅應將其用于調試和測試目的。原因之一是性能。
盡管flannel0
TUN設備提供了一種通過內核獲取和發送數據包的簡單方法,但它會降低性能:必須將數據包從用戶空間來回復制到內核空間:
如上所述,必須從原始容器進程發送數據包,然后在用戶空間和內核空間之間復制3次,這將顯著增加網絡開銷,因此,如果可以的話,應避免在生產中使用UDP。
Flannel是kubernetes網絡模型的最簡單實現之一。它使用現有的Docker網絡和帶有守護進程的額外Tun設備進行UDP封裝。我解釋了核心部分的詳細信息:跨主機容器通信,并簡要提到了性能損失。
看完上述內容,你們掌握Flannel-UDP在kubernetes中如何工作的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。