18、docker-macvlan-2-示例
MAC VLAN
本章要点:macvlan(vepa、brigdge) 操作示例
来源: 豆包ai,Docker 三种网络驱动,接上章
macvlan模式
vepa模式
VEPA 模式下的 macvlan 设备无法直接互传数据,但可通过物理网卡外发,并借助 hairpin 设备回传以实现内部 VM 通信,该模式需特殊设备支持,创建时需指定macvlan_mode=vepa。
-
示例
-
建立vepa网络
[root@node139 ~]# docker network create -d macvlan --subnet=10.4.50.0/24 --gateway=10.4.50.1 -o parent=ens192 -o macvlan_mode=vepa vepamv 4e3ac6f33ceb6831b85c02fc9904fc91428300e459eecc209a3013f24ce88819[root@node139 ~]# docker network ls 44456c8796de vepamv macvlan local <-- 此时为macvlan的vepa网络[root@node139 ~]# docker network inspect vepamv [{"Name": "vepamv","Id": "4e3ac6f33ceb6831b85c02fc9904fc91428300e459eecc209a3013f24ce88819","Created": "2025-11-04T19:17:48.209274115+08:00","Scope": "local","Driver": "macvlan","EnableIPv6": false,"IPAM": {"Driver": "default","Options": {},"Config": [{"Subnet": "10.4.50.0/24","Gateway": "10.4.50.1"}]},"Internal": false,"Attachable": false,"Ingress": false,"ConfigFrom": {"Network": ""},"ConfigOnly": false,"Containers": {},"Options": {"macvlan_mode": "vepa","parent": "ens192"},"Labels": {}} ]参数 / 选项 说明 docker network createDocker 命令,用于创建新的网络 -d macvlan指定网络驱动为 macvlan(基于 MAC 地址的虚拟网络驱动)--subnet=10.4.50.0/24定义网络的子网网段,容器将从该网段分配 IP 地址(如 10.4.50.0-254) --gateway=10.4.50.1指定网络的网关地址,容器访问外部网络时通过该网关转发 -o parent=ens192通过 -o设置驱动选项,指定物理网卡为ens192(macvlan 基于此网卡创建虚拟接口)-o macvlan_mode=vepa指定 macvlan 的模式为 vepa(需依赖物理网卡或 hairpin 设备实现容器间间接通信)vepamv新创建的 macvlan 网络名称 -
运行容器
[root@node139 ~]# docker pull docker.gh-proxy.com/busybox [root@node139 ~]# docker tag docker.gh-proxy.com/busybox:latest busybox:latest# 创建两台虚拟机 [root@node139 ~]# docker run -itd --net=vepamv --ip=10.4.50.91 --name=vepa1 busybox /bin/sh fddcf6e15995bcee9a5e9d5022f188daab72e19d75ad62220c44516e25849d24 [root@node139 ~]# docker run -itd --net=vepamv --ip=10.4.50.92 --name=vepa2 busybox /bin/sh c8a32c79593970376a45420f9c85005415fb62d32b35a51622fd6dc84d4ca363# vepa2 ping vepa1 不通这是正常的 [root@node139 ~]# docker exec -it vepa2 ping vepa1 PING vepa1 (10.4.50.91): 56 data bytes ^C --- vepa1 ping statistics --- 2 packets transmitted, 0 packets received, 100% packet loss# 宿主机也不通, [root@node139 ~]# ping 10.4.50.91 PING 10.4.50.91 (10.4.50.91) 56(84) bytes of data. From 10.4.50.139 icmp_seq=1 Destination Host Unreachable -
现象分析
项目 具体说明 现象 宿主机与同一网段的 macvlan VEPA 模式容器无法 ping 通(即使 IP 网段相同) 核心原因 1 内核隔离机制:macvlan 虚拟网卡与宿主机物理网卡在数据链路层(L2)隔离,宿主机内核会直接丢弃来自 macvlan 设备的数据包,不处理也不回应 核心原因 2 VEPA 模式限制:其 hairpin 转发逻辑仅适用于同一物理网卡下的 macvlan 设备之间,不包含宿主机与容器的通信场景 验证配置的方向 1. 宿主机物理网卡是否配置同网段 IP(如 ip addr show ens192检查)2. 物理交换机是否开启 hairpin 功能(仅影响 macvlan 设备间通信)3. 容器 IP / 网关是否正确(如docker exec 容器名 ip addr检查)4. 关闭防火墙排除规则拦截(如ufw disable或停止 firewalld)结论 macvlan 设计上就不支持宿主机与容器直接通信,无论是否同网段、是否 VEPA 模式,这是其 “虚拟独立网卡” 特性的体现。若必须实现互通,只能通过外部设备(如支持 hairpin 的交换机 + 宿主机物理网卡配置)或额外网络层(如网桥、路由转发)间接绕开隔离,而非依赖 macvlan 本身的功能。
-
passthru 模式
这种模式,只允许单个子接口连接主接口,且必须设置成混杂模式,一般用于子接口桥接和创建 VLAN 子接口的场景。
# 混杂模式命令
[root@docker-02 ~]# ip link set ens192 promisc on
private 模式
隔离功能比VPEA更强,阻断了广播和组播,即使交换机开启 hairpin 也无法通信。
bridge 模式
在 macvlan 的 bridge 模式 下,寄生在同一物理设备的多个 macvlan 虚拟网卡(设备)可以直接通信,无需依赖外部的 hairpin 设备转发,这是其与 VEPA 模式的核心区别。
macvlan 的 bridge 模式 网卡需要跟物理网卡同一网段么?
-
macvlan 的 bridge 模式中,macvlan 虚拟网卡(如容器网卡)的 IP 建议与物理网卡在同一网段,原因如下:
-
直接通信的前提
- 同一物理网卡下的 macvlan 设备(如容器)要直接通信,需处于同一网段(IP 地址和子网掩码匹配),否则内核无法直接识别为 “内部设备”,可能需要网关转发,失去 bridge 模式本地直连的优势。
-
与外部网络交互
- 若 macvlan 设备需要访问物理网卡所在的外部网络(如其他主机、网关),必须与物理网卡在同一网段,否则无法通过物理网卡正常收发数据(类似物理机在同一局域网的要求)。
-
简单说:建议同网段,这样既能保证 macvlan 设备间直接通信,也能正常访问外部网络。
-
-
与 VEPA 模式的关键对比
场景 VEPA 模式 bridge 模式 同一物理网卡下的 macvlan 设备通信 需外部交换机支持 hairpin 回传 内核直接转发,无需外部设备 转发路径 物理网卡 → 外部交换机 → 目标设备 宿主机内核内部直接转发 -
相同 macvlan 网络之间的通信原理
步骤序号 操作对象 操作命令 / 配置 说明 1 环境确认 检查物理网络:两台主机接入同一交换机,同属 192.168.100.0/24网段Node A 物理 IP:192.168.100.10(网卡ens192)Node B 物理 IP:192.168.100.11(网卡ens192)网关:192.168.100.1(路由器 / 交换机)确保物理网络基础一致,交换机需关闭 “端口安全”(允许多 MAC 地址通过) 2 Node A + Node B 检查 Docker 版本: docker --version(建议 20.10+)检查内核 Macvlan 支持:modprobe macvlan && echo "supported"现代 Linux 内核(3.9+)默认支持 Macvlan,无需额外安装模块 3 Node A + Node B 创建 Macvlan 网络: bash<br>docker network create -d macvlan \<br> --subnet=192.168.100.0/24 \<br> --gateway=192.168.100.1 \<br> -o parent=ens192 \<br> -o macvlan_mode=bridge \<br> macvlan_bridge<br>两台主机需创建完全相同的网络(子网、网关、物理网卡绑定一致) 4 Node A 启动容器并指定 IP: bash<br>docker run -itd \<br> --name macvlan-nodea \<br> --network macvlan_bridge \<br> --ip=192.168.100.20 \<br> alpine:latest \<br> sh<br>容器 IP 需在 192.168.100.0/24内,且不与物理设备冲突5 Node B 启动容器并指定 IP: bash<br>docker run -itd \<br> --name macvlan-nodeb \<br> --network macvlan_bridge \<br> --ip=192.168.100.21 \<br> alpine:latest \<br> sh<br>与 Node A 容器同子网,IP 唯一(如 192.168.100.21)6 Node A 容器 验证跨主机通信: bash<br># 进入容器<br>docker exec -it macvlan-nodea sh<br># ping Node B 容器<br>ping 192.168.100.21<br>若 ping 通,说明跨主机容器通信正常 7 Node B 容器 验证反向通信: bash<br># 进入容器<br>docker exec -it macvlan-nodeb sh<br># ping Node A 容器<br>ping 192.168.100.20<br>双向 ping 通可确认网络互通性 8 容器内(可选) 验证外网访问: ping 192.168.100.1(网关)ping 8.8.8.8(公网)确保容器能访问物理网络及外网(依赖网关路由配置) 9 宿主主机(可选) 开启宿主与容器通信: bash<br># 在 Node A 或 B 执行<br>sudo ip link add macvlan_link link ens192 type macvlan mode bridge<br>sudo ip addr add 192.168.100.100/24 dev macvlan_link<br>sudo ip link set macvlan_link up<br>容器可通过 192.168.100.100访问宿主(解决 Macvlan 本地隔离问题)
关键注意事项:
- 步骤 3 中
parent=ens192需替换为实际物理网卡名(可通过ip link查看)。 - 若步骤 6/7 通信失败,优先检查交换机是否允许 “同一端口多 MAC 地址”,或临时开启宿主网卡混杂模式(
sudo ip link set ens192 promisc on)测试。 - 容器与宿主默认无法直接通信,步骤 9 为可选解决方案。
Macvlan 跨主机容器通信的核心问题通常不在 “内核是否开启”(现代内核默认支持 Macvlan 模块),而在于 物理交换机是否允许多 MAC 地址通过 以及 主机网络转发是否正常。优先排查交换机配置和转发参数,必要时开启网卡混杂模式临时验证,再针对性解决网络环境限制即可。
