Linux Bridge模擬在docker中的應(yīng)用

什么是Bridge

Bridge是一種虛擬網(wǎng)絡(luò)設(shè)備,所以具備虛擬網(wǎng)絡(luò)設(shè)備的所有特性,比如可以配置 IP、MAC 等。除此之外,Bridge 還是一個(gè)虛擬交換機(jī),具有交換機(jī)所有的功能。

對(duì)于普通的網(wǎng)絡(luò)設(shè)備,就像一個(gè)管道,只有兩端,數(shù)據(jù)從一端進(jìn),從另一端出,如物理網(wǎng)卡從外面網(wǎng)絡(luò)中收到數(shù)據(jù)轉(zhuǎn)發(fā)給內(nèi)核網(wǎng)絡(luò)協(xié)議棧,從網(wǎng)絡(luò)協(xié)議棧過(guò)來(lái)的數(shù)據(jù)轉(zhuǎn)發(fā)到外部網(wǎng)絡(luò)。而 Bridge 有多個(gè)端口,數(shù)據(jù)可以從多個(gè)端口進(jìn),從多個(gè)端口出,原理和交換機(jī)類似。

Bridge 的這個(gè)特性讓它可以接入其他的網(wǎng)絡(luò)設(shè)備,比如物理設(shè)備、虛擬設(shè)備。Bridge 通常充當(dāng)主設(shè)備,其他設(shè)備為從設(shè)備,這樣的效果就等同于物理交換機(jī)的端口連接了一根網(wǎng)線。Bridge是和主機(jī)的網(wǎng)絡(luò)協(xié)議棧相連的,也就是說(shuō)通過(guò)bridge的網(wǎng)絡(luò)數(shù)據(jù),是要經(jīng)過(guò)host主機(jī)的內(nèi)核協(xié)議棧的進(jìn)行處理的(我的理解就是net_filter通過(guò)iptables設(shè)置的rules進(jìn)行處理)

什么是veth-pair

veth-pair 就是一對(duì)的虛擬設(shè)備接口,它都是成對(duì)出現(xiàn)的。一端連著協(xié)議棧,一端彼此相連著

正因?yàn)橛羞@個(gè)特性,它常常充當(dāng)著一個(gè)橋梁,連接著各種虛擬網(wǎng)絡(luò)設(shè)備。例如在docker中,他們連接容器所處網(wǎng)絡(luò)namespace和bridge。

此圖中veth-pair一個(gè)是連接在bridge上的veth,另一個(gè)是連接在容器網(wǎng)絡(luò)namespace上的eth0。veth和eth0彼此相連,veth通過(guò)bridge與host的網(wǎng)絡(luò)協(xié)議棧相連,eth0通過(guò)容器namespace和容器的網(wǎng)絡(luò)協(xié)議棧相連。這里的容器是在host內(nèi)部的容器,不考慮跨節(jié)點(diǎn)的容器。

模擬容器和bridge連接

安裝docker成功后,我們可以看到docker在host機(jī)器上默認(rèn)的創(chuàng)建一個(gè)docker0的bridge,這個(gè)bridge也是容器的默認(rèn)的連接方式。在這里我們將用將創(chuàng)建網(wǎng)絡(luò)namespace來(lái)模擬容器,讓namespace和我們創(chuàng)建好的bridge連接起來(lái),容器之間可以相互訪問(wèn),容器可以和host所在網(wǎng)絡(luò)訪問(wèn)。

首先我們要打開(kāi)host機(jī)器上的ip_forwarding功能,這樣host的物理網(wǎng)卡和bridge之間才能forward數(shù)據(jù)包。IP_FORWARD可以使連接在同一個(gè)網(wǎng)絡(luò)協(xié)議棧上的網(wǎng)絡(luò)接口間進(jìn)行數(shù)據(jù)包的轉(zhuǎn)發(fā),適合host上有多塊物理網(wǎng)卡,虛擬設(shè)備接口,結(jié)合iptables的 forward鏈一起使用。例如主機(jī)網(wǎng)絡(luò)協(xié)議棧上連接了30.0/24這個(gè)物理網(wǎng)卡和88.0/24這個(gè)bridge虛擬設(shè)備,一個(gè)數(shù)據(jù)包從30.0/24這塊網(wǎng)卡進(jìn)入網(wǎng)絡(luò)協(xié)議棧,數(shù)據(jù)包的destination是88.0/24這個(gè)網(wǎng)段上的某一個(gè)IP地址,內(nèi)核協(xié)議棧發(fā)現(xiàn)這個(gè)包是去bridge子網(wǎng)的,于是就會(huì)把這個(gè)數(shù)據(jù)包forward給bridge連在網(wǎng)絡(luò)協(xié)議棧上的端口并進(jìn)行處理。如果forward功能沒(méi)有打開(kāi),數(shù)據(jù)包無(wú)法轉(zhuǎn)發(fā)到bridge,只能在drop掉。

這個(gè)重啟后就失效了,要想永久有效請(qǐng)修改文件/etc/sysctl.conf

