偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

特洛伊木馬-圖解VXLAN容器網(wǎng)絡通信方案

云計算 云原生
這篇文章我主要通過下面這張全景圖來講述K8s是如何利用VXLAN來實現(xiàn)K8s的容器通信方案的。

一篇文章圍繞一張圖,講述一個主題。不過這個主題偏大,我估計需要好幾篇文章才能說得清楚。

云原生的代表技術(shù)包括容器、服務網(wǎng)格、微服務、不可變基礎設施和聲明式API。其中K8s是不可變基礎設施的壓艙石。典型的K8s集群由數(shù)十個Node, 成百個Pod,上千個Container組成。相互隔離的容器間需要協(xié)作才能完成更大規(guī)模的應用。而協(xié)作就需要網(wǎng)絡通信。

這篇文章我主要通過下面這張全景圖來講述K8s是如何利用VXLAN來實現(xiàn)K8s的容器通信方案的。網(wǎng)絡通信不是量子糾纏,網(wǎng)絡流量是實打?qū)嵉赝ㄟ^了各個虛擬的、實體的網(wǎng)絡設備,途徑每個設備節(jié)點時自然也會受到設備上的路由、iptables等策略控制。

圖:VXLAN容器網(wǎng)絡方案全景圖

K8s的容器通信方案有很多種。譬如flannel實現(xiàn)的host-gw方案、calico基于三層轉(zhuǎn)發(fā)實現(xiàn)的方案以及本文著重講述的flannel.1 VXLAN方案。為什么我要挑flannel.1 VXLAN方案來細聊呢,因為它夠復雜,涉及到了比較多的虛擬網(wǎng)絡設備和組網(wǎng)技術(shù)。

這張圖里面涉及到如下幾種網(wǎng)絡設備,有機會我們單獨拿一篇出來過一下這些設備。

  • eth: 物理網(wǎng)卡在內(nèi)核中的表示。它一端連著網(wǎng)絡棧,另一端通過驅(qū)動連接著物理網(wǎng)卡。
  • veth: virtual eth。它是成對出現(xiàn)的,類似交叉網(wǎng)線連接的一對物理網(wǎng)卡。從網(wǎng)卡一端流出的數(shù)據(jù)會原樣流入另外一端。每個veth都有自己的MAC地址,也可以給它設置IP地址。
  • bridge: bridge的行為類似二層交換機,又翻譯成網(wǎng)橋??梢詫eth,tap等虛擬網(wǎng)絡設備連(插)到它上面。如果數(shù)據(jù)包的目的 MAC 地址為網(wǎng)橋本身,并且網(wǎng)橋設置了 IP 地址的話,那該數(shù)據(jù)包就會被認為是bridge收到了發(fā)往創(chuàng)建網(wǎng)橋那臺主機的數(shù)據(jù)包,這個數(shù)據(jù)包將不會轉(zhuǎn)發(fā)到任何設備,而是直接交給上層(三層)協(xié)議棧去處理。
  • VTEP:VXLAN 網(wǎng)絡的每個邊緣入口上,布置有一個 VTEP(VXLAN Tunnel Endpoints)設備,它既可以是物理設備,也可以是虛擬化設備,主要負責 VXLAN 協(xié)議報文的封包和解包。圖中flannel.1就是一個VTEP設備,它既有IP地址,又有MAC地址。

雖然容器間的網(wǎng)絡方案多種多樣,但所有的容器網(wǎng)絡通信問題,其實都可以歸結(jié)為以下幾種場景。本篇我們專注容器間通信的場景,故略去了其它通信主體與容器通信的情形,比如本地Node里面的進程也會和容器通信。留個彩蛋,以后再聊。

  • 同一個Pod內(nèi)的容器間通信。
  • 同一個Node內(nèi)的容器間通信。
  • 跨Node的容器間通信。

這里需要強調(diào)的一個點是,雖然Pod是K8s編排調(diào)度的基本單位,但是通信的需求卻發(fā)端于Pod里面的容器。

環(huán)境說明

這張圖里面,Node 1 和Node X位于同一個局域網(wǎng)17.168.0.0/24。Node 1的IP地址是17.168.0.2,Node X的IP是17.168.0.3。

