k8s的Flannel網(wǎng)絡(luò)

引: 之前寫過一篇文章介紹如何管理linux設(shè)備上的bridge(網(wǎng)橋)和docker bridge, 今天我們來看看k8s的網(wǎng)絡(luò)模型幕屹。

我們先來看圖示例,下面則個是k8s的網(wǎng)絡(luò)模型圖邪铲。

k8s的網(wǎng)絡(luò)模型

我們知道,在k8s里面最小的管理單元是pod无拗,一個主機(jī)可以跑多個pod带到,一個pod里面可以跑多個容器。

如上面所示英染,一個pod里面所有的容器共享一個網(wǎng)絡(luò)命名空間(network namespace)揽惹,所以被饿,pod里面的容器之間通信,可以直接通過localhost來完成搪搏,pod里面的容器之間通過localhost+端口的方式來通信(這和應(yīng)用程序在宿主機(jī)的通信方式是一樣的)狭握。

那么pod和pod之間的通信呢?通常來說慕嚷,我們給應(yīng)用程序定死端口會給應(yīng)用程序水平擴(kuò)展帶來很多不便哥牍,所以k8s不會使用定死端口這樣的方法,而是采用其他方法來解決pod之間尋址的問題

每個pod都會有一個自己的ip喝检,可以將Pod像VM或物理主機(jī)一樣對待。這樣pod和pod之間的通信就不需要像容器一樣撼泛,通過內(nèi)外端口映射來通信了挠说,這樣就避免了端口沖突的問題。

特殊的情況下(比如運維做網(wǎng)絡(luò)檢測或者程序調(diào)試)愿题,可以在pod所在的宿主機(jī)想向pod的ip+端口發(fā)起請求损俭,這些請求會轉(zhuǎn)發(fā)到pod的端口,但是pod本身它自己是不知道端口的存在的潘酗。

因此杆兵,k8s的網(wǎng)絡(luò)遵循以下原則:

  • 一個節(jié)點的pod和其他節(jié)點的pod通信不需要通過做網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT)
  • 一個節(jié)點上所有的agent控制程序(如deamon和kubelet)可以和這個節(jié)點上的pod通信
  • 節(jié)點主機(jī)網(wǎng)絡(luò)中的Pod可以與其他所有節(jié)點上的所有Pod通信,而無需NAT

把上面這個pod替換成容器也是成立的仔夺,因為pod里面的容器和pod共享網(wǎng)絡(luò)琐脏。

基本上的原則就是,k8s的里面的pod可以自由的和集群里面的任何其他pod通信(即使他們是部署在不同的宿主機(jī))缸兔,而且pod直接的通信是直接使用pod自己的ip來通信日裙,他們不知道宿主機(jī)的ip,所以惰蜜,對于pod之間來說昂拂,宿主機(jī)的網(wǎng)絡(luò)信息是透明的,好像不存在一樣抛猖。

然后格侯,定了這幾個原則之后,具體的實現(xiàn)k8s的這個網(wǎng)絡(luò)模型有好多種實現(xiàn)财著,我們這里介紹的是Flannel联四,是其中最簡單的一種實現(xiàn)。

Flannel實現(xiàn)pod之間的通信瓢宦,是通過一種覆蓋網(wǎng)絡(luò)(overlay network)碎连,把數(shù)據(jù)包封裝在另外一個網(wǎng)絡(luò)來做轉(zhuǎn)發(fā),這個覆蓋網(wǎng)絡(luò)可以給每一個pod分配一個獨立的ip地址驮履,使他們看起來都是一臺具有獨立ip的物理主機(jī)一樣鱼辙。

下面這個就是k8s用覆蓋網(wǎng)絡(luò)來實現(xiàn)的一個例子:

flannel覆蓋網(wǎng)絡(luò)

可以看到有3個node廉嚼,在多個node上建立一個覆蓋網(wǎng)絡(luò),子網(wǎng)網(wǎng)段是100.95.0.0/16,然后倒戏,最終到容器級別怠噪,每個容器在這個網(wǎng)段里面獲取到一個獨立的ip。而宿主機(jī)所在的局域網(wǎng)絡(luò)的網(wǎng)段是172.20.32.0/19

