vault backup: 2026-11-07 16:33:44

This commit is contained in:
cheney
2026-11-07 16:33:55 +08:00
commit 7015312702
1208 changed files with 132432 additions and 0 deletions
@@ -0,0 +1,300 @@
![告别单机自嗨:从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 通!**