K8s集群所使用的子網(wǎng)為10.244.0.0/16。對于網(wǎng)絡17.168.0.0/24和它里面的交換機和路由器來說,K8s集群所使用的子網(wǎng)是無效的網(wǎng)絡,交換機和路由器更是無從轉(zhuǎn)發(fā)、路由任何源IP或目的IP為K8s子網(wǎng)的數(shù)據(jù)包。

非常明顯的矛盾出現(xiàn)了:K8s集群要通過子網(wǎng)為10.244.0.0/16通信,而宿主機環(huán)境卻根本不認識這個子網(wǎng)。我們接下來將看到"特洛伊木馬"的故事在這里再次上演。

我們的目標是在這種矛盾的網(wǎng)絡環(huán)境下,解釋清楚pod a里面的container-1訪問pod b里面的container-1時發(fā)生了哪些事情。圖中藍色的標線展示了數(shù)據(jù)流的方向。

圖中的綠色標線和綠色的框圖表示了與VXLAN相關(guān)的數(shù)據(jù)流和網(wǎng)絡封包示意圖。

出于簡單,Node 1里面只畫出了一個Pod, pod a,所有的Pod都連在了bridge cni0上,子網(wǎng)為10.244.0.1/24。Node X里面只畫了兩個Pod, pod b和pod c ,所有的Pod也一樣都連在了bridge cni0上,子網(wǎng)為10.244.1.1/24。

每個Node上面的bridge都分配有IP地址。Pod a的IP地址是10.244.0.2,Pod b的IP地址是10.244.1.3。

同一個Pod內(nèi)的容器間通信

這是最簡單的情形,內(nèi)核自帶技能,不需額外的組網(wǎng)技術(shù)加持。

需要強調(diào)的一個知識點是Pod內(nèi)部所有的容器是共享同一個網(wǎng)絡棧、routes以及iptables的,因為它們屬于同一個network namespace。

在一個k8s cluster內(nèi)部,每個Pod擁有獨一無二的IP地址,Pod內(nèi)部所有的container共享分配Pod的地址。Pod內(nèi)部的容器共享pod的IP地址,但各個容器的端口不能沖突。

由于Pod調(diào)度的原子性,一個Pod內(nèi)部的所有container只會被調(diào)度到一臺主機上運行。類似本地機器上兩個應用程序通過localhost進行進程間通信一樣,同一個Pod內(nèi)部的容器間可以直接通過localhost來通信。此時的traffic直接通過loopback 網(wǎng)絡設備在兩個容器間流動。圖中的bridge無法感知這樣的traffic,主機上的網(wǎng)絡棧和其它網(wǎng)絡設備更不會感知到。

同一個Node內(nèi)的容器間通信

圖中Node X上畫出了多個Pod。當Pod b里面的container-1想要訪問Pod c里面的container-1時屬于這個場景。

Pod b里面的路由表決定了訪問Pod c的traffic需要從自己的interface eth0出去。

  • src IP:10.244.1.3,dest IP:10.244.1.8。
  • src MAC為Pod b veth MAC,dest MAC為Pod c veth MAC。

從圖中可以看到Pod b和Pod c都是插在了bridge上面。作為一個虛擬的二層交換機,它按照二層交換機的行為交換、轉(zhuǎn)發(fā)數(shù)據(jù)包。

在這種場景下,這兩個container之間的通信行為不會超出bridge的范圍,包括Pod b的container-1通過ARP得知目的container的MAC地址也是在bridge內(nèi)處理。也不會涉及NAT等地址轉(zhuǎn)換操作。

跨Node的容器間通信

這是最常用的通信場景。容器訪問api server即是典型的例子。

下面開始最復雜的步驟,這些步驟發(fā)生在Node 1。Node X收到以太幀后的操作是一個逆過程,這里不做贅述。

我們按照traffic的流向,以它途徑的各個網(wǎng)絡設備(虛擬的、實體的)為分割節(jié)點,分段講述每段發(fā)生了什么。

從container到cni0

從Pod a的路由表可知,以太幀需要從它的NIC eth0離開。因為eth0是veth的其中一端,另外一端插在bridge cni0上面,于是以太幀進入cni0。此以太幀的目的MAC地址為bridge。

  • src IP:10.244.0.2,dest IP:10.244.1.3。
  • src MAC為Pod a veth MAC,dest MAC為cni0 MAC。

從cni0到flannel.1

