理解linux虛擬網路設備veth

前言

 

前面介紹了linux network namespace,接著介紹一下如何讓一個獨立的網路命名空間和主機的網路互通,這裡我們需要用到linux虛擬網路設備veth。

 

veth設備

 

veth是linux的一種虛擬網路設備,它有點類似於兩張網卡中間用一條網線連著,veth設備總是成對出現,通常用來連接不同網路命名空間(下面開始簡稱NS),一端連著NS1的內核協議棧,另一端連著NS2的內核協議棧,一端發送的數據會立刻被另一端接收。

1.jpg

接下來我們通過一些示例來理解veth設備,我們創建一個新的NS,然後跟主機的NS連接起來通過下面的命令可以創建一對veth設備:

 

2.jpg

然後創建一個名為ns1的network namespace :

 

3.jpg

然後把剛創建的veth1網卡的其中一端轉到ns1,這就好像一端插到ns1上,另一端插在主機的ns上:

 

4.jpg

給veth的兩端都配置個IP,設置veth0時,要用ip netns exec ns1,因為veth0此時在ns1中:

 

5.jpg

此時的狀態如下:

 

6.jpg

這時候主機和ns1已經可以相互ping通了:

 

7.jpg

如果我們進到ns1中發現ping localhost不通的話,有可能只是因為lo網卡沒有啟動起來

 

8.jpg

如果我們進到ns1中發現ping localhost不通的話,有可能只是因為lo網卡沒有啟動起來

 

9.jpg

這條路由指示以後凡是往192.168.10.0/24這個網段的地址都給veth1,這顯然不是我們想要的結果,因為其它的ns並沒有連在veth1上。在k8s的節點上,相同主機的pod通常會在同一個子網段里,前面那條路由就相當於把這個主機的全部pod的通訊都引到了veth1上,這就有問題了。其實,我們是可以不在veth1上配置IP的,上面的示例只是為了讓大家可以對veth連接的效果有個認識,因為veth1連的是主機的內核協議棧,主機上已經有很多個IP了,只是因為當前ns1中沒有默認路由,去主機的IP的話是不通的(當然如果你的主機的網段本來就是192.168.10.0/24網段,那又是能通的),所以如果不配置veth1端的IP的話,只要加上默認路由就可以了,下面我們演示一個更實用的場景。

 

另一種方法

 

直接上命令,跟上面的差不多,也是建一對veth網卡,一端轉到新的ns上,在這就不一句句解釋了:

 

10.jpg

打開主機這一端veth3的arp代答:

 

11.jpg

給ns2加上默認路由:

 

12.jpg

在主機上添加去往ns2路由:

 

13.jpg

為什麼ns2的默認路由是個這麼奇怪的IP?後面會解釋。

此時整個狀態如下圖:

 

14.jpg

這時候ping一下ns2,發現通了:

 

15.jpg

那ns1和ns2能不能相互ping通呢?行的,不過要先打開veth1的arp代答,並給ns1配個默認網關

 

16.jpg

如無意外,在ns1上ping ns2應該是通了,記得要打開主機的路由轉發功能:

簡單解釋一下為什麼給ns2設置的默認網關是169.2.2.2,其實默認網關的IP在整個通訊的過程中都不會用到,想一下數據包發送流程,當ns2的要發一個包去主機時,封完IP頭後,到了鏈路層,協議棧的路由判決已經決定了下一跳為默認網關,這時候鄰居子系統會從ns1的鄰居表(也就是ARP表)查找下一跳IP的MAC地址,找不到就會發送ARP請求,這時候ARP請求到了對端veth3,因為veth3開啟了arp代答,所以會直接把自己的MAC地址返回去,這樣ns2的鄰居子系統會以為自己得到了網關的MAC地址,於是完成MAC頭的封裝,把數據包發送到veth1,所以其實在這裡的默認網關的IP可以隨便寫一個非當前網段的地址。

 

總結

 

上面介紹了在主機與容器相互連接的兩種方法,還有第三種方法就是用linux bridge,下一章介紹linux bridge。

 

歡迎關注滴普科技官網 //datasink-sensors.deepexi.top/t/Ha

 

作者:劉海峰,IT行業資深碼農,

從事.net/Java/go語言開發十餘年,

長期關注springcloud/k8s/linux網路相關的技術,

現為滴普科技容器產品首席架構師。

Tags: