docker(7、容器网络3) macvlan 网络 不支持DNS服务

macvlan 本身是 linux kernel 模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP。

macvlan 本质上是一种网卡虚拟化技术,Docker 用 macvlan 实现容器网络。

macvlan 的最大优点是性能极好,相比其他实现,macvlan 不需要创建 Linux bridge,而是直接通过以太 interface 连接到物理网络。

1、准备实验环境

创建一个 macvlan 网络。

使用 host1 和 host2 上再添加单独的网卡 ens37 创建 macvlan

为保证多个 MAC 地址的网络包都可以从 ens192 通过,需要打开网卡的混杂模式。

ip link set ens37 promisc on

ip link show ens37

确保 ens37 状态 UP 并且 promisc 模式已经生效。

 如果 host1 和 host2 是 vwmare 虚拟机,还需要在网卡配置选项页中设置混杂模式

2、创建 macvlan 网络

在 host1 和 host2 中创建 macvlan 网络 mac_net1:

docker network create -d macvlan --subnet=172.16.86.0/24 --gateway=172.16.86.1 -o parent=ens37 mac_net1

 

注意:在 host2 中也要执行相同的命令。

1) -d macvlan 指定 driver 为 macvlan。

2) macvlan 网络是 local 网络,为了保证跨主机能够通信,用户需要自己管理 IP subnet。

3) 与其他网络不同,docker 不会为 macvlan 创建网关,这里的网关应该是真实存在的,否则容器无法路由。

4) -o parent 指定使用的网络 interface。

在 host1 中运行容器 bbox1 并连接到 mac_net1。

由于 host1 中的 mac_net1 与 host2 中的 mac_net1 本质上是独立的,为了避免自动分配造成 IP 冲突,我们最好通过 --ip 指定 bbox1 地址为 172.16.86.10。

docker run -itd --name bbox1 --ip=172.16.86.10 --network mac_net1 busybox 

在 host2 中运行容器 bbox2,指定 IP 172.16.86.11。

docker run -itd --name  bbox2 --ip=172.16.86.11 --network mac_net1 busybox

验证 bbox1 和 bbox1 的连通性。

bbox2 能够 ping 到 bbox1 的 IP 172.16.86.10,但无法解析 “bbox1” 主机名。

可见 docker 没有为 macvlan 提供 DNS 服务,这点与 overlay 网络是不同的。

3、macvlan 网络结构分析

macvlan 不依赖 Linux bridge,brctl show 可以确认没有创建新的 bridge。 docker——gwbridge 是overlay网络生成的,不是本环境的

查看一下容器 bbox1 的网络设备:

除了 lo,容器只有一个 eth0,请注意 eth0 后面的 @if16,这表明该 interface 有一个对应的 interface,其全局的编号为 16。

根据 macvlan 的原理,我们有理由猜测这个 interface 就是主机的 ens37,确认如下:

由此可见,容器的 eth0 就是 ens37 通过 macvlan 虚拟出来的 interface。

容器的 interface 直接与主机的网卡连接,这种方案使得容器无需通过 NAT 和端口映射就能与外网直接通信(只要有网关),在网络上与其他独立主机没有区别。

当前网络结构如图所示

4、用 sub-interface 实现多 macvlan 网络(另外的环境的测试网卡是ens192的Ubuntu系统)

macvlan 会独占主机的网卡,也就是说一个网卡只能创建一个 macvlan 网络,否则会报错:

但主机的网卡数量是有限的,如何支持更多的 macvlan 网络呢?

好在 macvlan 不仅可以连接到 interface(如 ens192),也可以连接到 sub-interface(如 ens192.xxx)。

VLAN 是现代网络常用的网络虚拟化技术,它可以将物理的二层网络划分成多达 4094 个逻辑网络,这些逻辑网络在二层上是隔离的,每个逻辑网络(即 VLAN)由 VLAN ID 区分,VLAN ID 的取值为 1-4094。

Linux 的网卡也能支持 VLAN(apt-get install vlan),同一个 interface 可以收发多个 VLAN 的数据包,不过前提是要创建 VLAN 的 sub-interface。