前面提到該網(wǎng)橋配置有IP地址,現(xiàn)在它收到一個目的MAC地址為自己的數(shù)據(jù)包,于是觸發(fā)了 Linux Bridge 的特殊轉(zhuǎn)發(fā)規(guī)則:網(wǎng)橋不會將這個數(shù)據(jù)包轉(zhuǎn)發(fā)給任何設備,而是直接轉(zhuǎn)交給主機的三層協(xié)議棧處理。

主機協(xié)議棧根據(jù)host的路由表,從而得知需要把IP包交給本機的flannel.1。

從這步以后就是三層路由了,已經(jīng)不在網(wǎng)橋的工作范圍之內(nèi),而是由 Linux 主機依靠 Netfilter 進行 IP 轉(zhuǎn)發(fā)(IP Forward)去實現(xiàn)的。注意這里是IP包轉(zhuǎn)發(fā),接收者收到的是3層的package,因而它不包含二層的數(shù)據(jù)。

flannel.1組裝內(nèi)部數(shù)據(jù)幀

至此,越過千山萬水,本機的flannel.1終于收到了IP包。

從這里開始,flannel.1需要想辦法營造幻象:跨主機營造一個虛擬的網(wǎng)絡10.244.0.0/16,好讓Pod a看起來Pod b和它正處于一個完全合法的、信息交換自由無障礙的環(huán)境。天真的Pod們完全不知這個網(wǎng)絡是一個虛擬的、私有的、宿主機網(wǎng)絡里面的交換機和路由器根本不認識它這樣一個事實。

前面提到flannel.1收到的是 IP 包,既然是IP包,那它就沒有MAC地址,但flannel.1同時又要想辦法把“原始 IP 包”加上一個目的 MAC 地址(當然也需要包含源flannel.1的MAC地址),封裝成一個完整的二層數(shù)據(jù)幀,然后發(fā)送給位于Node X上的flannel.1。

而大家都知道要組裝一個完整的二層數(shù)據(jù)幀,首先需要解決的問題是目標 flannel.1的MAC地址是什么呢?下面的提示給出了答案。

Node X上的flannel.1的 MAC 地址是什么?

我們已經(jīng)知道了Node X上的flannel.1的 IP 地址,它是數(shù)據(jù)包的目的地。要根據(jù)三層 IP 地址查詢對應的二層 MAC 地址,這正是 ARP(Address Resolution Protocol )表的功能。這里要用到的 ARP 記錄,也是 flanneld 進程在 Node 1 節(jié)點啟動時,自動添加在 Node 1 上的。我們可以通過 ip 命令看到它,如下所示:

# 在Node 1
$ ip neigh show dev flannel.1
10.244.1.0 lladdr 5e:f8:4f:00:e3:37 PERMANENT

通過ARP,我們知道了目的 flannel.1的MAC是 5e:f8:4f:00:e3:37。到此時,已經(jīng)完整地產(chǎn)生了內(nèi)部數(shù)據(jù)載荷(Inner payload), 內(nèi)部IP頭(Inner IP Header) 10.244.1.3和內(nèi)部Ethernet頭(Inner Ethernet Header)5e:f8:4f:00:e3:37了。

但是,因為上面提到的這些 VTEP 設備的 MAC 地址,對于宿主機網(wǎng)絡來說并沒有什么實際意義,所以上面封裝出來的這個數(shù)據(jù)幀,并不能在我們的宿主機二層網(wǎng)絡里傳輸。為了方便敘述,我們把它稱為“內(nèi)部數(shù)據(jù)幀”(Inner Ethernet Frame),或者叫"原始二層數(shù)據(jù)幀"(Original Layer 2 Frame)。

封裝好的內(nèi)部數(shù)據(jù)幀如全景圖中藍色的方框所示。

接下來,Linux 內(nèi)核還需要再把“原始二層數(shù)據(jù)幀”進一步封裝成為宿主機網(wǎng)絡里的一個普通的外部數(shù)據(jù)幀,好讓它載著“原始二層數(shù)據(jù)幀”,通過宿主機的 eth0 網(wǎng)卡進行傳輸。

flannel.1組裝VXLAN數(shù)據(jù)幀

如下圖所示,原始二層數(shù)據(jù)幀加上VXLAN頭,我們把它叫做“VXLAN數(shù)據(jù)幀”。在全景圖中,我在藍色的方框上面加了一個灰色的方框,用來表示VXLAN頭。需要特別注意下灰色方框中VNI=1這個部分。VNI(Virtual Network Identifier)長24-bit,在這里flannel.1默認把它設置為1,這樣Node X上面的flannel.1就知道這個數(shù)據(jù)幀是需要它處理的。

  • Flannel 中,VNI 的默認值是 1,這也是宿主機上的 VTEP 設備都叫作 flannel.1 的原因。

