kubernetes的網絡策略(kube-proxy)流程探究

關于路由

很多像我這樣的網絡小白,對于整個路由過程比較模糊。下面以一個簡單的PING示例解釋一下路由的整個過程。

有兩個原則需要記住:

二層網絡是通過MAC地址進行交換

三層路由通過IP選路。

一個ICMP的以太網格式報文:

|目的MAC|源MAC|目的IP|源IP|ICMP包|

主機A發送一個ICMP包到主機B, 此時目的IP為10.10.0.2,源IP為192.168.0.2。 主機A發現,這個IP和我不在一個網段,那就需要進行IP選路了。此時它就只能把包發往直接的網關了(192.168.0.1) ,主機A和網關在同一個網段,通過MAC地址進行交換,所以目的MAC就是MACRA, 源Mac就是MACHOSTA。

因此從主機A發出的一個以太網報文格式為:

|MACRA|MACHOSTA|10.10.0.2|192.168.0.2|ICMP包

路由器在接口A處收到以太網包進行分析,選出目的IP,根據自身的路由表發現,這個數據包要經過接口B發出啊。于是就在路由器接口B封裝數據包

|MACHOSTB|MACRB|10.10.0.2|192.168.0.2|ICMP包

主機B在二層收到從路由器接口B發生的以太網進行解析發現目的IP是自己的,然后開始回復。首先發現目的IP是192.168.0.2.這貨和我不是一個網段的啊,那我就把數據包先發給網關,讓網關幫我郵遞。于是封裝出下面的以太網包:

|MACRB|MACHOSTB|192.168.0.2|10.10.0.2|ICMP

路由器從接口B收到數據包之后,同樣進行分析之后知道自己需要通過接口A發出。于是封裝的以太網包:

|MACHOSA|MACRA|192.168.0.2|10.10.0.2|ICMP

終于回復的數據包被主機A收到,整個ICMP過程完成。

有一個非常重要的原則要記住:在數據跳轉的過程中,改變的是MAC,IP是始終是沒有改變的。

關于NAT

NAT是網絡地址轉換的意思,什么時候會用到它呢, 一個簡單的例子就是我們平時上網用到路由器,

上圖是我們家里常用的路由器連接示例,HOSTA和HOSTB連接到路由器的LAN口,當主機A訪問8.8.8.8時,根據上面講的路由過程,我們知道到達路由器的以太網包為:

|MACRA|HOSTA|8.8.8.8|192.168.1.2|ICMP包

此時路由器通過WAN口將報文發送到公網上去,按這常理它的數據包格式應該是:

|下一跳路由MAC|路由器A的WAN口的MAC|8.8.8.8|192.168.1.2|ICMP包

我們在深入思考一下,假設這樣的一個數據包發送到公網上之后,確定還能按原路找回來嗎? 大家的路由器網關都是192.168.1.1 ,數據如果回來之后根本就不知道發送到哪一個路由器了。

這個時候就出現了NAT的技術,如果想讓回復的數據包能夠返回,那么我就需要更改源IP地址啊,于是路由器在從WAN口路由出去之后更改源IP為WAN口的IP,同時記錄NAT轉換的信息,保證回復的數據能夠投遞到指定的目標。這種技術叫做SNAT。同理還有一個叫做DNAT,也就是更改目的地址IP。 后邊會在介紹k8s路由過程中解釋。 只需要記住SNAT是路由之后進行的,DNAT是路由之前進行的即可。

Iptables原理

在介紹k8s的網絡之前,還需要介紹一下iptables的原理,因為k8s中用到了大量iptables的知識,iptables博大精深,本人也只是略懂一二。

Iptables是Linux內核模塊netfilter的應用程序,通過iptables這個應用程序來控制netfilter內核的行為。Linux的iptables默認是4表5鏈,當然也可以自定義自己的規則鏈。

4表: nat, manage, raw, filter,

5鏈: prerouting, input, output, forward, postrouting

一般情況下我們只需要關心nat和filter這個兩個表。Nat表可以控制非本地的網絡包,filter可以控制路由到本地的數據包。

不廢話,先上圖:(所有圖均是自己繪制的,心疼自己幾十秒)

上圖表示了一個數據包在Linux的netfilter內核模塊中流轉的流程。可以說Linux的強大的網絡功能讓我非常震驚。驚呆了。

K8s的網絡流程

