Network namespace 在邏輯上是網(wǎng)絡(luò)堆棧的一個(gè)副本,它有自己的路由、防火墻規(guī)則和網(wǎng)絡(luò)設(shè)備。默認(rèn)情況下,子進(jìn)程繼承其父進(jìn)程的 network namespace。也就是說(shuō),如果不顯式創(chuàng)建新的 network namespace,所有進(jìn)程都從 init 進(jìn)程繼承相同的默認(rèn) network namespace。 每個(gè)新創(chuàng)建的 network namespace 默認(rèn)有一個(gè)本地環(huán)回接口 lo,除此之外,所有的其他網(wǎng)絡(luò)設(shè)備(物理/虛擬網(wǎng)絡(luò)接口,網(wǎng)橋等)只能屬于一個(gè) network namespace。每個(gè) socket 也只能屬于一個(gè) network namespace。 說(shuō)明:本文的演示環(huán)境為 ubuntu 16.04。 ip netns 命令 創(chuàng)建 network namespace我們先查一下看默認(rèn)的 network namespace 的 ID: $ readlink /proc/$$/ns/net 然后通過(guò) ip netns add 命令創(chuàng)建名為 mynet 的 network namespace: $ sudo ip netns add mynet 從上圖可以看出,在名為 mynet 的 network namespace 創(chuàng)建成功后,/var/run/netns 目錄下多了一個(gè)名為 mynet 文件。ip netns exec 子命令可以在對(duì)應(yīng)的 network namespace 中執(zhí)行命令,下面我們就通過(guò)它在 mynet network namespace 中創(chuàng)建一個(gè) bash 進(jìn)程,并查看 network namespace 的 ID: $ sudo ip netns exec mynet bash # readlink /proc/$$/ns/net 這是一個(gè)完全不同的 network namespace ID,說(shuō)明當(dāng)前的 bash 進(jìn)程運(yùn)行在一個(gè)隔離的 network 環(huán)境中。接下來(lái)讓我們看看新的 network namespace 中都有什么: # ip addr 每個(gè)新創(chuàng)建的 network namespace 默認(rèn)有一個(gè)本地環(huán)回接口 lo,并且這個(gè)接口是處于關(guān)閉狀態(tài)的。下面我們就啟動(dòng)這個(gè)接口: # ip link set lo up 啟動(dòng) lo 接口后我們可以看到其 IP 地址,并且能夠正確的響應(yīng) ping 命令。 在兩個(gè) network namespace 之間通信network namespace 之間是相互隔離的,我們可以使用 veth 設(shè)備把兩個(gè) network namespace 連接起來(lái)進(jìn)行通信。veth 設(shè)備是虛擬的以太網(wǎng)設(shè)備。它們可以充當(dāng) network namespace 之間的通道,也可以作為獨(dú)立的網(wǎng)絡(luò)設(shè)備使用。veth 設(shè)備總是被成對(duì)的創(chuàng)建,并且這一對(duì)設(shè)備總是連接在一起的,所以一般把稱之為 veth pair。需要注意的是,veth pair 無(wú)法單獨(dú)存在,刪除其中一個(gè),另一個(gè)也會(huì)自動(dòng)消失。接下來(lái)的示例我們就演示如何使用 veth pair 在兩個(gè) network namespace 直接通信。示例中我們使用 ip link 命令來(lái)創(chuàng)建和管理 veth pair。 第一步,先創(chuàng)建兩個(gè) network namespace net0 和 net1 $ sudo ip netns add net0 $ sudo ip netns add net1 第二步,創(chuàng)建一對(duì)命名的 veth 設(shè)備 $ sudo ip link add vethmother type veth peer name vethfather 如圖所示,veth pair 在主機(jī)上表現(xiàn)為兩個(gè)網(wǎng)卡。 第三步,把這一對(duì) veth pair 分別放到 network namespace net0 和 net1中 $ sudo ip link set vethmother netns net0 $ sudo ip link set vethfather netns net1 $ sudo ip netns exec net0 ip addr $ sudo ip netns exec net1 ip addr 查看 net0 和 net1 中的網(wǎng)絡(luò)資源,發(fā)現(xiàn)各自多了一個(gè)網(wǎng)卡,也就是 veth 設(shè)備的兩個(gè)端點(diǎn)。注意,當(dāng)我們把 veth pair 分配到 network namespace 中后,在主機(jī)上就看不到它們了: 此時(shí)主機(jī)的網(wǎng)卡中已經(jīng)看不到剛才的 veth pair 身影了。 第四步,給這些 veth pair 分配 IP 并啟用它們 $ sudo ip netns exec net0 ip link set vethmother up $ sudo ip netns exec net0 ip addr add 10.0.1.1/24 dev vethmother $ sudo ip netns exec net0 ip route $ sudo ip netns exec net1 ip link set vethfather up $ sudo ip netns exec net1 ip addr add 10.0.1.2/24 dev vethfather $ sudo ip netns exec net1 ip route 下面通過(guò) ping 命令來(lái)驗(yàn)證兩個(gè) network namespace 是否可以通信: $ sudo ip netns exec net0 ping -c 3 10.0.1.2 至此,我們構(gòu)建了一個(gè)如下結(jié)構(gòu)的虛擬網(wǎng)絡(luò): 通過(guò) bridge 連接 network namespace雖然 veth pair 可以實(shí)現(xiàn)兩個(gè) network namespace 之間的通信,但是當(dāng)需要在多個(gè) network namespace 之間通信的時(shí)候,光靠 veth pair 就不行了。我們可以使用 Linux 提供的虛擬交換機(jī),來(lái)完成這樣的功能。下面的示例演示如何通過(guò)虛擬交換機(jī)(這里就是一個(gè)虛擬網(wǎng)橋)連接多個(gè) network namespace。 第一步,先添加一個(gè)叫 mybridge0 的網(wǎng)橋 $ sudo ip link add mybridge0 type bridge $ sudo ip link set dev mybridge0 up $ sudo ip addr 對(duì)主機(jī)來(lái)說(shuō)其實(shí)就是新添加了一個(gè)網(wǎng)絡(luò)接口(network interface): 第二步,創(chuàng)建 network namespace 和 veth 設(shè)備 $ sudo ip netns add net0 創(chuàng)建 veth 設(shè)備: $ sudo ip link add veth0 type veth peer name veth0p 把其中的一個(gè) veth 放置到 net0 中,設(shè)置 IP 并啟動(dòng)它: $ sudo ip link set dev veth0p netns net0 $ sudo ip netns exec net0 ip link set dev veth0p name eth0 $ sudo ip netns exec net0 ip addr add 10.0.1.1/24 dev eth0 $ sudo ip netns exec net0 ip link set dev eth0 up $ sudo ip netns exec net0 ip addr 上圖顯示 network namespace net0 中的 eth0 網(wǎng)卡已經(jīng)啟動(dòng)了。下面把 veth 設(shè)備的另一端連接到網(wǎng)橋 mybridge0 上: $ sudo ip link set dev veth0 master mybridge0 $ sudo ip link set dev veth0 up 第三步,重復(fù)第二步創(chuàng)建 net1 和 net2,并連接到網(wǎng)橋 $ sudo ip link set dev mybridge0 down $ sudo ip addr add 10.0.1.0/24 dev mybridge0 $ sudo ip link set dev mybridge0 up $ ip addr 通過(guò) bridge link 命令查看網(wǎng)橋的信息如下: 這時(shí)就可以在不同的 network namespace 之間通信了: $ sudo ip netns exec net0 ping -c 3 10.0.1.3 我們創(chuàng)建的網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)如下所示: 總結(jié)通過(guò) network namespace 可以創(chuàng)建相互獨(dú)立的網(wǎng)絡(luò)棧,從而實(shí)現(xiàn)網(wǎng)絡(luò)的隔離。本文只是簡(jiǎn)單的介紹了 network namespace 的創(chuàng)建以及如何在 network namespace 之間通信,其中 network namespace 之間通過(guò) bridge 通信的方式已經(jīng)與 docker 網(wǎng)絡(luò)的 bridge 模式非常類似了。 參考: |
|