有了VXLAN數(shù)據(jù)幀,就可以開始演繹一個和“特洛伊木馬”相同的故事。VXLAN數(shù)據(jù)幀如同希臘戰(zhàn)士,但我們的目的不是攻打特洛伊城,而是把這個VXLAN數(shù)據(jù)幀完整地、神不知鬼不覺地送到城內(nèi)的flannel.1手里。要達到這個目的,我們還需要一個木馬。

圖:VXLAN數(shù)據(jù)幀

從flannel.1發(fā)起UDP連接

好了,“希臘戰(zhàn)士”有了,我們就差一個木馬了。接下來要做的事情是,像把希臘戰(zhàn)士藏到木馬里一樣,Linux 內(nèi)核要把這個VXLAN數(shù)據(jù)幀塞進一個 UDP 包里發(fā)出去。上面的全景圖中,我特意把VXLAN數(shù)據(jù)幀畫得窄了一些,好讓你感覺外圍稍胖的UDP包確實像是個木馬。

Node 1上的flannel.1 設備要扮演一個“網(wǎng)橋”的角色,在二層網(wǎng)絡進行 UDP 包的封包和轉(zhuǎn)發(fā)。在Node 1看來,它會以為自己的 flannel.1 設備只是在向另外一臺宿主機的 flannel.1 設備,發(fā)起了一次普通的 UDP 鏈接,卻全然不知它發(fā)送的是一個木馬(不要緊張,此木馬非木馬病毒)。

但且慢,先回答一個問題:剛才在組裝內(nèi)部數(shù)據(jù)幀的時候,我們知道 flannel.1 設備已經(jīng)知道了目的 flannel.1 設備的 MAC 地址,但這個 UDP 包該發(fā)給哪臺宿主機呢?也就是說,木馬有了,希臘戰(zhàn)士也藏到木馬肚子里了,但特洛伊城在哪里?

是時候輪到一個叫作轉(zhuǎn)發(fā)數(shù)據(jù)庫(FDB, Forwarding Database)上場幫忙了。這個 flannel.1“網(wǎng)橋”對應的 FDB 信息,也是 flanneld 進程負責維護的。它的內(nèi)容可以通過 bridge fdb 命令查看到,如下所示:

# 在Node 1上,使用“目的VTEP設備”的MAC地址進行查詢
$ bridge fdb show flannel.1 | grep 5e:f8:4f:00:e3:37
5e:f8:4f:00:e3:37 dev flannel.1 dst 17.168.0.3 self permanent

在上面這條 FDB 記錄里,指定了這樣一條規(guī)則:發(fā)往我們前面提到的“目的 flannel.1”(MAC 地址是 5e:f8:4f:00:e3:37)的二層數(shù)據(jù)幀,應該通過本機的flannel.1 設備,發(fā)往 IP 地址為 17.168.0.3 的主機。顯然,這臺主機正是 Node X,UDP 包要發(fā)往的目的地就找到了。

得到了目的IP地址,自然也會得知Node X的MAC地址。接下來的流程,就是一個正常的,宿主機網(wǎng)絡上的封包工作,且最終從 Node 1 的 eth0 網(wǎng)卡發(fā)出去了。只不過這個過程發(fā)生在虛擬設備flannel.1上面罷了。

責任編輯:姜華 來源: 二哥聊云原生
相關(guān)推薦

2015-05-07 10:38:58

2010-01-15 21:47:39

2010-01-14 20:49:08

2010-07-06 10:45:25

2012-06-13 09:38:27

2013-10-10 09:24:34

2021-10-13 11:01:54

Android特洛伊木馬SOVA

2013-08-20 09:57:52

2019-09-09 07:03:37

2010-09-13 09:16:16

特洛伊木馬

2019-02-12 05:03:18

2019-09-11 13:23:33

2013-09-03 13:48:10

2009-01-22 09:51:17

2009-02-17 09:58:00

2021-08-27 12:33:00

LemonDuck木馬LemonCat

2014-08-21 11:09:31

2012-02-24 10:07:25

2009-07-27 09:51:48

2016-12-02 10:34:21

點贊
收藏

51CTO技術(shù)棧公眾號