【Docker网络原理分析四】不同网络中的容器如何通信

我们自定义两个容器网络,network1和network2,如何实现两个网络中容器通信呢?

自定义两个网络network1 (172.19.1.0/24)和network2(172.19.2.0/24)

[root@localhost ~]# docker network create network1 --subnet   172.19.1.0/24
ec6f94effcea558ade7634b90ce9b015952827e968007a660993ba7d86b7cdf4
[root@localhost ~]# docker network create network2 --subnet   172.19.2.0/24
9feb392b7cd01d43ff47fb96e1549aeda7c5a590214585ec8e6c6179e3434bc8
[root@localhost ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
96acf619479a        bridge              bridge              local
b4a586d8b755        host                host                local
ec6f94effcea        network1            bridge              local
9feb392b7cd0        network2            bridge              local
d66905d1ffee        none                null                local

在两个网络中,分别生成两个容器

[root@localhost ~]# docker run -itd --network network1 --name box1-1 busybox
[root@localhost ~]# docker run -itd --network network1 --name box1-2 busybox
[root@localhost ~]# docker run -itd --network network2 --name box2-1 busybox
[root@localhost ~]# docker run -itd --network network2 --name box2-2 busybox

相同网络中容器能正常通信,不在一个网络中容器,无法通信。如何实现他们能通信呢?

方法一:把容器加入另一个网络中

问题转换下,正常情况下,不在一个网络中物理机如何通信呢?如何物理条件允许,我们可以把一个物理机加入到另一个物理机的网络中,这样就能实现两个物理机通信,前提是物理可达,以及物理机有多个网卡,对应到容器中,我们可以把容器加入到另一个网络中,这样也能实现容器和其他网络中容器通信,

#把box1-1加入到network2中
[root@localhost ~]# docker network connect  network2 box1-1
#进入box1-1中查看网络设备
[root@localhost ~]# docker exec -it  box1-1  sh
/ # ip addr
1: lo:  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
17: eth0@if18:  mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:13:01:02 brd ff:ff:ff:ff:ff:ff
    inet 172.19.1.2/24 brd 172.19.1.255 scope global eth0
       valid_lft forever preferred_lft forever
25: eth1@if26:  mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:13:02:04 brd ff:ff:ff:ff:ff:ff
    inet 172.19.2.4/24 brd 172.19.2.255 scope global eth1
       valid_lft forever preferred_lft forever
#验证
/ # ping  -c 2 172.19.2.3
PING 172.19.2.3 (172.19.2.3): 56 data bytes
64 bytes from 172.19.2.3: seq=0 ttl=64 time=0.851 ms
64 bytes from 172.19.2.3: seq=1 ttl=64 time=0.104 ms

--- 172.19.2.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.104/0.477/0.851 ms
/ # ping  -c 2 172.19.1.3
PING 172.19.1.3 (172.19.1.3): 56 data bytes
64 bytes from 172.19.1.3: seq=0 ttl=64 time=0.935 ms
64 bytes from 172.19.1.3: seq=1 ttl=64 time=0.087 ms

--- 172.19.1.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.087/0.511/0.935 ms

进入容器中,我们看到就是在box1-1中加入了新的veth-pair设备。从之前的文章中,我们可以分析到其实就是把veth-pair的一端放入到box-1-1的命名空间中,一端依附到要加入的网络的网桥中。同时给放入netns中的一端中加入网络地址。

接下来,我们通过手动方式给box1-2添加到network2中,首先恢复下docker隐藏的box1-2的netns:

#获取容器box1-2的进程号
[root@localhost ~]# docker inspect box1-2 |grep Pid
            "Pid": 7629,
#将进程网络命名空间恢复到主机目录(没有 /var/run/netns先创建)
ln -s /proc/容器进程号/ns/net /var/run/netns/容器
[root@localhost ~]# ln -s /proc/7629/ns/net   /var/run/netns/box1-2
#查看恢复的netns
[root@localhost ~]# ip netns list
box1-2 (id: 2)

增加veth-pair并配置网络

#增加veth-pari对设备
ip link add veth_b_1_2 type veth name peer veth_b_1_2_peer
#把一端放入box1-2的netns中
ip link set veth_b_1_2 ns box1-2
#配置IP地址
ip netns exec box1-2 ip addr add 172.17.2.5/24 dev veth_b_1_2
ip netns exec box1-2 ip link set veth_b_1_2  up
#把一端依附到对应的网桥上
#查看网络对应的网桥
ip addr
#忽略其它的
.......
8: br-9feb392b7cd0:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0c:c1:a6:7a brd ff:ff:ff:ff:ff:ff
    inet 172.19.2.1/24 brd 172.19.2.255 scope global br-9feb392b7cd0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:cff:fec1:a67a/64 scope link 
       valid_lft forever preferred_lft forever
.....
ip link set dev veth_b_1_2_peer master br-9feb392b7cd0
ip link set veth_b_1_2_peer  up

验证

[root@localhost ~]#  ip netns exec box1-2  ping -c 2 172.19.2.2
PING 172.19.2.2 (172.19.2.2) 56(84) bytes of data.
64 bytes from 172.19.2.2: icmp_seq=1 ttl=64 time=0.233 ms
64 bytes from 172.19.2.2: icmp_seq=2 ttl=64 time=0.064 ms

--- 172.19.2.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.064/0.148/0.233/0.085 ms
[root@localhost ~]# docker exec -it box1-2 sh
/ # ip addr
1: lo:  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
19: eth0@if20:  mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:13:01:03 brd ff:ff:ff:ff:ff:ff
    inet 172.19.1.3/24 brd 172.19.1.255 scope global eth0
       valid_lft forever preferred_lft forever
28: veth_b_1_2@if27:  mtu 1500 qdisc noqueue qlen 1000
    link/ether 9e:7b:c9:91:7f:b2 brd ff:ff:ff:ff:ff:ff
    inet 172.19.2.5/24 scope global veth_b_1_2
       valid_lft forever preferred_lft forever

方法二:把需要通信的容器加入到第三方网络中

如果两个容器想要通信,就把两个容器加入第三方网络中,这样两个容器就能通信了,具体思路就是创建第三网络,使用docker connect 命令把两个需要通信的容器加入到这个网络中,实现通信,如果不想让两个容器通信了,就通过docker disconnect删除。底层的原理和上面的方法类似就不展开分析了。

方法三:修改底层的iptables规则实现两个网络通信

方法一和方法二都是通过把容器加入到网络中,想办法把想要通信的容器加入到一个网络中。从《容器网络原理分析一》种可以得到,正常情况下,创建好ns配置好网络以及路由,同一个宿主机中的不同的bridge之间是可以通信的。为什么容器的两个网络之间是无法通信呢?《容器网络原理分析基础篇》中得知是iptables规则给阻拦了。

1.首先找到网络的桥接接口名称

[root@localhost ~]# ip addr
........
7: br-ec6f94effcea:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:be:93:94:2f brd ff:ff:ff:ff:ff:ff
    inet 172.19.1.1/24 brd 172.19.1.255 scope global br-ec6f94effcea
       valid_lft forever preferred_lft forever
    inet6 fe80::42:beff:fe93:942f/64 scope link 
       valid_lft forever preferred_lft forever
8: br-9feb392b7cd0:  mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0c:c1:a6:7a brd ff:ff:ff:ff:ff:ff
    inet 172.19.2.1/24 brd 172.19.2.255 scope global br-9feb392b7cd0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:cff:fec1:a67a/64 scope link 
       valid_lft forever preferred_lft forever
........

2.修改iptables规则实现两个子网通信

[root@localhost ~]# iptables -I DOCKER-USER -i br-ec6f94effcea -o br-9feb392b7cd0 -j ACCEPT
[root@localhost ~]# iptables -I DOCKER-USER -i br-9feb392b7cd0 -o br-ec6f94effcea -j ACCEPT

 

你可能感兴趣的:(Cloud,Computing,Networking)