理解linux虛擬網路設備bridge

前言

 

上一節我們介紹了Linux veth設備,了解了如何把多個獨立網路命名空間(下面開始簡稱NS)與主機互通,並且多個NS間也能相互通訊,在這一節我們將介紹另一種方式,用linux bridge。

 

linux bridge

 

Linux bridge即linux虛擬網橋,工作方式類似於物理的網路交換機,工作在二層時,能夠轉發乙太網報文,能夠學習MAC地址與埠的映射關係,下面通過一些示例來了解一下。我們將通過linux bridge連接兩個NS,通過下面的命令可以創建一個linux bridge並啟動:

 

1.jpg

 

接下來我們創建兩個新的NS和兩對linux veth網卡:

 

2.jpg

 

接下來就是把主機這邊的兩個端都插到bridge上:

 

3.jpg

 

就這樣兩個NS就可以相互PING通了,因為是相同網段,所以暫不需要默認網關,又因為linux bridge會廣播ARP請求,NS1的協議棧能通過ARP廣播拿到NS2中網卡的MAC地址。

但是此時在主機上ping兩個ns反而是ping不通的,因為主機不知道怎麼去192.168.10.0/24網段,所以先給主機加條路由:

 

4.jpg

 

注意主機的這條路由針對的是整個網段192.168.10.0/24,就是說後面如果繼續加新的NS,只要IP還在這個段內,就不用再增加主機路由了。

來看一下現狀:

 

5.jpg

 

主機加了路由後,從主機ping ns1還是不行,應該是ns1缺默認網關,所以不知道怎麼回這個包,看一下當前NS1中的路由資訊:

 

6.jpg

 

這條路由是我們在給veth0設置ip的時候由系統自動生成的。

 

我們給ns1和ns2都加個默認路由,然後打開br0的arp代答:

 

7.jpg

 

這時候應該就ping得通了。

 

為什麼給ns1和ns2設置的默認網關是169.2.2.2?這個在上一章有解釋過了,想了解的話請看回上一章的內容

 

區別

 

到目前為止我們介紹了兩種在同個主機連接多個ns的方法,現在來介紹一下兩種方法異同點:如果只是用veth連接,就是單純地把主機當成路由器,兩個ns之間的通訊數據包都是要走主機協議棧的三層轉發流程的,如圖1所示:

 

8.jpg

 

而用bridge的方式,則在二層直接把數據包就從ns1轉到了ns2,沒有再走主機協議棧的三層,如圖2所示:

 

9.jpg

 

這個我們可以用如下方式求證,用bridge的情況下,關掉主機的路由轉發功能:

 

10.jpg

 

然後你會發現ns1中ping ns2其實還是可以ping通的。

 

那這樣一來,主機的防火牆策略豈不是沒用了?k8s的網路策略就是在主機的iptables規則中來控制的,為了讓這個規則生效,還是有辦法的,可以讓經過linux bridge的數據包也過一遍iptabls規則:

 

11.jpg

 

開啟了這個參數,數據包還是沒有經過主機的協議棧的三層處理,只是linux bridge的__br_forward方法中顯式地調用了NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD,net, NULL, skb, indev, skb->dev,br_forward_finish)
程式碼在:/net/bridge/br_forward.c

這時候在主機的iptables防火牆裡增加一個過濾規則,把數據包全攔截掉:

 

12.jpg

 

然後ns1就ping不通ns2了。

 

總結

前面介紹的linux veth和linux bridge主要是用於完成同主機容器的相互通訊,下一章我們來介紹一下如何配置跨主機的容器通訊。

 

linux bridge 不能跨網路命名空間,所以不要嘗試把br0轉到ns1中,下面的命令會報錯
ip link set br0 netns ns1
RTNETLINK answers: Invalid argument
凡是netns-local為on的設備都不能跨網路命名空間,像loopback/vxlan/bridge,用下面的命名可以查看eth0的netns-local的值
ethtool -k eth0|grep netns-local

作者:劉海峰,IT行業資深碼農,從事.net/Java/go語言開發十餘年,長期關注springcloud/k8s/linux網路相關的技術。

 

了解更多詳情請登錄://www.deepexi.com/