18、docker-macvlan-2-示例

MAC VLAN

本章要点:macvlan(vepa、brigdge) 操作示例

来源: 豆包ai,Docker 三种网络驱动,接上章

macvlan模式

vepa模式

VEPA 模式下的 macvlan 设备无法直接互传数据,但可通过物理网卡外发,并借助 hairpin 设备回传以实现内部 VM 通信,该模式需特殊设备支持,创建时需指定macvlan_mode=vepa。

  • 示例

    • 建立vepa网络

      bash 复制代码
      [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 create Docker 命令,用于创建新的网络
      -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 网络名称
    • 运行容器

      bash 复制代码
      [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 子接口的场景。

bash 复制代码
# 混杂模式命令
[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 本地隔离问题)

关键注意事项:

  1. 步骤 3 中 parent=ens192 需替换为实际物理网卡名(可通过 ip link 查看)。
  2. 若步骤 6/7 通信失败,优先检查交换机是否允许 "同一端口多 MAC 地址",或临时开启宿主网卡混杂模式(sudo ip link set ens192 promisc on)测试。
  3. 容器与宿主默认无法直接通信,步骤 9 为可选解决方案。

Macvlan 跨主机容器通信的核心问题通常不在 "内核是否开启"(现代内核默认支持 Macvlan 模块),而在于 物理交换机是否允许多 MAC 地址通过 以及 主机网络转发是否正常。优先排查交换机配置和转发参数,必要时开启网卡混杂模式临时验证,再针对性解决网络环境限制即可。

相关推荐
一个天蝎座 白勺 程序猿5 小时前
KingbaseES数据库归档重做日志文件管理:从配置到运维的实战指南
运维·数据库·oracle·kingbasees·金仓数据库
分布式存储与RustFS9 小时前
镜像仓库的层别堆本地盘:用 RustFS 给 Docker Registry 当 S3 后端
运维·云原生·开源·对象存储·分布式存储·s3·性能基准
陈希12310 小时前
Linux 防火墙配置实战:firewalld、iptables 与云安全组
linux·运维·服务器
@兽血沸腾11 小时前
Windows系统安装Jenkins部署应用至远程Windows服务器操作指南
运维·服务器·jenkins
闲云自留地16 小时前
K8s 的记忆大脑!ETCD 集群部署、etcdctl 命令与备份恢复全通关
容器·kubernetes·etcd
讯捷蓝达16 小时前
戴尔R720xd服务器卡死在 “Configuring Memory...Done“,换了内存还是卡?问题根本不在内存
运维·服务器
爱和冰阔落19 小时前
【Linux网络】TCP 服务器如何并发处理多个客户端?从 fork、僵尸进程到双重 fork
linux·运维·服务器·网络
lisanmengmeng19 小时前
alertmanger 标签 rules 打上分组标签
linux·运维·服务器
Android系统攻城狮20 小时前
Linux FFmpeg深度解析之av_write_frame调用流程与实战(三十三)
linux·运维·服务器·ffmpeg·音视频进阶·ffmpeg音视频
上火的金鱼妹20 小时前
k8s生产实际问题排查(网关,数据库读写等)
运维·服务器