docker 还开发了另一个支持跨主机容器网络的 driver:macvlan.
macvlan 本身是 linxu kernel 模块, 其功能是允许在同一个物理网卡上配置多个 Mac 地址, 即多个 interface, 每个 interface 可以配置自己的 IP.macvlan 本质上是一种网卡虚拟化技术, Docker 用 macvlan 实现容器网络就不奇怪了.
macvlan 的最大优点是性能极好, 相比其他实现, macvlan 不需要创建 Linux bridge, 而是直接通过以太 interface 连接到物理网络. 下面我们就来创建一个 macvlan 网络.
准备测试环境
我们会使用 fdfs1 和 fdfs2 上单独的网卡 eth0 创建 macvlan. 为保证多个 Mac 地址的网络包都可以从 eth0 通过, 我们需要打开网卡的混杂模式
- ip link set eth0 promisc on
- [[email protected]-1 ~]# 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
- .NET 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,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
- link/ether 52:54:00:3e:3c:ef brd ff:ff:ff:ff:ff:ff
- .NET 192.168.16.6/24 brd 192.168.16.255 scope global noprefixroute eth0
- valid_lft forever preferred_lft forever
- inet6 fe80::5054:ff:fe3e:3cef/64 scope link
- valid_lft forever preferred_lft forever
在两台主机上分别执行以下命令, 创建 macvlan 网卡(由于我们 kvm 主机没有做 vlan 配置, macvlan 复刻 host 的 ip 配置)
docker network create -d macvlan --subnet=192.168.16.0/24 --gateway=192.168.16.1 -o parent=eth0 manet_1
启动两个 alpine 容器进行 ping 测试
- [[email protected]1 ~]# docker run -d --network=manet_1 --ip=192.168.16.111 --name test1 alpine sleep 10000
- 58c9e529e491689b6b4f2b6dc6c58103b4b9b84a77db2df7047eb5513205f2d7
- [[email protected]-2 ~]# docker run -d --network=manet_1 --ip=192.168.16.112 --name test2 alpine sleep 10000
- d5e23bf52dd149259ff5fee8cd777c0cee40fb789bc507e10b2cc54813db9e0d
- [[email protected] ~]# docker exec test1 ping 192.168.16.112
- PING 192.168.16.112 (192.168.16.112): 56 data bytes
- 64 bytes from 192.168.16.112: seq=0 ttl=64 time=0.370 ms
- 64 bytes from 192.168.16.112: seq=1 ttl=64 time=0.364 ms
- 64 bytes from 192.168.16.112: seq=2 ttl=64 time=0.439 ms
- [[email protected] ~]# docker exec test2 ping 192.168.16.111
- PING 192.168.16.111 (192.168.16.111): 56 data bytes
- 64 bytes from 192.168.16.111: seq=0 ttl=64 time=1.418 ms
- 64 bytes from 192.168.16.111: seq=1 ttl=64 time=0.403 ms
- 64 bytes from 192.168.16.111: seq=2 ttl=64 time=0.409 ms
成功跨主机通信
可见, 容器的 eth0 就是 宿主机 eth0 通过 macvlan 虚拟出来的 interface. 容器的 interface 直接与主机的网卡连接, 这种方案使得容器无需通过 NAT 和端口映射就能与外网直接通信(只要有网关), 在网络上与其他独立主机没有区别.
macvlan 会独占主机的网卡, 也就是说一个网卡只能创建一个 macvlan 网络
但主机的网卡数量是有限的, 如何支持更多的 macvlan 网络
好在 macvlan 不仅可以连接到 interface(如 eth0), 也可以连接到 sub-interface(如 eth0.xxx).
VLAN 是现代网络常用的网络虚拟化技术, 它可以将物理的二层网络划分成多达 4094 个逻辑网络, 这些逻辑网络在二层上是隔离的, 每个逻辑网络 (即 VLAN) 由 VLAN ID 区分, VLAN ID 的取值为 1-4094.
Linux 的网卡也能支持 VLAN(apt-get install vlan), 同一个 interface 可以收发多个 VLAN 的数据包, 不过前提是要创建 VLAN 的 sub-interface.
比如希望 eth0 同时支持 VLAN10 和 VLAN20, 则需创建 sub-interface eth0.10 和 eth0.20.
在交换机上, 如果某个 port 只能收发单个 VLAN 的数据, 该 port 为 Access 模式, 如果支持多 VLAN, 则为 Trunk 模式, 所以接下来实验的前提是:
eth0 要接在交换机的 trunk 口上. 不过我们用的是 VirtualBox 虚拟机, 则不需要额外配置了.
来源: http://www.bubuko.com/infodetail-3109701.html