創(chuàng)建一個(gè)bridge br0,激活這個(gè)device,并給他分配一個(gè)IP地址及掩碼192.168.88.1/24。

創(chuàng)建一個(gè)網(wǎng)絡(luò)的namespace ns0,然后在這個(gè)網(wǎng)絡(luò)namespace中執(zhí)行bash命令(另外起一個(gè)terminal做這個(gè)事情),如果你還不清楚什么是linux內(nèi)核namespace,請(qǐng)google相關(guān)資料。

執(zhí)行命令后,我這個(gè)terminal已經(jīng)進(jìn)入到ns0這個(gè)namespace了,這和docker容器的網(wǎng)絡(luò)namespace是一致的。通過(guò)ip命令查詢,現(xiàn)在這個(gè)命令空間里面只有一個(gè)loopback的網(wǎng)絡(luò)設(shè)備,沒(méi)有其他網(wǎng)絡(luò)設(shè)備相連。然后通過(guò)命令使loopback設(shè)備active

接下來(lái)我們就要?jiǎng)?chuàng)建veth pair,一邊和這個(gè)ns0連接,一邊和br0連接,并給他們分配IP地址。(這些操作不要在ns0里執(zhí)行bash命令的terminal里面做)

這里創(chuàng)建一個(gè)veth pair,veth0和veth0p,并且把veth0和ns0相連,并分配和br0同一個(gè)網(wǎng)段的IP地址192.168.88.2,啟動(dòng)veth0p這個(gè)設(shè)備。返回到ns0下bash的terminal,可以看到多出一個(gè)網(wǎng)卡信息并分配到IP地址,但是這個(gè)dev是處于LOWERLAYDOWN的狀態(tài),這是由于pair另一端還沒(méi)有接入到br0.

接下來(lái)就是把veth0連接到br0上,并啟動(dòng)這個(gè)設(shè)備。

我們可以看到br0上有一個(gè)veth設(shè)備連接上來(lái),返回去看ns0下的bash,我們可以看到veth0p的狀態(tài)已經(jīng)變成UP。

現(xiàn)在br0的IP是192.168.88.1,ns0的IP地址為192.168.88.2,我們可以在ns0下去ping 192.168.88.1是可以通的,我們可以通過(guò)同樣的步驟在創(chuàng)建另外一個(gè)namespace ns1并分配IP192.168.88.3。ns0,ns1, br0都是可以相互連接的,這里就不重復(fù)創(chuàng)建了。

目前為止連接在bridge上的namespace都是可以相互訪問(wèn),這個(gè)體現(xiàn)了bridge虛擬交換機(jī)的功能。如果我們還需要容器能訪問(wèn)host所在的網(wǎng)絡(luò),我們需要繼續(xù)配置下面步驟。

在ns0下的bash命令行下設(shè)置默認(rèn)路由,不屬于192.168.88.0/24這個(gè)網(wǎng)段的數(shù)據(jù)包全部路由到默認(rèn)網(wǎng)關(guān)br0 192.168.88.1.

由于192.168.88.0/24這個(gè)網(wǎng)段和host所在的網(wǎng)路不是一個(gè)網(wǎng)絡(luò),一切從88.0/24這個(gè)網(wǎng)絡(luò)的數(shù)據(jù)包要訪問(wèn)外部網(wǎng)絡(luò)都是要通過(guò)host的主機(jī)IP去訪問(wèn)的,對(duì)于遠(yuǎn)端服務(wù)連接它是不知道88.0/24這個(gè)網(wǎng)絡(luò)的,他接收的數(shù)據(jù)包的src地址都是host的IP地址,在這里我們需要對(duì)88.0/24這個(gè)網(wǎng)段的數(shù)據(jù)包做SNAT。在host的terminal下通過(guò)iptables的命令設(shè)置。

iptables必須是enable的,并對(duì)NAT table的POSTROUTING chain添加一條規(guī)則,所有src地址為88.0/24這個(gè)網(wǎng)段的數(shù)據(jù)包,全部走h(yuǎn)ost機(jī)器上的物理網(wǎng)卡,通過(guò)MASQUERADE選項(xiàng)修改src地址為網(wǎng)卡eno16777736的IP地址。你也可以用SNAT這個(gè)參數(shù)代替指定一個(gè)特殊IP地址。

請(qǐng)自行參考iptables的用法和原理,如果你的host主機(jī)上實(shí)現(xiàn)設(shè)置了其他iptables rules從而阻止了88.0/24這個(gè)網(wǎng)絡(luò)的forward或者routing,需要自行檢查一下,每一個(gè)機(jī)器的網(wǎng)絡(luò)狀態(tài)是不一樣的沒(méi)辦法全部覆蓋。這里推薦一個(gè)系列博客很詳細(xì)的講解了iptables。?

這里可以看到我們?cè)趎s0下的bash命令行,可以ping通host所在網(wǎng)絡(luò)的機(jī)器30.134和internet上的baidu。現(xiàn)在就完成了整個(gè)模擬實(shí)驗(yàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容