比如希望 ens192 同时支持 VLAN10 和 VLAN20,则需创建 sub-interface ens192.10 和 ens192.20。

在交换机上,如果某个 port 只能收发单个 VLAN 的数据,该 port 为 Access 模式,如果支持多 VLAN,则为 Trunk 模式,所以接下来实验的前提是:

ens192 要接在交换机的 trunk 口上。如果是虚拟机,则不需要额外配置了。

在 ens192.10 和 ens192.20 上创建 macvlan 网络。

首先编辑 host1 和 host2 的 /etc/network/interfaces,配置 sub-interfaces:

然后启用 sub-interface:

创建 macvlan 网络:

host1上:

docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1 -o parent=ens192.10 mac_net10

docker network create -d macvlan --subnet=172.16.20.0/24 --gateway=172.16.20.1 -o parent=ens192.20 mac_net20

host2上用同样方法创建macvlan网络。

在 host1 中运行容器:

 

在 host2 中运行容器:

 

当前网络结构如图所示:

5、macvlan 网络隔离和连通

验证 macvlan 之间的连通性。

bbox1 能 ping 通 bbox3,bbox2 能 ping 通 bbox4。

即:同一 macvlan 网络能通信。

bbox1 无法 ping 通 bbox2 和 bbox4。

即:不同 macvlan 网络之间不能通信。

但更准确的说法应该是:不同 macvlan 网络不能 在二层上 通信。

在三层上可以通过网关将 macvlan 连通,下面我们就启用网关。

将 额外的doceker-machine配置成一个虚拟路由器,设置网关并转发 VLAN10 和 VLAN20 的流量。

当然也可以使用物理路由器达到同样的效果。首先确保操作系统 IP Forwarding 已经启用。

输出为 1 则表示启用,如果为 0 可通过如下命令启用:

sysctl -w net.ipv4.ip_forward=1

在 /etc/network/interfaces 中配置 vlan sub-interface:

启用 sub-interface:

ifup ens192.10

ifup ens192.20

将网关 IP 配置到 sub-interface:

[root@ubuntu ~]$ifconfig ens192.10 172.16.10.1 netmask 255.255.255.0 up

[root@ubuntu ~]$ifconfig ens192.20 172.16.20.1 netmask 255.255.255.0 up

添加 iptables 规则,转发不同 VLAN 的数据包。

iptables -t nat -A POSTROUTING -o ens192.10 -j MASQUERADE

iptables -t nat -A POSTROUTING -o ens192.20 -j MASQUERADE

iptables -A FORWARD -i ens192.10 -o ens192.20 -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A FORWARD -i ens192.20 -o ens192.10 -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A FORWARD -i ens192.10 -o ens192.20 -j ACCEPT

iptables -A FORWARD -i ens192.20 -o ens192.10 -j ACCEPT

当前网络拓扑如下图所示:

现在 host1 上位于 mac_net10 的 bbox1 已经可以与 host2 上位于 mac_net20 的 bbox4 通信了。

下面我们分析数据包是如何从 bbox1(172.16.10.10)到达 bbox4(172.16.20.11)的。整个过程如下图所示:

1) 因为 bbox1 与 bbox4 在不同的 IP 网段,跟据 bbox1 的路由表:

数据包将发送到网关 172.16.10.1。

2) 路由器从 ens192.10 收到数据包,发现目的地址是 172.16.20.11,查看自己的路由表:

于是将数据包从 ens192.20 转发出去。

3) 通过 ARP 记录的信息,路由器能够得知 172.16.20.11 在 host2 上,于是将数据包发送给 host2。

4) host2 根据目的地址和 VLAN 信息将数据包发送给 bbox4。

macvlan 网络的连通和隔离完全依赖 VLAN、IP subnet 和路由,docker 本身不做任何限制,用户可以像管理传统 VLAN 网络那样管理 macvlan。

发布了62 篇原创文章 · 获赞 10 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/cojn52/article/details/104688173