在Docker中创建macvlan网络

LonelyMan 777 2022-11-10

概念

使用macvlan网络模式的Docker容器,可以看作是局域网内的一个独立设备,它会有一个独立的内网IP。每个macvlan下的Docker容器,都有自己一套完整的端口可用,不会互相冲突。

macvlan最大的优点就是可以和宿主机配置为不同网关,方便网络分流。

创建

前置配置

# 开启网卡混杂模式
ip link set ens192 promisc on

IPv4

docker network create -d macvlan --subnet=10.0.0.0/24 --gateway=10.0.0.1 -o parent=ens192 mac_net

IPv4 & IPv6 双栈

docker network create -d macvlan --subnet=10.0.0.0/24 --gateway=10.0.0.1 --ipv6 --subnet=fd00::/60 --gateway=fd00::1  -o parent=ens192 mac_net

docker network create -d macvlan:指定创建的网络类型是macvlan
--subnet=10.0.0.0/24macvlan的IPv4网段
--gateway=10.0.0.1macvlan的IPv4网关
--ipv6:启用IPv6支持
--subnet=fd00::/60macvlan的IPv6前缀
--gateway=fd00::1macvlan的IPv6网关
-o parent=ens192:桥接网络走的接口名称
mac_net:需要创建的macvlan网络名称

问题

macvlan网络下不能与宿主机通讯问题

原因

一般在macvlan模式下同网段的其他机器可以和容器互通,但宿主不能和容器互通,这是在macvlan模式设计的时候为了安全而禁止了宿主机和容器直接通信。

如果想要实现互通,有个曲线救国的方法,就是macvlanmacvlan之间可以互通,只需要在宿主机再创建一个macvlan网络,然后修改路由,让数据经过这个macvlan达到互通的目的。

实现

假设当前网段为10.0.0.0/24

名字 IP 接口
宿主机 10.0.0.10 ens192
macvlan容器 10.0.0.11 mac_net

输入以下命令,在宿主机上新建一个macvlan虚拟接口

# 创建一个名为macvlan_host的macvlan虚拟接口,并桥接到ens192物理接口上
ip link add macvlan_host link ens192 type macvlan mode bridge
# 为macvlan_host接口添加一个10.0.0.15的IP
ip addr add 10.0.0.15 dev macvlan_host
# 开启macvlan_host接口
ip link set macvlan_host up
# 新增路由,使到macvlan容器的数据包由macvlan_host发出
ip route add 10.0.0.11 dev macvlan_host

macvlan容器与宿主机在同一网段的情况下,macvlan_host不需要配置IP

验证

宿主机通过10.0.0.11访问macvlan容器
macvlan容器通过10.0.0.15访问宿主机

总结

mavlan虚拟出来的网口不能和父网口直通,但是可以和同一子网的其他网口互通(包括其他虚拟出来的网口)。
通过在宿主机上用macvlan添加一个虚拟网口macvlan_host,并在宿主机上配置路由『到容器的数据包由macvlan_host发出』,就架起了宿主机与容器的通信桥梁。
宿主机发往容器的数据包,由macvlan_host发给容器;容器发往宿主机的数据包先发给macvlan_host,再由macvlan_host转交给 ens192(宿主机)。

参考