如何让 MACvLan 网络下的容器与宿主机互联互通

我在 NAS 上部署了一个 NginxProxyManager 方便管理其他 Self Host 服务的 SSL 证书,为了避免占用宿主机的 80/443 端口,我用了 macvlan 为 NPM 容器分配了一个独立的局域网 IP。

networks:
  macvlan_network:
    driver: macvlan
    driver_opts:
      parent: <your-network-interface>
    ipam:
      config:
        - subnet: 192.168.100.0/24
          gateway: 192.168.100.1

services:
  npm:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    networks:
      macvlan_network:
        ipv4_address: 192.168.100.22
    environment:
      DISABLE_IPV6: 'true'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

这时,局域网其他的设备就可以通过 192.168.100.22 访问 NPM,但是对于宿主机以及宿主机上其他的容器来说,这个地址是无法访问的

在咨询了 GPT 之后,它建议了下面的方案:

[Unit]
Description=Set up specific macvlan route for a Docker container
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
# Replace <your-network-interface> with the actual interface name
ExecStart=/usr/bin/ip link add mvlan0 link <your-network-interface> type macvlan mode bridge
ExecStart=/usr/bin/ip addr add <unused-ip>/24 dev mvlan0
ExecStart=/usr/bin/ip link set mvlan0 up
ExecStart=/usr/bin/ip route del 192.168.100.0/24 dev mvlan0
ExecStart=/usr/bin/ip route add 192.168.100.22 dev mvlan0
ExecStop=/usr/bin/ip link delete mvlan0

[Install]
WantedBy=multi-user.target

默认情况下的问题:

    • 当使用 macvlan/ipvlan 时,Docker 容器会直接连接到物理网络接口
    • 但是宿主机无法通过物理接口直接与这些容器通信,因为物理接口不会处理宿主机到 macvlan 接口的流量

    创建 mvlan0 的作用:

    sudo ip link add mvlan0 link <your-network-interface> type macvlan mode bridge
    sudo ip addr add <unused-ip>/24 dev mvlan0
    sudo ip link set mvlan0 up
    • 这实际上是在宿主机创建了一个新的网络接口 mvlan0
    • 这个接口也是一个 macvlan 接口,与 Docker 容器使用相同的技术
    • mvlan0 接口可以看作是宿主机在 192.168.100.0/24 网段的一个”入口”

    通信流程:

    宿主机 -> mvlan0 (unused-ip) -> 物理网卡 -> Docker 容器 (192.168.100.22)
    • 当宿主机要访问 192.168.100.22 时
    • 数据包会通过 mvlan0 接口发出
    • 由于 mvlan0 和容器的网络接口都是 macvlan 类型,它们可以在同一层次通信

    类比解释:

      • 可以把这个设置想象成宿主机也”加入”到了容器所在的网络
      • mvlan0 就像是宿主机的一个”虚拟网卡”,使它能够与容器在同一个网络层面通信

      为什么需要这样:

        • 这种设置避免了常规的网络栈限制
        • 提供了一个直接的通信路径
        • 保持了网络隔离性的同时又允许必要的通信

        这就是为什么添加这个 macvlan 接口可以让宿主机访问容器的原理。这种方法既保持了容器网络的独立性,又提供了必要的访问路径。

        发表回复

        您的邮箱地址不会被公开。 必填项已用 * 标注