建议使用自定义网桥来控制哪些容器可以相互通讯,还可以自动DNS解析容器名称到ip地址。Docker提供了创建这些网络的默认网络驱动程序,你可以创建一个新的Bridge网络,Overlay或Macvlan网络,你可以创建一个网络插件或远程网络进行完善的自定义和控制。
你可以根据需要创建任意数量的网络,并且可以在任何给定的时间将容器连接到这些网络中的零个或多个网络。此外,您可以连接并断开网络中的容器,而无需重新启动容器,当容器连接到多个网络时,其外部连接通过第一个非内部网络以词法顺序提供。
接下来介绍Docker的内置网络驱动程序
1.1bridge
一个bridge网络时Docker中最常用的网络类型,桥接网络类似于默认briage网络,但添加一些新的功能并删除一些旧的能力,以下示例创建一些桥接网络,并对这些网络上的容器执行一些实验
root@paas:~# docker network create --driver bridge new_bridge
创建好网络后可以看到新增加了一个网桥172.18.0.1
root@paas:~# ifconfig
br-a918a5874846: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:1b:79:99:a5 txqueuelen 0 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:60ff:fed5:d6b7 prefixlen 64 scopeid 0x20<link>
ether 02:42:60:d5:d6:b7 txqueuelen 0 (以太网)
RX packets 127 bytes 11931 (11.9 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3583 bytes 731015 (731.0 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.213.128 netmask 255.255.255.0 broadcast 192.168.213.255
inet6 fe80::1b3e:b3e1:b7ac:b028 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:24:5a:a6 txqueuelen 1000 (以太网)
RX packets 45060 bytes 21955972 (21.9 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 71073 bytes 8811434 (8.8 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (本地环回)
RX packets 6030 bytes 609128 (609.1 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6030 bytes 609128 (609.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth3b5eb18: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::e41e:1ff:feff:f63c prefixlen 64 scopeid 0x20<link>
ether e6:1e:01:ff:f6:3c txqueuelen 0 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2279 bytes 466544 (466.5 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
1.2 macvlan Bridge 模式示例用法
Macvlan是一个新的尝试,是真正的网络虚拟化技术的转折点,Linux实现非常轻量化,因为与传统的Linux Briage隔离相比,他们只是简单地与一个Linux以太网接口与子接口相关联,以实现网络间的分离和物理网络的连接
Macvlan提供了许多独特的功能,并有充足的的空间进一步创新与各种模式,这个方法有两个高级的优点是绕过Linux网桥的正面性能以及移动部件少的简单性,删除传统上驻留在Docker和主机NIC和容器接口之间的网桥留下了一个非常简单地设置,包括容器接口,直接连接到Docker主机接口,由于这种情况没有端口映射,因此可以轻松的访问外部服务。
1.2.1 Macvlan Bridge模式示例用法
Macvlan Briage 模式每个容器都有唯一的MAC地址,用于跟踪Docker主机的MAC到端口映射。Macvlan驱动程序网络连接到父Docker主机接口,示例是物理接口,例如eth0,用于802.1q VLAN标记的子接口eth0.10(.10代表VLAN10)或甚至绑定的主机适配器,将两个以太网接口捆绑为一个以太网接口,指定的网关由网络基础设施提供的主机外部。每个Macvlan Bridge 模式的Docker网络彼此隔离,一次只能有一个网络连接到父节点,每个主机适配器有一个理论限制,每一个主机适配器可以连接一个Docker网络,同一个子网内的任何容器都可以没有相关网卡的同一网络的中的任何其他的容器进行通讯macvlan bridge。相同的docker network命令适用于vlan驱动程序,在macvlan模式下,在两个网络/子网没有外部路由进程的情况下,单独容器网络上的容器无法相互访问。这也适用于统一码头网络内的多个子网。
在以下示例中,eth0在docker主机网络上具有IP地址172.16.86.0/24,默认网关为172.16.86.1,网关地址为外部路由器172.16.86.1。
1.2.2 macvlan802.1q Trunk Bridge模式示例用法
VLAN(虚拟局域网) 长期以来一直是虚拟话数据中心网络的主要手段,目前仍在几乎所有现有的网络中心隔离广播的主要手段。
常用的VLAN划分方式是通过端口进行划分的,尽管这种划分VLAN的方式设置比较简单,但仅适用于终端设备物理位置比较固定的组网环境。随着移动办公的普及,终端设备可能不再通过固定的端口接入交换机,这就会增加网络管理的工作量,比如,一个用户可能本次接入交换机的端口1,下次接入交换的端口2,由于端口1和端口2属于不同VLAN,若用户想要截图原来的VLAN中,网关就必须重新对交换机进行设置,显然,这种划分方式不适用和那些需要频繁改变拓扑结构的网络,而MAC VLAN可以有效解决这个问题,它根据端口设备的MAC地址划分VLAN,这样即便用户改变了接入端口,也仍然处在原VLAN中。
MAC VLAN不是以交换机端口来划分vlan。因此,一个交换机端口可以接受来自多个mac地址的数据,一个交换机端口可以处理多个vlan的数据,而要设置trunk模式。
在主机上同事运行多个虚拟网络的要求是非常常见的。Linux网络长期以来一直支持VLAN标记,也称为标准802.1去,用于维护网络之间的数据路由隔离,连接到Docker主机的以太网链路可以配置为支持802.1q VLAN ID,方法是创建Linux子接口,每个子接口专用于唯一的VLAN ID。
创建macvlan网络
VLAN ID 10
root@paas:~# docker network create --driver macvlan \
> --subnet=192.168.0.0/24 \
> --gateway=192.168.0.1 \
> -o parent=ens33.10 macvlan10
abb8f25122918068f89af8995bb8100cf932c8a7babff18db16b014f579a0536
开启一个桥接Macvlan的容器:
root@paas:~# docker run --net=macvlan10 -it --name macvlan_test1 --rm alpine /bin/sh
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
18: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:c0:a8:00:02 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.2/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
可以看到分配了一个192.168.0.2 的地址,然后看一下路由地址。
/ # ip route
default via 192.168.0.1 dev eth0
192.168.0.0/24 dev eth0 scope link src 192.168.0.2
然后再开启一个桥接Macvlan的容器:
root@paas:~# docker run --net=macvlan10 -it --name macvlan_test2 --rm alpine /bin/sh
/ # ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
7: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:c0:a8:00:03 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.3/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
可以看到分配了一个192.168.0.3的地址,然后可以在两个容器之间相互ping,是可以ping通的。
/ # ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: seq=0 ttl=64 time=0.153 ms
64 bytes from 192.168.0.2: seq=1 ttl=64 time=0.061 ms
^[^A64 bytes from 192.168.0.2: seq=2 ttl=64 time=0.057 ms
经过上面两个容器的创建可以看出,容器IP是根据创建网络时的网段从小往大分配的。
当然,在创建容器时,我们也可以使用–ip手动执行一个IP地址分配给容器,如下操作。
root@paas:~# docker run --net=macvlan10 -it --ip 192.168.0.88 --name macvlan_test2 --rm alpine /bin/sh
/ # ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
8: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:c0:a8:00:58 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.88/24 brd 192.168.0.255 scope global eth0
valid_lft forever preferred_lft forever
VLAN ID 20
接着可以创建由Docker主机标记和隔离的第二个VLAN网络,该macvlan_mode默认是macvlan_mode=bridge,如下:
root@paas:~# docker network create --driver macvlan --subnet=192.10.0.0/24 --gateway=192.10.0.253 -o parent=ens33.20 -o macvlan_mode=bridge macvlan20
20cdadaa2eb30fbb7e7db3d192c43a697ae35f0bcfb653c4f93cdbaadc0332e9
当我们创建完Macvlan网络之后,在docker主机可以看到相关的子接口,如下:
ens33.10: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::20c:29ff:fe24:5aa6 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:24:5a:a6 txqueuelen 0 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 52 bytes 5546 (5.5 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33.20: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::20c:29ff:fe24:5aa6 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:24:5a:a6 txqueuelen 0 (以太网)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 26 bytes 3120 (3.1 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
在/proc/net/vlan/config文件中,还可以看见相关的Vlan信息,如下:
root@paas:~# cat /proc/net/vlan/config
VLAN Dev name | VLAN ID
Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
ens33.10 | 10 | ens33
ens33.20 | 20 | ens33