1. 程式人生 > 其它 >Docker之網路名稱空間

Docker之網路名稱空間

namespace(名稱空間)和cgroup是軟體容器化(想想Docker)趨勢中的兩個主要核心技術。簡單來說,cgroup是一種對程序進行統一的資源監控和限制,它控制著你可以使用多少系統資源(CPU,記憶體等)。而namespace是對全域性系統資源的一種封裝隔離,它通過Linux核心對系統資源進行隔離和虛擬化的特性,限制可以檢視的內容。Linux 3.8核心提供了6種類型的名稱空間:Process ID (pid)、Mount (mnt)、Network (net)、InterProcess Communication (ipc)、UTS、User ID (user)。例如,pid名稱空間內的程序只能看到同一名稱空間中的程序。mnt名稱空間,可以將程序附加到自己的檔案系統(如chroot)。

在本文中,只關注網路名稱空間 Network (net)。網路名稱空間為名稱空間內的所有程序提供了全新隔離的網路協議棧。這包括網路介面,路由表和iptables規則。通過使用網路名稱空間就可以實現網路虛擬環境,實現彼此之間的網路隔離,這對於雲端計算中租戶網路隔離非常重要,Docker中的網路隔離也是基於此實現的。下面進入正題,介紹如何使用網路名稱空間。

環境準備及狀態確認

1.建立測試容器

#建立兩個測試容器
[root@localhost ~]# docker run -d -it --name busybox_1 busybox /bin/sh -c "while true;do sleep 3600;done
" [root@localhost ~]# docker run -d -it --name busybox_2 busybox /bin/sh -c "while true;do sleep 3600;done" [root@localhost ~]# docker ps -a

2.檢視容器IP及網路聯通性

#檢視容器的IP
[root@localhost ~]# docker exec -it busybox_1 ip a
[root@localhost ~]# docker exec -it busybox_2 ip a

[root@localhost ~]# docker exec -it busybox_1 /bin/sh
/ # ping 172.17.0.3 #進入容器,ping busybox_2的地址 PING 172.17.0.3 (172.17.0.3): 56 data bytes 64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.133 ms 64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.097 ms 64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.124 ms [root@localhost ~]# docker exec -it busybox_2 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.109 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.152 ms

現象總結:同一臺宿主機上建立的容器預設是能夠互相通訊的。

通過命令列模擬docker容器的網路通訊

1.手動建立兩個網路名稱空間

[root@localhost ~]# ip netns add test1 
[root@localhost ~]# ip netns add test2
[root@localhost ~]# ip netns list
test2
test1

2.檢視test1網路名稱空間網路狀態

[root@localhost ~]# ip netns exec test1 ip link 
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000 #預設只存在lo介面,並且狀態為DOWN 
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

3.檢視宿主機網路裝置

[root@localhost ~]# ip link #發現除了正常系統存在的lo和eth0網路介面外,還存在其他三個介面
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:fd:34:4b brd ff:ff:ff:ff:ff:ff
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
link/ether 02:42:23:c0:91:f9 brd ff:ff:ff:ff:ff:ff
105: veth0a87245@if104: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default 
link/ether f2:be:7e:3c:02:3c brd ff:ff:ff:ff:ff:ff link-netnsid 0
107: vethabf8073@if106: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default 
link/ether d6:dd:20:cf:84:4a brd ff:ff:ff:ff:ff:ff link-netnsid 1

4.建立一對veth pair網路介面

什麼是veth pair?veth pair 不是一個裝置,而是一對裝置,以連線兩個虛擬以太埠。操作veth pair,需要跟namespace一起配合。兩個namespace ns1/ns2 中各有一個tap組成veth pair,兩個tap 上配置的ip進行互ping

簡單的拓撲圖:

建立一對veth pair

[root@localhost ~]# ip link add veth-test1 type veth peer name veth-test2 #建立 veth-test1 和 veth-test2 一對pair
[root@localhost ~]# ip link #檢視是否新增成功 108 109
108: veth-test2@veth-tes1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether be:08:e6:25:be:01 brd ff:ff:ff:ff:ff:ff
109: veth-tes1@veth-test2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether da:97:e4:b1:cc:38 brd ff:ff:ff:ff:ff:ff

5.將veth-test1 介面新增到test1網路名稱空間中去

[root@localhost ~]# ip link  set veth-test1  netns test1
[root@localhost ~]# ip netns exec test1 ip link #檢視是否新增成功,狀態為DOWN
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
109: veth-tes1@if108: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether da:97:e4:b1:cc:38 brd ff:ff:ff:ff:ff:ff link-netnsid 0

6.檢查宿主機本地網路介面(109: veth-tes1@veth-test2已經沒有了)

[root@localhost ~]# ip link 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:fd:34:4b brd ff:ff:ff:ff:ff:ff
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:23:c0:91:f9 brd ff:ff:ff:ff:ff:ff
105: veth0a87245@if104: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default 
    link/ether f2:be:7e:3c:02:3c brd ff:ff:ff:ff:ff:ff link-netnsid 0
107: vethabf8073@if106: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default 
    link/ether d6:dd:20:cf:84:4a brd ff:ff:ff:ff:ff:ff link-netnsid 1
108: veth-test2@if109: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether be:08:e6:25:be:01 brd ff:ff:ff:ff:ff:ff link-netnsid 2

7.參照之前步驟,將veth-test2 介面新增到test2網路名稱空間中去

[root@localhost ~]# ip link set veth-test2 netns test2
[root@localhost ~]# ip netns exec test2 ip link

8.為兩個網路名稱空間的網路介面分別新增一個IP地址

[root@localhost ~]# ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1  #為test1網路名稱空間中veth-test1介面新增IP,地址為192.168.1.1
[root@localhost ~]# ip netns exec test2 ip addr add 192.168.1.2/24 dev veth-test2   #同上

[root@localhost ~]# ip netns exec test1 ip a #檢視test1網路名稱介面狀態,veth-test1已經綁定了IP,但是狀態為DOWN
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
109: veth-tes1@if108: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether da:97:e4:b1:cc:38 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet 192.168.1.1/24 scope global veth-tes1
       valid_lft forever preferred_lft forever
[root@localhost ~]# ip netns exec test2 ip a #同上
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
108: veth-test2@if109: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether be:08:e6:25:be:01 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.1.2/24 scope global veth-test2
       valid_lft forever preferred_lft forever

9.啟動以上兩個網路介面

[root@localhost ~]# ip netns exec test1 ip link set dev veth-test1 up
[root@localhost ~]# ip netns exec test2 ip link set dev veth-test2 up
[root@localhost ~]# ip netns exec test1 ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
109: veth-tes1@if108: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether da:97:e4:b1:cc:38 brd ff:ff:ff:ff:ff:ff link-netnsid 1
[root@localhost ~]# ip netns exec test2 ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
108: veth-test2@if109: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether be:08:e6:25:be:01 brd ff:ff:ff:ff:ff:ff link-netnsid 0

10.測試通訊

#網路通訊測試    
[root@localhost ~]# ip netns exec test1 ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.057 ms

[root@localhost ~]# ip netns exec test2 ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.039 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.084 ms