終于,終于到正題了,大家看看就行了,吾生也有涯,而知也無涯。以有涯隨無涯,怠矣。

當你使用kubernets的時候,可能會感到奇怪,為何我訪問的集群的任意一個IP均可以訪問到指定的應用。 為何在集群的機器上訪問一個不存在的IP(clusterIP)卻能夠幫我路由到指定的pod,而且還是等概率的訪問一個節點。

上面是一張k8s的架構圖(這張不是我畫的),我們只看proxy部分,kube-proxy是k8s的一個核心組件。每臺機器上都運行一個kube-proxy服務,它監聽API server中service和endpoint的變化情況,并通過iptables等來為服務配置負載均衡。 所以接下來我們通過例子結合iptable表中的規則來梳理整個流程。

環境:

master01: 172.24.6.153

master02: 172.24.6.154

master03: 172.24.6.145

我們以kdcos-keystone這個應用為例來分析訪問流程。

從圖中可以看出, kdcos-keystone的clusterIP為10.0.0.10, 容器端口是8080, 集群端口是30808.

Keystonde的pod分布:

master01的路由表:

現在我們先不看iptable的規則,自己去考慮一下,如果我想在master01 上訪問10.0.0.80(隨便找一個不沖突的IP都行) 最終能夠訪問到master02上的keystone(10.254.59.219)應該怎么做呢?

1. 首先可以確定的是肯定是在iptable的nat表上進行添加規則。

2. 我們在集群內部訪問的clusterIP是一個虛擬IP,最終要訪問的IP是10.254.59.219. 所有肯定是要進行DNAT轉換的。(這樣數據包應該是從本地協議發出 會經過nat的OUTPUT和POSTROUTING鏈。看上圖的iptable流程圖即可明白)

3. 我們通過在集群外部訪問nodeport,最終如果要訪問到10.254.59.219,需要進行DNAT轉換,這個和第二步一樣,另外,在上面講解NAT的時候說到,如果要想讓消息能返回客戶端,那就需要進行SNAT轉換。如果實在覺得理解困難,可以把master01當做一個路由器,客戶端就是一個主機。

# 在集群中訪問虛擬IP最終訪問到keystone

iptables -t nat -I OUTPUT -p tcp -m

comment --comment "this is clusterip demo" -d 10.0.0.80/32 --dport 8080 -j DNAT --to-destination 10.254.59.219:8080

# 讓外部客戶端訪問nodeport最終訪問到keystone

iptables -t nat -I POSTROUTING -p tcp -d

10.254.59.219 --dport 8080 -j MASQUERADE

iptables -t nat -I PREROUTING -p tcp -m

comment --comment "this is nodeport demo" --dport 40808 -j DNAT --to-destination 10.254.59.219:8080

這個時候 在集群的master01上訪問10.0.0.80:8080 或者在外部訪問172.24.6.153:408080,就會發現驚訝的發現原來k8s還能這樣操作。是不是很驚喜。無圖無真相:

下圖是在master01上訪問10.0.0.80:8080 時設置的iptable規則。

下圖是讓外部能夠通過nodeport訪問keystone設置的規則。

在自己的電腦上訪問nodeport:

留個問題:

上面的iptable規則可以保證在master01上通過虛擬ip(10.0.0.80)訪問到keystone,可以保證在外部訪問172.24.6.153:8080訪問到keystone,但是如果你嘗試在master01(172.24.6.153)上通過訪問172.24.6.153:40808到達keystone確是不行的。 不信?我截圖給你看?

那你覺得應該如何設置才能在master01上通過自身IP也能訪問到keystone呢?

另:

MASQUERADE和SNAT的功能類似,只是SNAT需要明確指明源IP的的值,MASQUERADE會根據網卡IP自動更改,所以更實用一些。

所以說,如果在開發過程中,想外部訪問某個應用(比如redis),但是呢碰巧這個應用的svc又沒有開啟nodeport,那你就可以模仿我剛才設置的iptable規則,從而達到不修改SVC也能通過外部應用訪問。

到這里,也許你大概明白了k8s的kube-proxy的工作原理了,總結起來就是通過更改iptable的規則讓我們可以訪問一個虛擬IP從而能夠到達后端pod。如果看到這里還不是很了解的話,建議還是從頭再看一下,因為下面分析的k8s生成的iptable鏈要比這個會更復雜一下。

現在我們分析k8s的iptable的流程:

