美文网首页
Docker网络命名空间

Docker网络命名空间

作者: 云师兄 | 来源:发表于2018-06-07 22:58 被阅读26次

    首先运行一个基于busybox镜像的busybox容器,名字为test1:

    docker run -d --name test1 hub.c.163.com/library/busybox:latest /bin/sh -c "while true;do sleep 3600;done"
    

    启动容器后进入容器:

    docker exec -it aec1c356e72c /bin/sh
    

    我们在容器中首先输入命令ip a来查看当前容器的网络接口:

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
    58: eth0@if59: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
        link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    

    第一个网络接口为本地的Lookback,即回还口。当我们创建一个容器时,也会相应创建一个网络namespace。我们退出容器后,在本地宿主机上执行 ip a命令时,打印如下:

    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
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 52:54:00:5f:94:78 brd ff:ff:ff:ff:ff:ff
        inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic eth0
           valid_lft 57642sec preferred_lft 57642sec
        inet6 fe80::5054:ff:fe5f:9478/64 scope link
           valid_lft forever preferred_lft forever
    3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
        link/ether 02:42:08:96:2b:f9 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:8ff:fe96:2bf9/64 scope link
           valid_lft forever preferred_lft forever
    59: vetha65affd@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
        link/ether 5a:31:ef:f0:fb:64 brd ff:ff:ff:ff:ff:ff link-netnsid 1
        inet6 fe80::5831:efff:fef0:fb64/64 scope link
           valid_lft forever preferred_lft forever
    

    由此可见主机的网络接口信息和容器的网络接口信息不同,这是由于宿主机也有自己的网络命名空间,和容器的网络命名空间相互隔离。
    当我们再启动另外一个容器,并执行docker exec -it hub.c.163.com/library/busybox:latest ip a来查看网络的接口信息如下:

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
    60: eth0@if61: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
        link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
           valid_lft forever preferred_lft forever
    

    由此发现,创建的这两个容器的网络是相通的,因为172.17.0.2和172.17.0.3位于同一网段,所以可以ping通。
    接下来来了解下两个容器能够网络相通的原理。

    原理

    sudo ip netns list命令:在宿主机上可以通过来查看当前已有的network namespace。
    sudo ip netns delete test1命令:删除名称为test1的network namespace。
    sudo ip netns add test1命令:新增名为test1的network namespace。
    了解上面几个命令后,我们新增test1和test2两个network namespace,并执行命令:
    sudo ip netns exec test1 ip a来查看test1这个network namespace,如下:

    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
    

    由上可知test1这个network namespace的lo回还口的状态为Down。再介绍一个命名:
    ip link,它也可以查看network namespace信息,另外可以使用这个 命令将状态为down的网络接口启动起来,使之状态为up。为此我们想将test1这个network namespace的lo端口up起来:

    sudo ip netns exec test1 ip link set dev lo up
    

    然后使用sudo ip netns exec test1 ip link来查看test1的网络接口信息,如下:

    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
    

    状态并没有从down变成up,而是变成了unknown状态。这是因为在Linux里面端口是成对出现才会变成up状态。

    下面我们来了解下两个命名空间之间通信的原理:


    image.png

    由上图可知,两个命名空间内部都有一个通信的接口,中间通过类似于网线的Veth pair进行通信,下面我们通过命令来模拟这个实现的过程:
    首先我们执行命令如下:

    sudo ip link add veth-test1 type veth peer name veth-test2
    

    通过这个命令,我们创建了两个网络端口veth-test1和veth-test2,查看结果:

    [vagrant@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:5f:94:78 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:08:96:2b:f9 brd ff:ff:ff:ff:ff:ff
    59: vetha65affd@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
        link/ether 5a:31:ef:f0:fb:64 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    61: veth7dcab2c@if60: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
        link/ether 32:87:13:6c:b5:39 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    62: veth-test2@veth-test1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
        link/ether da:3f:b3:ab:f7:0b brd ff:ff:ff:ff:ff:ff
    63: veth-test1@veth-test2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
        link/ether e2:5a:43:9f:c0:a8 brd ff:ff:ff:ff:ff:ff
    

    可以看到现在在最下面多了两个网络端口。
    接着我们将创建的这两个网络端口分别添加到两个命名空间中:

    sudo ip link set veto-test1 netns test1
    sudo ip link set veto-test2 netns test2
    

    添加完后查看命名空间test1和test2的网络接口信息:

    [vagrant@localhost ~]$ sudo 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
    63: veth-test1@if62: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
        link/ether e2:5a:43:9f:c0:a8 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    [vagrant@localhost ~]$ sudo 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
    62: veth-test2@if63: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
        link/ether da:3f:b3:ab:f7:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    

    可以看出,两个命名空间中已经多了网络端口veth-test1和veth-test2。
    但是这两个网络端口状态都是down,并且没有IP地址,为此下面我们给这两个网络端口分配IP地址:

    sudo ip netns exec test1 ip addr add 192.168.1.1/24 dev veth-test1
    sudo ip netns exec test2 ip addr add 192.168.1.2/24 dev veth-test2
    

    然后我们将这两个网络端口都up起来:

    sudo ip netns exec test1 ip link set dev veth-test1 up
    sudo ip netns exec test2 ip link set dev veth-test2 up
    

    由于192.168.1.1和192.168.1.2这两个地址位于同一网段,为此两个命名空间之间就可以互相ping通了:

    [vagrant@localhost ~]$ sudo 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.062 ms
    64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.052 ms
    64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=0.070 ms
    64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=0.058 ms
    ^C
    --- 192.168.1.2 ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3007ms
    rtt min/avg/max/mdev = 0.052/0.060/0.070/0.010 ms
    

    这就是两个容器也能ping通的原理。

    相关文章

      网友评论

          本文标题:Docker网络命名空间

          本文链接:https://www.haomeiwen.com/subject/gsvnsftx.html