Linux Namespace : Network

Network namespace 在邏輯上是網絡堆棧的一個副本,它有本身的路由、防火牆規則和網絡設備。默認狀況下,子進程繼承其父進程的 network namespace。也就是說,若是不顯式建立新的 network namespace,全部進程都從 init 進程繼承相同的默認 network namespace。html

每一個新建立的 network namespace 默認有一個本地環回接口 lo,除此以外,全部的其餘網絡設備(物理/虛擬網絡接口,網橋等)只能屬於一個 network namespace。每一個 socket 也只能屬於一個 network namespace。linux

說明:本文的演示環境爲 ubuntu 16.04。docker

ip netns 命令
ip netns 命令用來管理 network namespace。本文將使用 ip netns 命令來建立和操做 network namespace。有關 ip netns 命令的詳細介紹請參考筆者的博文《Linux ip netns 命令》。ubuntu

建立 network namespace

咱們先查一下看默認的 network namespace 的 ID:segmentfault

$ readlink /proc/$$/ns/net

而後經過 ip netns add 命令建立名爲 mynet 的 network namespace:bash

$ sudo ip netns add mynet

從上圖能夠看出,在名爲 mynet 的 network namespace 建立成功後,/var/run/netns 目錄下多了一個名爲 mynet 文件。ip netns exec 子命令能夠在對應的 network namespace 中執行命令,下面咱們就經過它在 mynet network namespace 中建立一個 bash 進程,並查看 network namespace 的 ID:網絡

$ sudo ip netns exec mynet bash
# readlink /proc/$$/ns/net

這是一個徹底不一樣的 network namespace ID,說明當前的 bash 進程運行在一個隔離的 network 環境中。接下來讓咱們看看新的 network namespace 中都有什麼:socket

# ip addr

每一個新建立的 network namespace 默認有一個本地環回接口 lo,而且這個接口是處於關閉狀態的。下面咱們就啓動這個接口:spa

# ip link set lo up

啓動 lo 接口後咱們能夠看到其 IP 地址,而且可以正確的響應 ping 命令。3d

在兩個 network namespace 之間通訊

network namespace 之間是相互隔離的,咱們可使用 veth 設備把兩個 network namespace 鏈接起來進行通訊。veth 設備是虛擬的以太網設備。它們能夠充當 network namespace 之間的通道,也能夠做爲獨立的網絡設備使用。veth 設備老是被成對的建立,而且這一對設備老是鏈接在一塊兒的,因此通常把稱之爲 veth pair。須要注意的是,veth pair 沒法單獨存在,刪除其中一個,另外一個也會自動消失。接下來的示例咱們就演示如何使用 veth pair 在兩個 network namespace 直接通訊。示例中咱們使用 ip link 命令來建立和管理 veth pair。

第一步,先建立兩個 network namespace net0 和 net1

$ sudo ip netns add net0
$ sudo ip netns add net1

第二步,建立一對命名的 veth 設備
默認狀況下會自動爲 veth pair 生成名稱,這裏爲了易於辨識,咱們在建立時指定 veth pair 的名稱:

$ sudo ip link add vethmother type veth peer name vethfather

如圖所示,veth pair 在主機上表現爲兩個網卡。

第三步,把這一對 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 中的網絡資源,發現各自多了一個網卡,也就是 veth 設備的兩個端點。注意,當咱們把 veth pair 分配到 network namespace 中後,在主機上就看不到它們了:

此時主機的網卡中已經看不到剛纔的 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

下面經過 ping 命令來驗證兩個 network namespace 是否能夠通訊:

$ sudo ip netns exec net0 ping -c 3 10.0.1.2

至此,咱們構建了一個以下結構的虛擬網絡:

經過 bridge 鏈接 network namespace

雖然 veth pair 能夠實現兩個 network namespace 之間的通訊,可是當須要在多個 network namespace 之間通訊的時候,光靠 veth pair 就不行了。咱們可使用 Linux 提供的虛擬交換機,來完成這樣的功能。下面的示例演示如何經過虛擬交換機(這裏就是一個虛擬網橋)鏈接多個 network namespace。

第一步,先添加一個叫 mybridge0 的網橋

$ sudo ip link add mybridge0 type bridge
$ sudo ip link set dev mybridge0 up
$ sudo ip addr

對主機來講其實就是新添加了一個網絡接口(network interface):

第二步,建立 network namespace 和 veth 設備
建立 network namespace net0:

$ sudo ip netns add net0

建立 veth 設備:

$ sudo ip link add veth0 type veth peer name veth0p 

把其中的一個 veth 放置到 net0 中,設置 IP 並啓動它:

$ 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 網卡已經啓動了。下面把 veth 設備的另外一端鏈接到網橋 mybridge0 上:

$ sudo ip link set dev veth0 master mybridge0
$ sudo ip link set dev veth0 up

第三步,重複第二步建立 net1 和 net2,並鏈接到網橋
給 mybridge0 設置 IP:

$ 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

經過 bridge link 命令查看網橋的信息以下:

這時就能夠在不一樣的 network namespace 之間通訊了:

$ sudo ip netns exec net0 ping -c 3 10.0.1.3

咱們建立的網絡拓撲結構以下所示:

總結

經過 network namespace 能夠建立相互獨立的網絡棧,從而實現網絡的隔離。本文只是簡單的介紹了 network namespace 的建立以及如何在 network namespace 之間通訊,其中 network namespace 之間經過 bridge 通訊的方式已經與 docker 網絡的 bridge 模式很是相似了。

參考:
Network namespace man page
Linux Namespace系列(06):network namespace (CLONE_NEWNET)
Network namespace 簡介

相關文章
相關標籤/搜索