分析1: 集群內部通過clusterIP訪問到pod。

上面我們分析過,首先這個數據包是通過本地協議發出的,然后需要更改NAT表,那看來k8s只能在OUTPUT這個鏈上來動手了。

看下圖:

到達OUTPUT鏈的包要過KUBE-SERVICES這個k8s自定義的鏈

上圖就是KUBE-SERVICES 鏈,訪問10.0.0.10:8080 可以匹配到上圖的第一條紅線的規則,注意第二條紅線,下面會說到。

匹配到10.0.0.10:8080的時候會跳轉到KUBE-SVC-VZEERQ5BHBSZ5PRL這個鏈,那這個鏈又做了啥子呢?

看到上圖的--mode random --probability 0.33332999982 了嗎?它就是訪問SVC時能夠隨機訪問到后端POD的原因。

因為我們后面有三個pod,所以會有三條鏈, 我們只分析其中一條。

最終這個鏈做了兩件事,跳轉到KUBE-MARK-MASQ,我就不跳了,直接說結果就是給這個包打上標簽,這個標簽的用處,一會說。

然后我們終于看到了對這個包進行了一次DNAT轉換。 轉到了10.254.59.212:8080上面了。

這個OUTPUT走完之后,它就該到POSTROUTING鏈了。

跳轉到KUBE-POSTROUTING鏈,這個鏈只做了一個事,就是對打上了標簽的包進行SNAT轉換。這就引入了一個問題,在一個pod訪問一個clusterIP的時候,如果這個clusterIP的DNAT目標是自己的話,看到的IP卻是自己宿主機的IP。還有一點大家可能會有疑問,這個--mark 0x4000/0x4000是什么鬼,就是對匹配這個標簽的數據包進行SNAT,上面說到的KUBE-MARK-MASQ就是給數據包打上了這樣的一個標簽。

這樣一個訪問clusterIP最終訪問到pod的流程就算走完了。

分析2: 下面我們來分析通過外部nodeport訪問后端pod的流程。

根據iptable的流程我們知道,首先我們應該對nat表的PREROUTING鏈動手腳。看看k8s做了啥?

對,你沒看錯,這貨又把它跳到了KUBE-SERVICES這個鏈上去了,但是上面我們知道,這回我是通過nodeport訪問的,你根本匹配不上啊,不錯確實匹配不上,還記得我說的第二根紅線嗎?忘了?在貼下上面的圖。

那既然你們匹配不上那就給我跳轉到KUBE-NODEPORTS鏈上來。

在這個KUBE-NODEPORTS最后還是調到之前的KUBE-SVC-VZEERQ5BHBSZ5PRL上,打上標簽,DNAT轉換,SNAT轉換。完成。

另外:

在最開始我提到了一個問題,在集群上使用nodeport卻訪問不了后端pod, 那是因為我們沒有在OUTPUT鏈設置匹配nodeport的包進行DNAT轉換呀,那k8s做了嗎? 當然了,反正不管你是PREROUTING還是OUTPUT鏈,我都給你跳到KUBE-SERVICE, 到了KUBE-SERVICE匹配不上我就給你跳到KUBE-NODEPORTS,這就解決了不管是那種情況,無論是訪問clusterIP,還是nodeport最終都能訪問到了后端pod

總之: Linux的網絡功能復雜且強大,且學且珍惜!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • 防火墻的概念iptables的簡介iptables命令網絡防火墻NATfirewalld服務 一、防火墻的概念 (...
    哈嘍別樣閱讀 1,838評論 0 1
  • Teredo 原理概述 http://www.ipv6bbs.cn/thread-144-1-1.html (出處...
    我是葉問小盆友閱讀 2,030評論 0 1
  • ----寫于2014.5.07 今天preK沒課。所有學生到體育館欣賞小學和初中的樂隊表演。表演前,樂隊老...
    素秋微菊閱讀 429評論 0 1
  • 《一個人的朝圣---奎尼的情歌》,看到這個名字的時候就知道應該是個愛情故事。事實也是如此。奎尼愛著哈羅德。讀完第一...
    披著羽毛的豬閱讀 440評論 5 2
  • 一個人 一張票 不要問我去哪兒 到站了 我沒有下車 只想這樣一直走 我沒有遇見上車的人 也沒有遇見下車的人 心涌沒...
    為靑?閱讀 148評論 0 0