看這兩個網(wǎng)段杜跷,就知道傍念,fannel給這個集群創(chuàng)建了一個更大的網(wǎng)絡(luò)給pod使用,可以容納的主機(jī)數(shù)量達(dá)到65535(2^16)個葛闷。

對于每個宿主機(jī)憋槐,fannel給每個了一個小一點的網(wǎng)絡(luò)100.96.x.0/24,提供給每個這個宿主機(jī)的每一個pod使用淑趾,也就是說阳仔,每一個宿主機(jī)可以有256(2^8)個pod。docker默認(rèn)的網(wǎng)橋docker0用的就是這個網(wǎng)絡(luò)扣泊,也就是所有的docker通過docker0來使用這個網(wǎng)絡(luò)近范。即使說,對于容器來說延蟹,都是通過docker0這個橋來通信评矩,和我們平常單機(jī)的容器是一樣的(如果你不給創(chuàng)建的容器指定網(wǎng)絡(luò)的話,默認(rèn)用的是docker0阱飘,參考我以前寫的關(guān)于docker bridge的文章)

那么斥杜,對于同一個host里面的容器通信,我們上面說了是通過這個臺宿主機(jī)的里面的docker0這個網(wǎng)橋來通信俯萌。那對于跨宿主機(jī)果录,也即是兩個宿主機(jī)之間的容器是怎么通信的呢?fannel使用了宿主機(jī)操作系統(tǒng)的kernel route和UDP(這是其中一種實現(xiàn))包封裝來完成咐熙。下圖演示了這個通信過程:

fannel網(wǎng)絡(luò)中跨宿主機(jī)的容器通信

如圖所示弱恒,100.96.1.2(container-1) 要和100.96.2.3(container-2)通信,兩個容器分別處于不同的宿主機(jī)棋恼。
假設(shè)有一個包是從100.96.1.2發(fā)出去給100.96.2.3返弹,它會先經(jīng)過docker0,因為docker0這個橋是所有容器的網(wǎng)關(guān)爪飘。 然后這個包會經(jīng)過route table處理义起,轉(zhuǎn)發(fā)出去到局域網(wǎng)172.20.32.0/19. 而這個route table的對應(yīng)處理這類包的規(guī)則又是從哪里來的呢?它們是由fannel的一個守護(hù)程序flanneld創(chuàng)建的师崎。

每一臺宿主機(jī)都會跑一個flannel的deamon的進(jìn)程默终,這個進(jìn)程的程序會往宿主機(jī)的route table里面寫入特定的路由規(guī)則,這個規(guī)則大概是這樣的。

Node1的route table

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

圖例的數(shù)據(jù)包發(fā)出去的目標(biāo)地址是100.96.2.3,它屬于網(wǎng)段100.96.0.0/16,這個目標(biāo)地址命中第二條規(guī)則齐蔽,也就是這個包會發(fā)到flannel0這個設(shè)備(dev)两疚,這flannel0是一個TUN設(shè)備。是在內(nèi)核里面的一個虛擬網(wǎng)絡(luò)設(shè)備(虛擬網(wǎng)卡)含滴。

在內(nèi)核(kernel)里面诱渤,有兩種虛擬網(wǎng)卡設(shè)備,分別是TUN和TAP,其中TAP處理的是第二層(數(shù)據(jù)鏈路層)的幀谈况,而TUN處理的是第三層(網(wǎng)絡(luò)層)的ip包勺美。

應(yīng)用程序可以綁定到TUN和TAP設(shè)備,內(nèi)核會把數(shù)據(jù)通過TUN或者TAP設(shè)備發(fā)送給這些程序碑韵,反過來赡茸,應(yīng)用程序也可以通過TUN和TAP向內(nèi)核寫入數(shù)據(jù),進(jìn)而由內(nèi)核的路由處理這些發(fā)出去的數(shù)據(jù)包泼诱。

