容器网络(八)macvlan 网络结构分析【51】
(九)macvlan 网络结构分析
上一节我们创建了 macvlan 并部署了容器,本节详细分析 macvlan 底层网络结构。
(1)macvlan 网络结构分析
macvlan 不依赖 Linux bridge,brctl show
可以确认没有创建新的 bridge。
root@host2:~# brctl show
bridge name bridge id STP enabled interfaces
br-283474cba87c 8000.024237a184c6 no
br-ba21840c1713 8000.0242f55e6a61 no
docker0 8000.0242a529e093 no
查看一下容器 bbox11 的网络设备:
root@host2:~# docker exec bbox11 ip link
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
8: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:10:56:0c brd ff:ff:ff:ff:ff:ff
除了 lo,容器只有一个 eth0,请注意 eth0 后面的 @if3
,这表明该 interface 有一个对应的 interface,其全局的编号为 3。根据 macvlan 的原理,我们有理由猜测这个 interface 就是主机的 ens38,确认如下:
root@host2:~# ip link show ens38
3: ens38: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 00:0c:29:58:95:95 brd ff:ff:ff:ff:ff:ff
root@host2:~#
可见,容器的 eth0 就是 ens38 通过 macvlan 虚拟出来的 interface。容器的 interface 直接与主机的网卡连接,这种方案使得容器无需通过 NAT 和端口映射就能与外网直接通信(只要有网关),在网络上与其他独立主机没有区别。当前网络结构如图所示:
(2)用 sub-interface 实现多 macvlan 网络
macvlan 会独占主机的网卡,也就是说一个网卡只能创建一个 macvlan 网络,否则会报错:
root@host2:~# docker network create -d macvlan -o parent=ens38 mac_net2
Error response from daemon: network dm-e46963ceafd9 is already using parent interface ens38
root@host2:~#
但主机的网卡数量是有限的,如何支持更多的 macvlan 网络呢?
好在 macvlan 不仅可以连接到 interface(如 ens38),也可以连接到 sub-interface(如 ens38.xxx)。
VLAN 是现代网络常用的网络虚拟化技术,它可以将物理的二层网络划分成多达 4094 个逻辑网络,这些逻辑网络在二层上是隔离的,每个逻辑网络(即 VLAN)由 VLAN ID 区分,VLAN ID 的取值为 1-4094。
Linux 的网卡也能支持 VLAN(apt-get install vlan
),同一个 interface 可以收发多个 VLAN 的数据包,不过前提是要创建 VLAN 的 sub-interface。比如希望 ens38同时支持 VLAN10 和 VLAN20,则需创建 sub-interface ens38.10 和 ens38.20。
在交换机上,如果某个 port 只能收发单个 VLAN 的数据,该 port 为 Access 模式,如果支持多 VLAN,则为 Trunk 模式,所以接下来实验的前提是:ens38 要接在交换机的 trunk 口上。不过我们用的是 VirtualBox 虚拟机,则不需要额外配置了。
下面演示如何在 ens38.10 和 ens38.20 上创建 macvlan 网络。 首先编辑 host1 和 host2 的 /etc/network/interfaces,配置 sub-
root@host1:~# cat /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
ethernets:
ens33:
addresses:
- 10.0.0.21/24
gateway4: 10.0.0.254
nameservers:
addresses:
- 223.5.5.5
auto ens38:
iface ens38 inet manual:
auto ens38.10:
iface ens38.10 inet manual:
vlan-raw-device ens38:
auto enp0s9.20:
iface ens38.20 inet manual:
vlan-raw-device ens38:
version: 2
root@host1:~#
然后启用 sub-interface:
ifconfig ens38 up
ifconfig ens38 up
另外方法:
使用 vconfig 命令在 eth0 配置两个 VLAN
vconfig add ens38 100
vconfig add ens38 200
# 设置 VLAN 的 REORDER_HDR 参数,默认就行了
vconfig set_flag ens38.100 1 1
vconfig set_flag ens38.200 1 1
# 启用接口
ifconfig ens38.100 up
ifconfig ens38.200 up
分别在 host1 和 host2 上基于两个 VLAN 子接口创建 2 个 macvlan 网络,mac10 和 mac20。
docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens38.100 mac10
docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=ens38.200 mac20
3 分别在 host1 和 host2 上运行容器,并指定不同的 macvlan 网络。
# host1
docker run -itd --name d1 --ip=172.16.10.10 --network mac10 busybox
docker run -itd --name d2 --ip=172.16.20.10 --network mac20 busybox
# host2
docker run -itd --name d3 --ip=172.16.10.11 --network mac10 busybox
docker run -itd --name d4 --ip=172.16.20.11 --network mac20 busybox
创建 macvlan 网络:
docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens38.10 mac_net10
docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=ens38.20 mac_net20
在 host1 中运行容器:
docker run -itd --name bbox01 --ip=172.16.10.10 --network mac_net10 busybox
docker run -itd --name bbox02 --ip=172.16.20.10 --network mac_net20 busybox
在 host2 中运行容器:
docker run -itd --name bbox03 --ip=172.16.10.11 --network mac_net10 busybox
docker run -itd --name bbox04 --ip=172.16.20.11 --network mac_net20 busybox
当前网络结构如图所示(红框内部分):