![告别单机自嗨:从Docker容器跨主机通信需求到Overlay/Macvlan/IPvlan网络原理与实战](https://picx.zhimg.com/v2-eefe36d6bb45774752a001933b6d47dd_720w.jpg?source=7e7ef6e2&needBackground=1) 写 Docker 的朋友大概都经历过一个阶段:在单机上玩得飞起 docker run 用得滚瓜烂熟。但当业务扩展,需要两台服务器上的容器直接“对话”时,问题就来了。 默认的 bridge 网络只能管自家一亩三分地,跨主机通信怎么办?难道只能靠繁琐的端口映射和复杂的 iptables 转发? 当然不是。Docker 早已为我们准备了三把利剑:**Overlay、Macvlan 和 IPvlan**。 ![](https://pic4.zhimg.com/v2-f1f9bcba5f60142a4d23fc5ff9d11601_1440w.jpg) Docker官网的几种网络模式 今天这篇文章,我们就从原理到实战,彻底把这三者讲清楚,顺便带你避开那些文档里不常说的“坑”。 ## 一、 为什么我们需要跨主机通信? 在默认的 bridge 模式下,Docker 容器通过 NAT(网络地址转换)访问外部。外部要访问容器,必须通过**端口映射**。 **痛点很明显:** 1. **端口管理地狱**:几十个微服务,端口号记不住,还容易冲突。 2. **性能损耗**:NAT 转换在大流量下是 CPU 杀手。 3. **IP 不可见**:容器没有真实局域网 IP,传统的监控、服务发现工具无法直接通过 IP 管理容器。 我们想要的是:**容器像虚拟机一样,拥有局域网内的独立 IP,不仅跨主机能通,还能和物理机直接互联。** ## 二、 方案一:Overlay 网络 (Docker Swarm 的默认选择) 如果你用过 Docker Swarm 或 K8s (Flannel/Calico),对 Overlay 应该不陌生。 ### 1. 原理核心:VXLAN 隧道 Overlay 网络是在现有的物理网络(Underlay)之上,构建了一个虚拟网络。 - **封装**:当主机 A 的容器发包给主机 B 的容器时,Docker 会把原始数据包封装在一个 **VXLAN** 包(UDP 4789端口)里。 - **传输**:这个 UDP 包像普通数据一样在物理网络传输。 - **解封**:到达主机 B 后,Docker 拆开 UDP 包,拿出原始数据,塞给目标容器。 > **通俗理解:** 就像寄快递。原本的信件(容器数据)被装进了一个快递盒(VXLAN 封装),快递员(物理网络)只看快递单(物理 IP),不管盒子里装啥。到了目的地,拆盒取信。 ### 2. 实战测试 Overlay 需要依赖键值存储(KV Store)来同步网络信息,最简单的办法是使用 Docker Swarm 模式(无需安装额外组件),早期的Docker版本(17.03前)配置中也可使用外部组件如consul、etcd等同步信息 **环境准备:** - Node 1 (Manager): 172.21.14.5 - Node 2 (Worker): 172.21.14.6 - Docker环境 (我的 Docker version 26.1.5+dfsg1, build a72d7cd , 带docker swarm) **核心端口要求(Swarm 集群必需)** - 2377/tcp:Swarm 集群管理通信 - 7946/tcp/udp:节点间通信(覆盖网络发现) - 4789/udp:Overlay 网络数据传输(VXLAN) **Step 1: 初始化 Swarm (node1) , 加入Swarm集群(node2)** ```bash # node1上 Manager docker swarm init --advertise-addr 172.21.14.5 # 执行后会给出一个 token 命令,复制该命令到 Node 2 执行即可加入集群 ,也会打开了相应的端口 # node2上 Worker docker swarm join --token SWMTKN-1-028glf3487mka3134oot1z2rxfmbisqj7jaqan9gayvmwjjcpl-e5hpu73a6fvegdm5xi10otl15 172.21.14.5:2377 # node1上 Manager docker node ls ``` ![](https://pic1.zhimg.com/v2-59ba97cb96361a6c46af0029ca63f72c_1440w.jpg) 运行docker swarm init后 ![](https://pica.zhimg.com/v2-34859839513e3375415c4abc69802a34_1440w.jpg) 执行完后已查看到一个节点 ![](https://picx.zhimg.com/v2-b698ec0159d26498f7f39cb6d04ce63f_1440w.jpg) 加入docker ![](https://picx.zhimg.com/v2-c0ae0065a07cc2e3e4935c29ea996029_1440w.jpg) 已经有两个节点了 **Step 2: 创建 Overlay 网络,**Swarm 会自动同步到node2 工作节点 ```bash docker network create -d overlay --attachable my-overlay ``` _注意:加上 **--attachable** 才能让独立的容器(非 Swarm Service)也能使用这个网络。_ **Step 3: 跨主机验证** 在 Node 1 运行容器: ```bash docker run -itd --name app1 --network my-overlay alpine ``` 在 Node 2 运行容器: ```bash docker run -itd --name app2 --network my-overlay alpine ``` 进入 Node 1 的容器 ping Node 2 的容器: ```bash docker exec -it app1 ping app2 ``` ![](https://pic1.zhimg.com/v2-00c4ac7c4463f1e36fc165d196314eda_1440w.jpg) node1容器 ![](https://pic1.zhimg.com/v2-3a0ac1d182753fec0099de20ba5ee188_1440w.jpg) node2容器测试 **结果:** 跨主机 Ping 通!且支持 DNS 解析(直接 Ping 容器名)。 **Step 4: 查看验证通信原理(vxlan)** ```bash # 通过查看详情检查是vxlan docker network inspect my-overlay # 主机tcpdump抓包通信过程,之前说到的4789端口 tcpdump -i eth0 port 4789 -c 10 -nn ``` ![](https://picx.zhimg.com/v2-e3ea10f2df584fb374ad248f9a49c713_1440w.jpg) docker network inspect查看 ![](https://pic3.zhimg.com/v2-2ec4fd0f06f39ad6b1cb5c10bee3b756_1440w.jpg) tcpdump 抓取vxlan 4789端口数据包 **Step 5: 使用service进行验证** ```bash # node1上创建service1 并进行验证,并调度到node1节点 docker service create --name service1 --network my-overlay --replicas 3 --constraint node.hostname==iZt4n4moivyl2vcl14obxcZ nginx:alpine # 查看service docker service ls # 查看容器 docker ps # node1上创建service2 并进行验证,并调度到node2节点 docker service create --name service2 --network my-overlay --replicas 3 --constraint node.hostname==iZt4n4moivyl2vcl14obxdZ nginx:alpine # 查看service docker service ls # 在node2上查看容器,看调度情况 docker ps ``` ![](https://pica.zhimg.com/v2-b6d3f42491d7df07f2c77f65fb5ea3ac_1440w.jpg) 创建两个service进行验证 ![](https://pic3.zhimg.com/v2-9fa4a6fef3215aa96e6abc072985e22c_1440w.jpg) 在node1上验证service2的连通性和nginx服务 ## 三、 方案二:Macvlan (性能之王) 在验证了overlay后,看到官方还有IPvlan 、Macvlan,也想着来验证下。(**云服务器测试可能不通**) ![](https://pica.zhimg.com/v2-ac1b5cc4126b4ae8a456c6c37542086c_1440w.jpg) 官方network Overlay 虽然方便,但 VXLAN 封包解包有 CPU 损耗。如果你的应用对网络延迟极度敏感(如高频交易、VoIP),Macvlan 是更好的选择。 ### 1. 原理核心:子接口与独立 MAC Macvlan 允许你在物理网卡(如 eth0)上创建多个“子接口”,每个子接口都有**独立的 MAC 地址**和 IP 地址。 - 从交换机来看,你的服务器仿佛变身成了接了 N 台设备的“交换机”。 - 容器直接通过 Layer 2(数据链路层)通信,**无需 NAT,性能几乎等同于物理机。** ### 2. 实战测试 **前提:** 你的物理网卡需要支持(大部分都支持),且交换机开启混杂模式(Promiscuous Mode,如果在 VMware 虚拟机里测试,记得在 vSwitch 安全设置里开启“混杂模式”)。 **Step 1: 创建 Macvlan 网络 (两台主机都要执行)** 假设物理网段是 △192.168.1.0/24△,网关 △192.168.1.1△,我们划出一部分 IP 给容器用。 ```bash # 创建macvlan网络 docker network create -d macvlan \ --subnet=172.18.200.0/24 \ --gateway=172.18.200.254 \ -o parent=enp3s0 macvlan-net 9460256b68801cf46f5c21dff59c7a79d9a757010c5d6cc0414e5a1474d5433b ``` **Step 2: 运行容器** ```bash # 创建一个172.18.200.222的容器 docker run -d --name app \ --network macvlan-net \ --ip=172.18.200.222 \ nginx:1.23-alpine ``` ![](https://pic4.zhimg.com/v2-7f88d586e6763a7eb249e1679defcb9d_1440w.jpg) 运行macvlan网络和容器 **Step 3: 验证** 容器互 Ping、容器 Ping 外部物理机均可通, **这个过程可能需要一点儿时间。** ![](https://pic3.zhimg.com/v2-4e5497fb3d84c34899cfee3bcd5d4822_1440w.jpg) 局域网访问macvlan ip ![](https://picx.zhimg.com/v2-e5b98fc46c8e3040730ae135666d34e1_1440w.jpg) 在物理机上进行验证 ## 四、 方案三:IPvlan (云环境救星) Macvlan 有个缺点:每个容器都要一个新的 MAC 地址。很多公有云厂商(AWS, 阿里云等)的虚拟交换机有限制,如果不认识这个 MAC 地址,直接丢弃数据包。这就导致 Macvlan 在云上往往跑不通。 **IPvlan** 应运而生。 ### 1. 原理核心:共享 MAC IPvlan 也有 L2 和 L3 两种模式,最常用的是 L2。 - 所有容器**共享宿主机物理网卡的 MAC 地址**。 - 虽然 MAC 一样,但 IP 不同,Linux 内核根据 IP 地址进行流量分发。 ### 2. 实战测试 (L2 模式) 该命令需要 Linux 内核 >= 4.2。 **Step 1: 创建 IPvlan 网络** 语法几乎和 Macvlan 一模一样,只是驱动变了。我仍然在 ```bash # 创建一个ipvlan网络,创建之前要先删除之前的Macvlan(因为网络相同冲突了) docker network create -d ipvlan \ --subnet=172.18.200.0/24 \ --gateway=172.18.200.254 \ -o parent=enp3s0 \ -o ipvlan_mode=l2 \ ipvlan-net ``` **Step 2: 运行与验证** ```bash # 运行一个ipvlan-net 容器 docker run -d --name app \ --network ipvlan-net \ --ip=172.18.200.222 nginx:1.23-alpine ``` ![](https://pic1.zhimg.com/v2-343d8abb88b1e9cc63e2f6aac44bbbba_1440w.jpg) 本机验证ip及网络 ## 五、 总结:我该选哪个? 为了方便大家决策,我做了一张对比表: |特性|Overlay|Macvlan|IPvlan (L2)| |---|---|---|---| |应用场景|容器编排 (Swarm/K8s)|传统应用迁移、高性能需求|公有云环境、MAC受限环境| |配置难度|简单 (Swarm原生)|中等 (需规划网段)|中等| |性能|有损耗 (VXLAN封装)|极高 (接近物理机)|极高| |网络层级|纯虚拟网络|物理网络二层打通|物理网络二层打通| |MAC地址|虚拟 MAC|每个容器独立 MAC|共享宿主机 MAC| |最大缺点|只有 Docker 内部互通|容易耗尽交换机 MAC 表|旧内核不支持| **极简决策树:** 1. 如果在云服务器上跑,且不能申请辅助网卡 -> 选 **Overlay**。 2. 如果是自建机房,追求极致性能 -> 选 **Macvlan**。 3. 如果是自建机房,但交换机限制了 MAC 地址数量 -> 选 **IPvlan**。 **最后一步:** 看完原理和实验,建议你找两台虚拟机(VirtualBox 或 VMWare),按照文章里的命令敲一遍。网络这东西,**纸上得来终觉浅,绝知此事要 Ping 通!**