那么上面這個flannel0就是一個這樣的TUN設(shè)備坛掠。這個設(shè)備連到的是一個flannel的守護(hù)進(jìn)程程序flanneld

而這個flanneld是干嘛的呢?它可以接受所有發(fā)往flannel0這個設(shè)備的數(shù)據(jù)包治筒,然后做數(shù)據(jù)封裝處理,它的封裝的邏輯也很簡單舷蒲,就是根據(jù)目標(biāo)地址耸袜,找到這個這地址對應(yīng)的在整個flannel網(wǎng)絡(luò)里面對應(yīng)物理ip和端口(這里是Node2對應(yīng)的物理ip),然后增加一個包頭牲平,增加的包頭里面目標(biāo)地址為這個實際的物理ip和端口(當(dāng)然源地址也改成了局域網(wǎng)絡(luò)的ip)堤框,將原來的數(shù)據(jù)包嵌入在新的數(shù)據(jù)包中,然后再把這個封裝后的包扔回去給內(nèi)核纵柿,內(nèi)核根據(jù)目標(biāo)地址去路由規(guī)則匹配規(guī)則蜈抓,發(fā)現(xiàn)目標(biāo)地址ip是172.20.54.98,端口是8285. 根據(jù)ip匹配不到任何特定的規(guī)則,就用第一條default(默認(rèn))的規(guī)則昂儒,通過eth0這個物理網(wǎng)卡沟使,把數(shù)據(jù)包發(fā)給局域網(wǎng)(這里是UDP廣播出去)

當(dāng)Node2的收到這個包后,然后根據(jù)端口8285發(fā)現(xiàn)他的目標(biāo)地址原來是發(fā)給flanneld的渊跋,然后就直接交給flanneld這程序腊嗡,flanneld收到包后,把包頭去掉拾酝,發(fā)現(xiàn)原來目標(biāo)地址是100.96.2.3燕少,然后就交換flannel0,flannel0把這個解開后的原包交給內(nèi)核蒿囤,內(nèi)核發(fā)現(xiàn)它的目標(biāo)地址是100.96.2.3客们,應(yīng)該交給docker0來處理。(圖例里面畫的是直接由flannel0交給docker0,沒有圖示出內(nèi)核底挫,實際上flannel0是一個TUN設(shè)備恒傻,是跑在內(nèi)核的,數(shù)據(jù)經(jīng)過它后可以交給內(nèi)核凄敢,由內(nèi)核根據(jù)路由決定進(jìn)一步怎么forward)

以上就是這個通信的過程碌冶,那么這里有一個問題: flanneld是怎么知道100.96.2.3對應(yīng)的目標(biāo)地址是172.20.54.98:8285的呢?

這是因為flanneld維護(hù)了一個映射關(guān)系涝缝,它沒創(chuàng)造一個虛擬的容器ip(分配給容器新ip的時候)扑庞,它就知道這個容器的ip實際上是在哪臺宿主機(jī)上,然后把這個映射關(guān)系存儲起來拒逮,在k8s里面flanneld存儲的這個映射關(guān)系放在etd上罐氨,這就是為什么flanneld為什么知道這個怎么去封裝這些包了,下面就是etcd里面的數(shù)據(jù)的:

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"}

看上面這個數(shù)據(jù)滩援,etcd里面存儲的100.96.2.0-24這個網(wǎng)段的容器是放在172.20.54.98這臺宿主機(jī)上的栅隐。

那么還有一個問題,端口8285又是怎么知道的?

這個很簡單玩徊,flanneld的默認(rèn)監(jiān)聽的端口就是這個8285端口租悄,flanneld啟動的時候,就監(jiān)聽了UDP端口8285. 所以發(fā)給Node2:8285的所有UDP數(shù)據(jù)包會恩袱,flanneld這個進(jìn)程會直接處理泣棋,如何去掉包頭就還原出來原來的包了,還原后交給TUN設(shè)備flannel0,由flannel0交給內(nèi)核畔塔,內(nèi)核根據(jù)Node2的路由規(guī)則交給docker0(Node2的路由規(guī)則和node1是基本上一樣的潭辈,除了第三位的網(wǎng)段標(biāo)識不一樣,一個是100.96.1一個是100.92.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

看Node2的這個規(guī)則澈吨,flannld去掉包頭解出來的原包的目標(biāo)ip是100.96.2.3,由flannel0交回去給kennel把敢,kennel發(fā)現(xiàn)命中第三條規(guī)則,所以會把這個包叫給docker0,繼而就進(jìn)入了docker0這個橋的子網(wǎng)了谅辣,接下去就是docker的事情了修赞,參考以前寫的文章

最后一個問題屈藐,怎么配置docker去使用100.96.x.0/24這個子網(wǎng)呢榔组,如果是手工創(chuàng)建容器的話,這個也是非常簡單的联逻,參考以前寫的關(guān)于docker bridge的這篇文章搓扯,但是在k8s里面,是通過配置來實現(xiàn)的:

flanneld會把子網(wǎng)信息寫到一個配置文件/run/flannel/subnet.env

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會使用這個配置的環(huán)境變了來作為它的bridge的配置

dockerd --bip=$FLANNEL_SUBNET --mtu=$FLANNEL_MTU

以上包归,就是k8s如何使用flannel網(wǎng)絡(luò)來跨機(jī)器通信的原理锨推,總體來講,由于flanneld這個守護(hù)神干了所有的臟活累活(其實已經(jīng)是k8s的網(wǎng)絡(luò)實現(xiàn)里面最簡單的一種了),使得pod和容器能夠連接另外一個pod或者容器變得非常簡單换可,就像連一個大局域網(wǎng)里面任意以太主機(jī)一樣椎椰,他們只需要知道對方的虛擬ip就可以直接通信了,不需要做
NAT等復(fù)雜的規(guī)則處理沾鳄。

那么性能怎么樣慨飘?

新版本的flannel不推薦在生產(chǎn)環(huán)境使用UDP的包封裝這種實現(xiàn)。只用它來做測試和調(diào)試用译荞,因為它的性能表現(xiàn)和其他的實現(xiàn)比差一些瓤的。

flannel0 利用的TUN設(shè)備做包封裝原理

看上面這個圖解,一個upd包需要來回在用戶空間(user space)和內(nèi)核空間(kennel space)復(fù)制3次吞歼,這會大大增加網(wǎng)絡(luò)開銷圈膏。

官方的文檔里面可以看到其他的包轉(zhuǎn)發(fā)實現(xiàn)方式,可以進(jìn)一步閱讀,其中host-gw的性能比較好篙骡,它是在第二層去做數(shù)據(jù)包處理稽坤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市糯俗,隨后出現(xiàn)的幾起案子尿褪,更是在濱河造成了極大的恐慌,老刑警劉巖得湘,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茫多,死亡現(xiàn)場離奇詭異,居然都是意外死亡忽刽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門夺欲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跪帝,“玉大人,你說我怎么就攤上這事些阅∩〗#” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵市埋,是天一觀的道長黎泣。 經(jīng)常有香客問我,道長缤谎,這世上最難降的妖魔是什么抒倚? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮坷澡,結(jié)果婚禮上托呕,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好项郊,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布馅扣。 她就那樣靜靜地躺著,像睡著了一般着降。 火紅的嫁衣襯著肌膚如雪差油。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天任洞,我揣著相機(jī)與錄音蓄喇,去河邊找鬼。 笑死侈咕,一個胖子當(dāng)著我的面吹牛公罕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耀销,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼楼眷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了熊尉?” 一聲冷哼從身側(cè)響起罐柳,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎狰住,沒想到半個月后张吉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡催植,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年肮蛹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片创南。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡伦忠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出稿辙,到底是詐尸還是另有隱情昆码,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布邻储,位于F島的核電站赋咽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吨娜。R本人自食惡果不足惜脓匿,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望萌壳。 院中可真熱鬧亦镶,春花似錦日月、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绊起,卻和暖如春精拟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背虱歪。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工蜂绎, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人笋鄙。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓师枣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親萧落。 傳聞我的和親對象是個殘疾皇子践美,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容