
👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Docker这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!
文章目录
- Docker 容器的跨主机通信实现方案详解 🌐
-
- 🔍 为什么跨主机通信如此复杂?—— 网络本质再思考
- 🧱 方案一:Docker Swarm 内置 Overlay 网络(零依赖、开箱即用)
-
- 📐 网络模型与数据流
- ⚙️ 实践:三步搭建可通信集群
-
- 步骤 1:初始化 Swarm Manager(Host-A)
- 步骤 2:Worker 节点加入(Host-B)
- 步骤 3:创建 Overlay 网络并部署服务
- 💻 Java 示例:Spring Boot 服务调用(容器名直连)
-
- `inventory-service`(提供库存接口)
- `order-service`(调用库存服务)
- Docker Compose 部署(Swarm 模式下生效)
- 🌐 方案二:Flannel —— Kubernetes 生态最轻量的 CNI 插件
-
- 📐 网络模型(Host-GW 模式,极致性能)
- ⚙️ 实践:Kubernetes 集群中启用 Flannel
-
- 步骤 1:安装 Flannel(官方 manifest)
- 步骤 2:验证网络就绪
- 💻 Java 示例:Kubernetes Service 调用(DNS + ClusterIP)
-
- `inventory-service` Deployment + Service
- `order-service` 中调用逻辑(Java)
- 启动参数注入(Deployment 中)
- 🛡️ 方案三:Calico —— 企业级策略驱动网络(BGP + eBPF)
-
- 📐 网络模型(BGP 模式)
- ⚙️ 实践:在 kubeadm 集群部署 Calico
-
- 步骤 1:安装 Calico(Tigera 官方推荐)
- 步骤 2:验证 BGP 连接
- 💻 Java 示例:NetworkPolicy 控制下的安全调用
-
- `network-policy.yaml`
- Java 代码无需修改,策略由 Calico 透明执行:
- 🧩 方案四:Weave Net —— 自动加密、DNS 驱动的开发者友好网络
-
- 📐 网络模型(FastDP 模式)
- ⚙️ 实践:Weave on Docker Standalone(非 Kubernetes)
-
- 步骤 1:在 Host-A 启动 Weave
- 步骤 2:在 Host-B 加入
- 步骤 3:运行容器并验证 DNS
- 💻 Java 示例:Weave DNS 直连(无 Kubernetes 依赖)
- 🧭 方案五:自建 VXLAN 隧道(Linux 原生命令,教学价值高)
-
- 📐 网络模型(手动 VXLAN)
- ⚙️ 实践:手敲命令搭建(Host-A & Host-B)
-
- Host-A 执行:
- Host-B 执行(类似,注意 IP 和 VNI 一致):
- 测试连通性:
- 🌐 方案六:Service Mesh 间接通信(Istio / Linkerd)
-
- 📐 模型示意(Istio)
- 💻 Java 示例:零代码改造
- 🧪 方案对比与选型决策树
-
- 🧭 决策树(简化版):
- 🚀 最佳实践与避坑指南
-
- ✅ 必做事项
- ❌ 经典陷阱
- 🔍 调试黄金命令
- 🌟 结语:通信只是开始,治理才是未来
Docker 容器的跨主机通信实现方案详解 🌐
在现代云原生架构中,Docker 已成为容器化部署的事实标准。然而,单机 Docker(docker run 启动的默认 bridge 网络)天然隔离于宿主机网络,更无法直接与其他物理机或虚拟机上的容器通信。当业务规模扩大、服务需水平扩展、或混合部署(如部分服务在 IDC,部分在公有云)时,“容器如何跨主机互通”便成为绕不开的核心命题 🚧。
本文将系统性地剖析 Docker 跨主机通信的主流实现方案:从底层原理到工程落地,涵盖 Overlay 网络(Docker Swarm 原生)、Flannel、Calico、Weave、自建 VXLAN 隧道、以及基于 Service Mesh 的间接通信路径;每种方案均配以清晰的网络拓扑图(Mermaid 渲染)、可验证的配置步骤、真实可用的 Java 服务代码示例(含 Spring Boot REST API + 容器间 HTTP 调用逻辑),并指出适用场景与关键取舍。所有技术细节均基于当前稳定生态(Docker 24.x / Kubernetes 1.28+ / Spring Boot 3.2+),无过时假设,所有外链均为权威、公开、无需登录即可访问的文档站点 ✅。
🔍 为什么跨主机通信如此复杂?—— 网络本质再思考
Docker 默认使用 bridge 驱动创建 docker0 网桥,为每个容器分配 172.17.0.0/16 内网 IP,并通过 iptables NAT 实现与外部通信。该设计带来两个根本限制:
要让 Host-A 上的 container-A(IP: 10.0.1.5)直接 ping 或 HTTP GET Host-B 上的 container-B(IP: 10.0.2.8),必须在三层(IP 层)之上构建一个逻辑覆盖网络(Overlay Network) —— 即在现有物理网络(underlay)之上,封装一层可跨主机寻址与转发的虚拟网络平面 🌐。
💡 关键共识:跨主机通信 ≠ 端口映射(-p 8080:8080)。后者仅暴露服务端口到宿主机,仍需客户端主动访问宿主机 IP,且无法实现容器 IP 直通、服务发现、策略控制等高级能力。
🧱 方案一:Docker Swarm 内置 Overlay 网络(零依赖、开箱即用)
Docker Engine 自带集群编排能力(Swarm mode),其 overlay 网络驱动基于 VXLAN 封装 + 内置 KV 存储(Gossip 协议),无需额外组件,适合中小规模、对 Kubernetes 无强需求的团队。
📐 网络模型与数据流
#mermaid-svg-y9vsTG4E5Df57dvm{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-y9vsTG4E5Df57dvm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-y9vsTG4E5Df57dvm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-y9vsTG4E5Df57dvm .error-icon{fill:#552222;}#mermaid-svg-y9vsTG4E5Df57dvm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-y9vsTG4E5Df57dvm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-y9vsTG4E5Df57dvm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-y9vsTG4E5Df57dvm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-y9vsTG4E5Df57dvm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-y9vsTG4E5Df57dvm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-y9vsTG4E5Df57dvm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-y9vsTG4E5Df57dvm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-y9vsTG4E5Df57dvm .marker.cross{stroke:#333333;}#mermaid-svg-y9vsTG4E5Df57dvm svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-y9vsTG4E5Df57dvm p{margin:0;}#mermaid-svg-y9vsTG4E5Df57dvm .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-y9vsTG4E5Df57dvm .cluster-label text{fill:#333;}#mermaid-svg-y9vsTG4E5Df57dvm .cluster-label span{color:#333;}#mermaid-svg-y9vsTG4E5Df57dvm .cluster-label span p{background-color:transparent;}#mermaid-svg-y9vsTG4E5Df57dvm .label text,#mermaid-svg-y9vsTG4E5Df57dvm span{fill:#333;color:#333;}#mermaid-svg-y9vsTG4E5Df57dvm .node rect,#mermaid-svg-y9vsTG4E5Df57dvm .node circle,#mermaid-svg-y9vsTG4E5Df57dvm .node ellipse,#mermaid-svg-y9vsTG4E5Df57dvm .node polygon,#mermaid-svg-y9vsTG4E5Df57dvm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-y9vsTG4E5Df57dvm .rough-node .label text,#mermaid-svg-y9vsTG4E5Df57dvm .node .label text,#mermaid-svg-y9vsTG4E5Df57dvm .image-shape .label,#mermaid-svg-y9vsTG4E5Df57dvm .icon-shape .label{text-anchor:middle;}#mermaid-svg-y9vsTG4E5Df57dvm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-y9vsTG4E5Df57dvm .rough-node .label,#mermaid-svg-y9vsTG4E5Df57dvm .node .label,#mermaid-svg-y9vsTG4E5Df57dvm .image-shape .label,#mermaid-svg-y9vsTG4E5Df57dvm .icon-shape .label{text-align:center;}#mermaid-svg-y9vsTG4E5Df57dvm .node.clickable{cursor:pointer;}#mermaid-svg-y9vsTG4E5Df57dvm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-y9vsTG4E5Df57dvm .arrowheadPath{fill:#333333;}#mermaid-svg-y9vsTG4E5Df57dvm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-y9vsTG4E5Df57dvm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-y9vsTG4E5Df57dvm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y9vsTG4E5Df57dvm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-y9vsTG4E5Df57dvm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y9vsTG4E5Df57dvm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-y9vsTG4E5Df57dvm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-y9vsTG4E5Df57dvm .cluster text{fill:#333;}#mermaid-svg-y9vsTG4E5Df57dvm .cluster span{color:#333;}#mermaid-svg-y9vsTG4E5Df57dvm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-y9vsTG4E5Df57dvm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-y9vsTG4E5Df57dvm rect.text{fill:none;stroke-width:0;}#mermaid-svg-y9vsTG4E5Df57dvm .icon-shape,#mermaid-svg-y9vsTG4E5Df57dvm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-y9vsTG4E5Df57dvm .icon-shape p,#mermaid-svg-y9vsTG4E5Df57dvm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-y9vsTG4E5Df57dvm .icon-shape .label rect,#mermaid-svg-y9vsTG4E5Df57dvm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-y9vsTG4E5Df57dvm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-y9vsTG4E5Df57dvm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-y9vsTG4E5Df57dvm :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Host B
Host A
eth0
UDP 8472
IP PacketDst: Host-B IP
eth0
Container-A10.0.1.5
swarm-overlayVXLAN dev: vxlan0
Host-A KernelVXLAN Encap
Physical Network
Host-B KernelVXLAN Decap
swarm-overlayVXLAN dev: vxlan0
Container-B10.0.2.8
- 所有容器接入同一 overlay 网络后,获得 10.0.0.0/16 内连续 IP(由 Swarm 内置分配器管理);
- 数据包经 vxlan0 设备封装为 UDP 报文(目的端口 8472),通过物理网络送达目标主机;
- 目标主机内核解封后,交付至本地容器 —— 对应用完全透明,如同运行在同一台机器上。
⚙️ 实践:三步搭建可通信集群
步骤 1:初始化 Swarm Manager(Host-A)
# 初始化 Swarm,指定 advertise-addr 为 Host-A 可被 Host-B 访问的 IP(如 192.168.1.10)
docker swarm init –advertise-addr 192.168.1.10
# 输出加入命令,类似:
# docker swarm join –token SWMTKN-1-abc… 192.168.1.10:2377
步骤 2:Worker 节点加入(Host-B)
# 在 Host-B 执行上一步输出的 join 命令
docker swarm join –token SWMTKN-1-abc... 192.168.1.10:2377
步骤 3:创建 Overlay 网络并部署服务
# 在 Manager 节点创建 overlay 网络(–attachable 允许独立容器接入)
docker network create -d overlay –attachable my-overlay
# 启动服务 A(自动调度到某节点)
docker service create \\
–name service-a \\
–network my-overlay \\
–publish published=8080,target=8080 \\
nginx:alpine
# 启动服务 B(同网络)
docker service create \\
–name service-b \\
–network my-overlay \\
–publish published=8081,target=8080 \\
nginx:alpine
此时,service-a 容器内可直接 curl http://service-b:8080 —— Swarm 内置 DNS 会解析 service-b 为该服务所有任务(tasks)的 VIP(Virtual IP),流量经 overlay 网络负载均衡 🌟。
💻 Java 示例:Spring Boot 服务调用(容器名直连)
我们编写两个 Spring Boot 应用:order-service(下单)与 inventory-service(库存查询),通过 inventory-service 容器名调用其 /api/stock/{sku} 接口。
inventory-service(提供库存接口)
// InventoryController.java
@RestController
@RequestMapping("/api")
public class InventoryController {
@GetMapping("/stock/{sku}")
public ResponseEntity<Map<String, Object>> getStock(@PathVariable String sku) {
Map<String, Object> response = new HashMap<>();
response.put("sku", sku);
response.put("available", true);
response.put("quantity", 99);
response.put("host", InetAddress.getLoopbackAddress().getHostName()); // 返回容器主机名,用于验证来源
return ResponseEntity.ok(response);
}
}
order-service(调用库存服务)
// OrderService.java
@Service
public class OrderService {
private final RestTemplate restTemplate;
public OrderService(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Map<String, Object> placeOrder(String sku) {
try {
// ⚠️ 关键:直接使用容器名 inventory-service 作为 hostname!
String url = "http://inventory-service:8080/api/stock/" + sku;
ResponseEntity<Map> response = restTemplate.getForEntity(url, Map.class);
System.out.println("✅ Inventory response from: " + response.getBody().get("host"));
return response.getBody();
} catch (Exception e) {
System.err.println("❌ Failed to call inventory-service: " + e.getMessage());
throw new RuntimeException("Inventory check failed", e);
}
}
}
// OrderController.java(暴露下单 API)
@RestController
@RequestMapping("/api")
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
@PostMapping("/orders")
public Map<String, Object> createOrder(@RequestBody Map<String, String> request) {
String sku = request.get("sku");
return orderService.placeOrder(sku);
}
}
Docker Compose 部署(Swarm 模式下生效)
# docker-compose.yml
version: '3.8'
services:
inventory-service:
image: spring–inventory:1.0
networks:
– my–overlay
ports:
– "8080:8080"
deploy:
replicas: 1
order-service:
image: spring–order:1.0
networks:
– my–overlay
ports:
– "8081:8081"
depends_on:
– inventory–service
deploy:
replicas: 1
networks:
my-overlay:
driver: overlay
attachable: true
构建镜像并部署:
docker build -t spring-inventory:1.0 -f Dockerfile.inventory .
docker build -t spring-order:1.0 -f Dockerfile.order .
docker stack deploy -c docker-compose.yml shop-stack
验证通信:
# 进入 order-service 容器
docker exec -it $(docker ps –filter "name=order-service" -q) sh
# 在容器内执行(无需 IP,直接容器名)
curl -s http://inventory-service:8080/api/stock/IPHONE15 | jq
# 输出示例:
# {
# "sku": "IPHONE15",
# "available": true,
# "quantity": 99,
# "host": "inventory-service.1.xxx" ← 来自 Swarm DNS 解析
# }
✅ 优势:零外部依赖、内置 DNS、服务发现、滚动更新、健康检查; ⚠️ 局限:集群规模建议 < 100 节点;不支持 NetworkPolicy(需升级到 UCP 或切换 Calico);调试工具链较弱。
📘 深入阅读:Docker 官方 Overlay 网络文档 → https://docs.docker.com/network/overlay/
🌐 方案二:Flannel —— Kubernetes 生态最轻量的 CNI 插件
Flannel 由 CoreOS 开发,是 Kubernetes 早期事实标准网络插件。它不操作 Docker daemon,而是为每个 Node 分配唯一子网(如 10.244.1.0/24),容器 IP 直接路由可达,无隧道封装开销(可选 VXLAN/Host-GW 模式)。
📐 网络模型(Host-GW 模式,极致性能)
#mermaid-svg-hGShKYnOWazAQlOS{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hGShKYnOWazAQlOS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hGShKYnOWazAQlOS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hGShKYnOWazAQlOS .error-icon{fill:#552222;}#mermaid-svg-hGShKYnOWazAQlOS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hGShKYnOWazAQlOS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hGShKYnOWazAQlOS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hGShKYnOWazAQlOS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hGShKYnOWazAQlOS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hGShKYnOWazAQlOS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hGShKYnOWazAQlOS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hGShKYnOWazAQlOS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hGShKYnOWazAQlOS .marker.cross{stroke:#333333;}#mermaid-svg-hGShKYnOWazAQlOS svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hGShKYnOWazAQlOS p{margin:0;}#mermaid-svg-hGShKYnOWazAQlOS .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-hGShKYnOWazAQlOS .cluster-label text{fill:#333;}#mermaid-svg-hGShKYnOWazAQlOS .cluster-label span{color:#333;}#mermaid-svg-hGShKYnOWazAQlOS .cluster-label span p{background-color:transparent;}#mermaid-svg-hGShKYnOWazAQlOS .label text,#mermaid-svg-hGShKYnOWazAQlOS span{fill:#333;color:#333;}#mermaid-svg-hGShKYnOWazAQlOS .node rect,#mermaid-svg-hGShKYnOWazAQlOS .node circle,#mermaid-svg-hGShKYnOWazAQlOS .node ellipse,#mermaid-svg-hGShKYnOWazAQlOS .node polygon,#mermaid-svg-hGShKYnOWazAQlOS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hGShKYnOWazAQlOS .rough-node .label text,#mermaid-svg-hGShKYnOWazAQlOS .node .label text,#mermaid-svg-hGShKYnOWazAQlOS .image-shape .label,#mermaid-svg-hGShKYnOWazAQlOS .icon-shape .label{text-anchor:middle;}#mermaid-svg-hGShKYnOWazAQlOS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hGShKYnOWazAQlOS .rough-node .label,#mermaid-svg-hGShKYnOWazAQlOS .node .label,#mermaid-svg-hGShKYnOWazAQlOS .image-shape .label,#mermaid-svg-hGShKYnOWazAQlOS .icon-shape .label{text-align:center;}#mermaid-svg-hGShKYnOWazAQlOS .node.clickable{cursor:pointer;}#mermaid-svg-hGShKYnOWazAQlOS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hGShKYnOWazAQlOS .arrowheadPath{fill:#333333;}#mermaid-svg-hGShKYnOWazAQlOS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hGShKYnOWazAQlOS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hGShKYnOWazAQlOS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hGShKYnOWazAQlOS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hGShKYnOWazAQlOS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hGShKYnOWazAQlOS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hGShKYnOWazAQlOS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hGShKYnOWazAQlOS .cluster text{fill:#333;}#mermaid-svg-hGShKYnOWazAQlOS .cluster span{color:#333;}#mermaid-svg-hGShKYnOWazAQlOS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hGShKYnOWazAQlOS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hGShKYnOWazAQlOS rect.text{fill:none;stroke-width:0;}#mermaid-svg-hGShKYnOWazAQlOS .icon-shape,#mermaid-svg-hGShKYnOWazAQlOS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hGShKYnOWazAQlOS .icon-shape p,#mermaid-svg-hGShKYnOWazAQlOS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hGShKYnOWazAQlOS .icon-shape .label rect,#mermaid-svg-hGShKYnOWazAQlOS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hGShKYnOWazAQlOS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hGShKYnOWazAQlOS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hGShKYnOWazAQlOS :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Host B192.168.1.11
Host A192.168.1.10
eth0
Kernel Route
Kernel Route
eth0
Container-A10.244.1.5
flannel.110.244.1.0/24
Route: 10.244.2.0/24 via 192.168.1.11
Physical NIC
Physical NIC
flannel.110.244.2.0/24
Container-B10.244.2.8
- Flannel DaemonSet 在每节点启动 flanneld,从 etcd 获取本机子网(如 10.244.1.0/24);
- flanneld 配置 Linux kernel 路由表:ip route add 10.244.2.0/24 via 192.168.1.11;
- 容器发出的数据包,经 kernel 路由直接发往目标宿主机物理 IP,由目标宿主机 flannel.1 网桥接收并转发给容器 —— 纯三层路由,零封装,延迟最低。
⚙️ 实践:Kubernetes 集群中启用 Flannel
注意:此方案需先有 Kubernetes 集群(kubeadm 或托管 K8s)。Flannel 作为 CNI 插件工作于 kubelet 与容器运行时之间。
步骤 1:安装 Flannel(官方 manifest)
kubectl apply -f https://github.com/flannel-io/flannel/releases/download/v0.24.2/kube-flannel.yml
该 YAML 会:
- 创建 kube-flannel Namespace;
- 部署 flanneld DaemonSet(自动注入 –iface=eth0 参数);
- 创建 kube-flannel-cfg ConfigMap,定义网络配置(默认 10.244.0.0/16);
- 设置 RBAC 权限。
步骤 2:验证网络就绪
# 查看 flannel Pod 状态
kubectl get pods -n kube-flannel
# 查看节点路由(在 Host-A 执行)
ip route | grep 10.244
# 输出应包含:10.244.2.0/24 via 192.168.1.11 dev eth0
# 查看容器 IP(任意 Pod)
kubectl get pods -o wide
# NAME READY STATUS IP NODE
# nginx-abc12 1/1 Running 10.244.1.5 host-a
# redis-def34 1/1 Running 10.244.2.8 host-b ← 跨主机!
💻 Java 示例:Kubernetes Service 调用(DNS + ClusterIP)
在 Kubernetes 中,我们不再直接使用容器名,而是通过 Service 对象抽象后端 Pod 集合,并利用集群 DNS(CoreDNS)解析 service-name.namespace.svc.cluster.local。
inventory-service Deployment + Service
# inventory-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inventory–deployment
spec:
replicas: 2
selector:
matchLabels:
app: inventory
template:
metadata:
labels:
app: inventory
spec:
containers:
– name: inventory
image: spring–inventory:1.0
ports:
– containerPort: 8080
—
# inventory-service.yaml
apiVersion: v1
kind: Service
metadata:
name: inventory–service
spec:
selector:
app: inventory
ports:
– protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP # 内部服务,仅集群内可访问
order-service 中调用逻辑(Java)
@Service
public class InventoryClient {
private final RestTemplate restTemplate;
private final String inventoryUrl; // 从环境变量注入
public InventoryClient(RestTemplate restTemplate,
@Value("${inventory.service.url:http://inventory-service:8080}") String url) {
this.restTemplate = restTemplate;
this.inventoryUrl = url;
}
public Map<String, Object> checkStock(String sku) {
// 使用 Service DNS 名称(Kubernetes 自动解析)
String url = inventoryUrl + "/api/stock/" + sku;
return restTemplate.getForObject(url, Map.class);
}
}
启动参数注入(Deployment 中)
# order-deploy.yaml
env:
– name: INVENTORY_SERVICE_URL
value: "http://inventory-service.default.svc.cluster.local:8080"
# 或简写(default namespace 可省略)
# value: "http://inventory-service:8080"
✅ 优势:极致性能(Host-GW)、轻量(仅需 etcd + flanneld)、K8s 生态兼容性最佳; ⚠️ 局限:不支持 NetworkPolicy(需配合 Calico);大规模集群下 etcd 成为瓶颈;VXLAN 模式有封装开销。
📘 深入阅读:Flannel 官方架构说明 → https://github.com/flannel-io/flannel#architecture
🛡️ 方案三:Calico —— 企业级策略驱动网络(BGP + eBPF)
Calico 是 CNCF 毕业项目,定位为“云原生网络与安全平台”。它摒弃隧道,原生集成 Linux BGP 协议,让每个节点成为 BGP Speaker,动态宣告自身容器子网,实现全网可达;同时提供细粒度 NetworkPolicy(Kubernetes 原生策略)、eBPF 加速、服务网格集成。
📐 网络模型(BGP 模式)
#mermaid-svg-Lskk8rH97I0G5IqJ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Lskk8rH97I0G5IqJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Lskk8rH97I0G5IqJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Lskk8rH97I0G5IqJ .error-icon{fill:#552222;}#mermaid-svg-Lskk8rH97I0G5IqJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Lskk8rH97I0G5IqJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Lskk8rH97I0G5IqJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Lskk8rH97I0G5IqJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Lskk8rH97I0G5IqJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Lskk8rH97I0G5IqJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Lskk8rH97I0G5IqJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Lskk8rH97I0G5IqJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Lskk8rH97I0G5IqJ .marker.cross{stroke:#333333;}#mermaid-svg-Lskk8rH97I0G5IqJ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Lskk8rH97I0G5IqJ p{margin:0;}#mermaid-svg-Lskk8rH97I0G5IqJ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Lskk8rH97I0G5IqJ .cluster-label text{fill:#333;}#mermaid-svg-Lskk8rH97I0G5IqJ .cluster-label span{color:#333;}#mermaid-svg-Lskk8rH97I0G5IqJ .cluster-label span p{background-color:transparent;}#mermaid-svg-Lskk8rH97I0G5IqJ .label text,#mermaid-svg-Lskk8rH97I0G5IqJ span{fill:#333;color:#333;}#mermaid-svg-Lskk8rH97I0G5IqJ .node rect,#mermaid-svg-Lskk8rH97I0G5IqJ .node circle,#mermaid-svg-Lskk8rH97I0G5IqJ .node ellipse,#mermaid-svg-Lskk8rH97I0G5IqJ .node polygon,#mermaid-svg-Lskk8rH97I0G5IqJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Lskk8rH97I0G5IqJ .rough-node .label text,#mermaid-svg-Lskk8rH97I0G5IqJ .node .label text,#mermaid-svg-Lskk8rH97I0G5IqJ .image-shape .label,#mermaid-svg-Lskk8rH97I0G5IqJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-Lskk8rH97I0G5IqJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Lskk8rH97I0G5IqJ .rough-node .label,#mermaid-svg-Lskk8rH97I0G5IqJ .node .label,#mermaid-svg-Lskk8rH97I0G5IqJ .image-shape .label,#mermaid-svg-Lskk8rH97I0G5IqJ .icon-shape .label{text-align:center;}#mermaid-svg-Lskk8rH97I0G5IqJ .node.clickable{cursor:pointer;}#mermaid-svg-Lskk8rH97I0G5IqJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Lskk8rH97I0G5IqJ .arrowheadPath{fill:#333333;}#mermaid-svg-Lskk8rH97I0G5IqJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Lskk8rH97I0G5IqJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Lskk8rH97I0G5IqJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Lskk8rH97I0G5IqJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Lskk8rH97I0G5IqJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Lskk8rH97I0G5IqJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Lskk8rH97I0G5IqJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Lskk8rH97I0G5IqJ .cluster text{fill:#333;}#mermaid-svg-Lskk8rH97I0G5IqJ .cluster span{color:#333;}#mermaid-svg-Lskk8rH97I0G5IqJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Lskk8rH97I0G5IqJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Lskk8rH97I0G5IqJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-Lskk8rH97I0G5IqJ .icon-shape,#mermaid-svg-Lskk8rH97I0G5IqJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Lskk8rH97I0G5IqJ .icon-shape p,#mermaid-svg-Lskk8rH97I0G5IqJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Lskk8rH97I0G5IqJ .icon-shape .label rect,#mermaid-svg-Lskk8rH97I0G5IqJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Lskk8rH97I0G5IqJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Lskk8rH97I0G5IqJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Lskk8rH97I0G5IqJ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Host B
Host A
BGP Session
BGP Update
BGP Session
BGP Update
BGP over TCP 179
Container-A10.244.1.5
cni0 bridge
caliXXX interface
Host-B
Route: 10.244.2.0/24
caliYYY interface
cni0 bridge
Container-B10.244.2.8
Host-A
Route: 10.244.1.0/24
- Calico 为每个节点分配 10.244.0.0/16 下的 /26 子网(如 10.244.1.0/26);
- calico-node DaemonSet 启动 bird(BGP 守护进程),与集群内其他节点建立 Full Mesh BGP 连接;
- 节点学习到所有子网路由后,容器流量直接路由,无隧道、无 NAT、无额外封装;
- felix 组件实时同步 Kubernetes NetworkPolicy 到 iptables/eBPF,实现微隔离。
⚙️ 实践:在 kubeadm 集群部署 Calico
步骤 1:安装 Calico(Tigera 官方推荐)
# 下载并应用 Calico manifest(自动适配 kubeadm CIDR)
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/custom-resources.yaml
✅ 此方式使用 Tigera Operator,比传统 calico.yaml 更健壮,支持升级、监控、多租户。
步骤 2:验证 BGP 连接
# 查看 calico-node Pod
kubectl get pods -n tigera-operator
# 进入 calico-node 容器查看 BGP 状态
kubectl exec -n calico-system deploy/calico-node — birdcl status
# 输出应显示:BGP state = Established,Peer address = 192.168.1.11
# 查看路由表
kubectl exec -n calico-system deploy/calico-node — ip route | grep 10.244
# 10.244.2.0/26 via 192.168.1.11 dev eth0
💻 Java 示例:NetworkPolicy 控制下的安全调用
我们定义一条策略:仅允许 order-service Pod 访问 inventory-service 的 8080 端口。
network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow–order–to–inventory
namespace: default
spec:
podSelector:
matchLabels:
app: inventory
policyTypes:
– Ingress
ingress:
– from:
– podSelector:
matchLabels:
app: order
ports:
– protocol: TCP
port: 8080
应用后,order-service 可正常调用 inventory-service,但其他 Pod(如 debug-pod)将被拒绝。
Java 代码无需修改,策略由 Calico 透明执行:
// InventoryClient.java(同前)
public Map<String, Object> checkStock(String sku) {
// 仍使用 Service DNS,策略在底层生效
String url = "http://inventory-service:8080/api/stock/" + sku;
return restTemplate.getForObject(url, Map.class);
}
✅ 优势:企业级策略、BGP 原生路由、eBPF 加速(可选)、可观测性(Flow Logs)、服务网格集成; ⚠️ 局限:学习曲线陡峭;BGP 需要网络设备支持(或使用 internal BGP);资源占用略高。
📘 深入阅读:Calico 官方 NetworkPolicy 教程 → https://projectcalico.docs.tigera.io/security/calico-network-policy
🧩 方案四:Weave Net —— 自动加密、DNS 驱动的开发者友好网络
Weave Net 由 Weaveworks 开发,主打“开箱即用、自动发现、默认加密”。它使用 weave 虚拟网桥 + weaver 路由守护进程,支持 VXLAN 和 fastdp(数据面加速)模式,并内置 DNS 服务,容器可通过 service.namespace.weave.local 直连。
📐 网络模型(FastDP 模式)
#mermaid-svg-vxeDHJmz7w0vo7rM{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vxeDHJmz7w0vo7rM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vxeDHJmz7w0vo7rM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vxeDHJmz7w0vo7rM .error-icon{fill:#552222;}#mermaid-svg-vxeDHJmz7w0vo7rM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vxeDHJmz7w0vo7rM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vxeDHJmz7w0vo7rM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vxeDHJmz7w0vo7rM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vxeDHJmz7w0vo7rM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vxeDHJmz7w0vo7rM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vxeDHJmz7w0vo7rM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vxeDHJmz7w0vo7rM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vxeDHJmz7w0vo7rM .marker.cross{stroke:#333333;}#mermaid-svg-vxeDHJmz7w0vo7rM svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vxeDHJmz7w0vo7rM p{margin:0;}#mermaid-svg-vxeDHJmz7w0vo7rM .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-vxeDHJmz7w0vo7rM .cluster-label text{fill:#333;}#mermaid-svg-vxeDHJmz7w0vo7rM .cluster-label span{color:#333;}#mermaid-svg-vxeDHJmz7w0vo7rM .cluster-label span p{background-color:transparent;}#mermaid-svg-vxeDHJmz7w0vo7rM .label text,#mermaid-svg-vxeDHJmz7w0vo7rM span{fill:#333;color:#333;}#mermaid-svg-vxeDHJmz7w0vo7rM .node rect,#mermaid-svg-vxeDHJmz7w0vo7rM .node circle,#mermaid-svg-vxeDHJmz7w0vo7rM .node ellipse,#mermaid-svg-vxeDHJmz7w0vo7rM .node polygon,#mermaid-svg-vxeDHJmz7w0vo7rM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vxeDHJmz7w0vo7rM .rough-node .label text,#mermaid-svg-vxeDHJmz7w0vo7rM .node .label text,#mermaid-svg-vxeDHJmz7w0vo7rM .image-shape .label,#mermaid-svg-vxeDHJmz7w0vo7rM .icon-shape .label{text-anchor:middle;}#mermaid-svg-vxeDHJmz7w0vo7rM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vxeDHJmz7w0vo7rM .rough-node .label,#mermaid-svg-vxeDHJmz7w0vo7rM .node .label,#mermaid-svg-vxeDHJmz7w0vo7rM .image-shape .label,#mermaid-svg-vxeDHJmz7w0vo7rM .icon-shape .label{text-align:center;}#mermaid-svg-vxeDHJmz7w0vo7rM .node.clickable{cursor:pointer;}#mermaid-svg-vxeDHJmz7w0vo7rM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vxeDHJmz7w0vo7rM .arrowheadPath{fill:#333333;}#mermaid-svg-vxeDHJmz7w0vo7rM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vxeDHJmz7w0vo7rM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vxeDHJmz7w0vo7rM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vxeDHJmz7w0vo7rM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vxeDHJmz7w0vo7rM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vxeDHJmz7w0vo7rM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vxeDHJmz7w0vo7rM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vxeDHJmz7w0vo7rM .cluster text{fill:#333;}#mermaid-svg-vxeDHJmz7w0vo7rM .cluster span{color:#333;}#mermaid-svg-vxeDHJmz7w0vo7rM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vxeDHJmz7w0vo7rM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vxeDHJmz7w0vo7rM rect.text{fill:none;stroke-width:0;}#mermaid-svg-vxeDHJmz7w0vo7rM .icon-shape,#mermaid-svg-vxeDHJmz7w0vo7rM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vxeDHJmz7w0vo7rM .icon-shape p,#mermaid-svg-vxeDHJmz7w0vo7rM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vxeDHJmz7w0vo7rM .icon-shape .label rect,#mermaid-svg-vxeDHJmz7w0vo7rM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vxeDHJmz7w0vo7rM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vxeDHJmz7w0vo7rM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vxeDHJmz7w0vo7rM :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Host B
Host A
Encrypted UDP
Container-A10.32.0.5
weave bridge
weaver process
Host-B
weaver process
weave bridge
Container-B10.32.1.8
- weave launch 命令自动发现集群(支持 token 或 IP 列表);
- 所有容器接入 weave 网络后,获得 10.32.0.0/12 内 IP;
- weaver 进程建立加密 UDP 连接(AES-CTR),封装容器数据包;
- 内置 weaveDNS 为每个容器注册 <name>.<namespace>.weave.local DNS 记录。
⚙️ 实践:Weave on Docker Standalone(非 Kubernetes)
Weave 可独立于 Kubernetes 运行,适合 Docker Compose 或裸机集群。
步骤 1:在 Host-A 启动 Weave
# 启动 weave 并指定 peer(Host-B IP)
weave launch –ipalloc-range 10.32.0.0/12 192.168.1.11
# 输出:weave is ready
步骤 2:在 Host-B 加入
weave launch –ipalloc-range 10.32.0.0/12 192.168.1.10
步骤 3:运行容器并验证 DNS
# Host-A 运行 inventory
weave run –name inventory -p 8080:8080 spring-inventory:1.0
# Host-B 运行 order
weave run –name order -p 8081:8081 spring-order:1.0
# 在 order 容器内解析 inventory
docker exec order nslookup inventory.weave.local
# Server: 127.0.0.11
# Address 1: 10.32.1.5 inventory.weave.local
# 调用成功!
docker exec order curl -s http://inventory.weave.local:8080/api/stock/IPHONE15
💻 Java 示例:Weave DNS 直连(无 Kubernetes 依赖)
@Service
public class InventoryClient {
private final RestTemplate restTemplate;
public InventoryClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Map<String, Object> checkStock(String sku) {
// 使用 Weave DNS 名称(自动注册)
String url = "http://inventory.weave.local:8080/api/stock/" + sku;
return restTemplate.getForObject(url, Map.class);
}
}
✅ 优势:零配置发现、默认加密、内置 DNS、支持 Docker/K8s/standalone; ⚠️ 局限:性能略低于 Flannel/Calico(加密开销);社区活跃度低于 Calico;企业功能需付费版。
📘 深入阅读:Weave Net 官方快速入门 → https://www.weave.works/docs/net/latest/quickstart/
🧭 方案五:自建 VXLAN 隧道(Linux 原生命令,教学价值高)
理解底层原理的最佳方式,是亲手搭建一个 VXLAN 网络。这无需任何第三方软件,仅用 ip、brctl、ethtool 等 Linux 标准工具。
📐 网络模型(手动 VXLAN)
#mermaid-svg-ygly9nQ5YJYqlOfb{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ygly9nQ5YJYqlOfb .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ygly9nQ5YJYqlOfb .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ygly9nQ5YJYqlOfb .error-icon{fill:#552222;}#mermaid-svg-ygly9nQ5YJYqlOfb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ygly9nQ5YJYqlOfb .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ygly9nQ5YJYqlOfb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ygly9nQ5YJYqlOfb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ygly9nQ5YJYqlOfb .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ygly9nQ5YJYqlOfb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ygly9nQ5YJYqlOfb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ygly9nQ5YJYqlOfb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ygly9nQ5YJYqlOfb .marker.cross{stroke:#333333;}#mermaid-svg-ygly9nQ5YJYqlOfb svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ygly9nQ5YJYqlOfb p{margin:0;}#mermaid-svg-ygly9nQ5YJYqlOfb .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ygly9nQ5YJYqlOfb .cluster-label text{fill:#333;}#mermaid-svg-ygly9nQ5YJYqlOfb .cluster-label span{color:#333;}#mermaid-svg-ygly9nQ5YJYqlOfb .cluster-label span p{background-color:transparent;}#mermaid-svg-ygly9nQ5YJYqlOfb .label text,#mermaid-svg-ygly9nQ5YJYqlOfb span{fill:#333;color:#333;}#mermaid-svg-ygly9nQ5YJYqlOfb .node rect,#mermaid-svg-ygly9nQ5YJYqlOfb .node circle,#mermaid-svg-ygly9nQ5YJYqlOfb .node ellipse,#mermaid-svg-ygly9nQ5YJYqlOfb .node polygon,#mermaid-svg-ygly9nQ5YJYqlOfb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ygly9nQ5YJYqlOfb .rough-node .label text,#mermaid-svg-ygly9nQ5YJYqlOfb .node .label text,#mermaid-svg-ygly9nQ5YJYqlOfb .image-shape .label,#mermaid-svg-ygly9nQ5YJYqlOfb .icon-shape .label{text-anchor:middle;}#mermaid-svg-ygly9nQ5YJYqlOfb .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ygly9nQ5YJYqlOfb .rough-node .label,#mermaid-svg-ygly9nQ5YJYqlOfb .node .label,#mermaid-svg-ygly9nQ5YJYqlOfb .image-shape .label,#mermaid-svg-ygly9nQ5YJYqlOfb .icon-shape .label{text-align:center;}#mermaid-svg-ygly9nQ5YJYqlOfb .node.clickable{cursor:pointer;}#mermaid-svg-ygly9nQ5YJYqlOfb .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ygly9nQ5YJYqlOfb .arrowheadPath{fill:#333333;}#mermaid-svg-ygly9nQ5YJYqlOfb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ygly9nQ5YJYqlOfb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ygly9nQ5YJYqlOfb .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ygly9nQ5YJYqlOfb .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ygly9nQ5YJYqlOfb .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ygly9nQ5YJYqlOfb .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ygly9nQ5YJYqlOfb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ygly9nQ5YJYqlOfb .cluster text{fill:#333;}#mermaid-svg-ygly9nQ5YJYqlOfb .cluster span{color:#333;}#mermaid-svg-ygly9nQ5YJYqlOfb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ygly9nQ5YJYqlOfb .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ygly9nQ5YJYqlOfb rect.text{fill:none;stroke-width:0;}#mermaid-svg-ygly9nQ5YJYqlOfb .icon-shape,#mermaid-svg-ygly9nQ5YJYqlOfb .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ygly9nQ5YJYqlOfb .icon-shape p,#mermaid-svg-ygly9nQ5YJYqlOfb .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ygly9nQ5YJYqlOfb .icon-shape .label rect,#mermaid-svg-ygly9nQ5YJYqlOfb .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ygly9nQ5YJYqlOfb .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ygly9nQ5YJYqlOfb .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ygly9nQ5YJYqlOfb :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Host B192.168.1.11
Host A192.168.1.10
UDP 8472
Container-A10.10.1.5
veth-a
br-vxlan
vxlan0VNI: 100
192.168.1.11
vxlan0VNI: 100
br-vxlan
veth-b
Container-B10.10.2.8
⚙️ 实践:手敲命令搭建(Host-A & Host-B)
Host-A 执行:
# 1. 创建 bridge 和 vxlan
sudo ip link add br-vxlan type bridge
sudo ip link add vxlan0 type vxlan id 100 dev eth0 dstport 8472
sudo ip link set vxlan0 master br-vxlan
sudo ip link set br-vxlan up
sudo ip link set vxlan0 up
# 2. 分配子网 IP(供容器使用)
sudo ip addr add 10.10.1.1/24 dev br-vxlan
# 3. 启动容器并连接到 br-vxlan
docker run -d –name container-a –net none ubuntu:22.04 sleep infinity
PID=$(docker inspect –format '{{.State.Pid}}' container-a)
sudo mkdir -p /var/run/netns
sudo ln -s /proc/$PID/ns/net /var/run/netns/container-a
# 创建 veth pair
sudo ip link add veth-a type veth peer name veth-a-br
sudo ip link set veth-a netns container-a
sudo ip link set veth-a-br master br-vxlan
sudo ip link set veth-a-br up
# 配置容器内网络
sudo ip netns exec container-a ip link set veth-a up
sudo ip netns exec container-a ip addr add 10.10.1.5/24 dev veth-a
sudo ip netns exec container-a ip route add default via 10.10.1.1
Host-B 执行(类似,注意 IP 和 VNI 一致):
sudo ip link add br-vxlan type bridge
sudo ip link add vxlan0 type vxlan id 100 dev eth0 dstport 8472
sudo ip link set vxlan0 master br-vxlan
sudo ip link set br-vxlan up
sudo ip link set vxlan0 up
sudo ip addr add 10.10.2.1/24 dev br-vxlan
# 启动 container-b…
测试连通性:
# Host-A 中
sudo ip netns exec container-a ping -c 3 10.10.2.5 # 应成功!
# Host-B 中
sudo ip netns exec container-b curl http://10.10.1.5:8080/api/stock/IPHONE15
✅ 优势:彻底掌握 VXLAN 原理、无黑盒、最小依赖; ⚠️ 局限:运维成本极高、无服务发现、无健康检查、无法规模化。
🌐 方案六:Service Mesh 间接通信(Istio / Linkerd)
当直接容器 IP 通信不满足需求(如需要 mTLS、重试、熔断、分布式追踪),Service Mesh 提供了更高维度的解决方案:通信仍走底层网络(如 Calico),但所有流量被 Sidecar 代理劫持,由控制平面统一治理。
📐 模型示意(Istio)
#mermaid-svg-WiBYAJwb8WTVJ3kM{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WiBYAJwb8WTVJ3kM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WiBYAJwb8WTVJ3kM .error-icon{fill:#552222;}#mermaid-svg-WiBYAJwb8WTVJ3kM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WiBYAJwb8WTVJ3kM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WiBYAJwb8WTVJ3kM .marker.cross{stroke:#333333;}#mermaid-svg-WiBYAJwb8WTVJ3kM svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WiBYAJwb8WTVJ3kM p{margin:0;}#mermaid-svg-WiBYAJwb8WTVJ3kM .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-WiBYAJwb8WTVJ3kM .cluster-label text{fill:#333;}#mermaid-svg-WiBYAJwb8WTVJ3kM .cluster-label span{color:#333;}#mermaid-svg-WiBYAJwb8WTVJ3kM .cluster-label span p{background-color:transparent;}#mermaid-svg-WiBYAJwb8WTVJ3kM .label text,#mermaid-svg-WiBYAJwb8WTVJ3kM span{fill:#333;color:#333;}#mermaid-svg-WiBYAJwb8WTVJ3kM .node rect,#mermaid-svg-WiBYAJwb8WTVJ3kM .node circle,#mermaid-svg-WiBYAJwb8WTVJ3kM .node ellipse,#mermaid-svg-WiBYAJwb8WTVJ3kM .node polygon,#mermaid-svg-WiBYAJwb8WTVJ3kM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WiBYAJwb8WTVJ3kM .rough-node .label text,#mermaid-svg-WiBYAJwb8WTVJ3kM .node .label text,#mermaid-svg-WiBYAJwb8WTVJ3kM .image-shape .label,#mermaid-svg-WiBYAJwb8WTVJ3kM .icon-shape .label{text-anchor:middle;}#mermaid-svg-WiBYAJwb8WTVJ3kM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WiBYAJwb8WTVJ3kM .rough-node .label,#mermaid-svg-WiBYAJwb8WTVJ3kM .node .label,#mermaid-svg-WiBYAJwb8WTVJ3kM .image-shape .label,#mermaid-svg-WiBYAJwb8WTVJ3kM .icon-shape .label{text-align:center;}#mermaid-svg-WiBYAJwb8WTVJ3kM .node.clickable{cursor:pointer;}#mermaid-svg-WiBYAJwb8WTVJ3kM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WiBYAJwb8WTVJ3kM .arrowheadPath{fill:#333333;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WiBYAJwb8WTVJ3kM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WiBYAJwb8WTVJ3kM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WiBYAJwb8WTVJ3kM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WiBYAJwb8WTVJ3kM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WiBYAJwb8WTVJ3kM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WiBYAJwb8WTVJ3kM .cluster text{fill:#333;}#mermaid-svg-WiBYAJwb8WTVJ3kM .cluster span{color:#333;}#mermaid-svg-WiBYAJwb8WTVJ3kM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WiBYAJwb8WTVJ3kM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WiBYAJwb8WTVJ3kM rect.text{fill:none;stroke-width:0;}#mermaid-svg-WiBYAJwb8WTVJ3kM .icon-shape,#mermaid-svg-WiBYAJwb8WTVJ3kM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WiBYAJwb8WTVJ3kM .icon-shape p,#mermaid-svg-WiBYAJwb8WTVJ3kM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WiBYAJwb8WTVJ3kM .icon-shape .label rect,#mermaid-svg-WiBYAJwb8WTVJ3kM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WiBYAJwb8WTVJ3kM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WiBYAJwb8WTVJ3kM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WiBYAJwb8WTVJ3kM :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Host B
Host A
HTTP/1.1
Routing
Order App
istio-proxyEnvoy
ClusterIP Service
Host-B
istio-proxyEnvoy
Inventory App
- Sidecar(Envoy)与业务容器共享 Network Namespace,拦截 outbound 和 inbound 流量;
- 流量经 ClusterIP Service 路由,由 Istio Pilot 生成 xDS 配置下发给 Envoy;
- 应用代码完全无感知,Java 仍调用 http://inventory-service:8080,但实际经过 mTLS 加密、重试 3 次、超时 5s。
💻 Java 示例:零代码改造
// OrderService.java(完全不变!)
public Map<String, Object> placeOrder(String sku) {
// 依然直连 Service 名称
String url = "http://inventory-service:8080/api/stock/" + sku;
return restTemplate.getForObject(url, Map.class);
}
Istio 注入后,该请求流程为:
Order App → localhost:15001 (Envoy inbound)
→ DNS resolve inventory-service → ClusterIP
→ Envoy outbound → mTLS to inventory's Envoy → inventory-app
✅ 优势:业务无侵入、全链路可观测、零信任安全、渐进式灰度; ⚠️ 局限:资源开销(CPU/Mem)、调试复杂度高、学习曲线陡峭。
📘 深入阅读:Istio 官方流量管理指南 → https://istio.io/latest/docs/tasks/traffic-management/
🧪 方案对比与选型决策树
| Docker Swarm Overlay | ⭐☆☆☆☆(极简) | 中 | ❌ | ❌ | ✅(内置) | 小型 Docker 集群,无 K8s 需求 |
| Flannel | ⭐⭐☆☆☆ | ⭐⭐⭐⭐⭐(Host-GW) | ❌ | ❌ | ✅(K8s DNS) | K8s 初创集群,追求极致性能 |
| Calico | ⭐⭐⭐☆☆ | ⭐⭐⭐⭐☆(BGP) | ✅(可选) | ✅(NetworkPolicy) | ✅(K8s DNS) | 企业生产环境,需合规与安全 |
| Weave Net | ⭐⭐☆☆☆ | ⭐⭐⭐☆☆(加密开销) | ✅(默认) | ❌ | ✅(WeaveDNS) | 开发测试、混合环境快速验证 |
| 自建 VXLAN | ⭐⭐⭐⭐⭐(手动) | ⭐⭐⭐⭐☆ | ❌ | ❌ | ❌ | 教学、原理研究、特殊定制 |
| Service Mesh | ⭐⭐⭐⭐☆ | ⭐⭐☆☆☆(Sidecar 开销) | ✅(mTLS) | ✅(细粒度) | ✅(K8s DNS + Istio) | 微服务治理成熟期,需韧性保障 |
🧭 决策树(简化版):
#mermaid-svg-e5RSQk5gR6YKEbqO{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-e5RSQk5gR6YKEbqO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-e5RSQk5gR6YKEbqO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-e5RSQk5gR6YKEbqO .error-icon{fill:#552222;}#mermaid-svg-e5RSQk5gR6YKEbqO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-e5RSQk5gR6YKEbqO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-e5RSQk5gR6YKEbqO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-e5RSQk5gR6YKEbqO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-e5RSQk5gR6YKEbqO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-e5RSQk5gR6YKEbqO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-e5RSQk5gR6YKEbqO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-e5RSQk5gR6YKEbqO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-e5RSQk5gR6YKEbqO .marker.cross{stroke:#333333;}#mermaid-svg-e5RSQk5gR6YKEbqO svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-e5RSQk5gR6YKEbqO p{margin:0;}#mermaid-svg-e5RSQk5gR6YKEbqO .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-e5RSQk5gR6YKEbqO .cluster-label text{fill:#333;}#mermaid-svg-e5RSQk5gR6YKEbqO .cluster-label span{color:#333;}#mermaid-svg-e5RSQk5gR6YKEbqO .cluster-label span p{background-color:transparent;}#mermaid-svg-e5RSQk5gR6YKEbqO .label text,#mermaid-svg-e5RSQk5gR6YKEbqO span{fill:#333;color:#333;}#mermaid-svg-e5RSQk5gR6YKEbqO .node rect,#mermaid-svg-e5RSQk5gR6YKEbqO .node circle,#mermaid-svg-e5RSQk5gR6YKEbqO .node ellipse,#mermaid-svg-e5RSQk5gR6YKEbqO .node polygon,#mermaid-svg-e5RSQk5gR6YKEbqO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-e5RSQk5gR6YKEbqO .rough-node .label text,#mermaid-svg-e5RSQk5gR6YKEbqO .node .label text,#mermaid-svg-e5RSQk5gR6YKEbqO .image-shape .label,#mermaid-svg-e5RSQk5gR6YKEbqO .icon-shape .label{text-anchor:middle;}#mermaid-svg-e5RSQk5gR6YKEbqO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-e5RSQk5gR6YKEbqO .rough-node .label,#mermaid-svg-e5RSQk5gR6YKEbqO .node .label,#mermaid-svg-e5RSQk5gR6YKEbqO .image-shape .label,#mermaid-svg-e5RSQk5gR6YKEbqO .icon-shape .label{text-align:center;}#mermaid-svg-e5RSQk5gR6YKEbqO .node.clickable{cursor:pointer;}#mermaid-svg-e5RSQk5gR6YKEbqO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-e5RSQk5gR6YKEbqO .arrowheadPath{fill:#333333;}#mermaid-svg-e5RSQk5gR6YKEbqO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-e5RSQk5gR6YKEbqO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-e5RSQk5gR6YKEbqO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-e5RSQk5gR6YKEbqO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-e5RSQk5gR6YKEbqO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-e5RSQk5gR6YKEbqO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-e5RSQk5gR6YKEbqO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-e5RSQk5gR6YKEbqO .cluster text{fill:#333;}#mermaid-svg-e5RSQk5gR6YKEbqO .cluster span{color:#333;}#mermaid-svg-e5RSQk5gR6YKEbqO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-e5RSQk5gR6YKEbqO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-e5RSQk5gR6YKEbqO rect.text{fill:none;stroke-width:0;}#mermaid-svg-e5RSQk5gR6YKEbqO .icon-shape,#mermaid-svg-e5RSQk5gR6YKEbqO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-e5RSQk5gR6YKEbqO .icon-shape p,#mermaid-svg-e5RSQk5gR6YKEbqO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-e5RSQk5gR6YKEbqO .icon-shape .label rect,#mermaid-svg-e5RSQk5gR6YKEbqO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-e5RSQk5gR6YKEbqO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-e5RSQk5gR6YKEbqO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-e5RSQk5gR6YKEbqO :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
是
否
是
否
你用 Kubernetes 吗?
需要 NetworkPolicy 吗?
用 Docker Swarm 吗?
选 Calico
Flannel or Weave
选 Swarm Overlay
自建 VXLAN 或 Weave
部署 Calico
Flannel for perfWeave for simplicity
Swarm init + overlay
Weave launchor manual VXLAN
🚀 最佳实践与避坑指南
✅ 必做事项
- 始终使用 –mtu 显式设置:VXLAN 封装会减少 MTU,建议在 docker network create 或 Calico ConfigMap 中设为 1450;
- 关闭宿主机防火墙或放行关键端口:Swarm(2377, 7946, 8472)、Calico(179/BGP)、Weave(6783);
- 为容器指定 –ip 时,确保在子网范围内:docker run –ip 10.0.1.100 –network my-overlay …;
- Java 应用禁用 IPv6 回退:添加 JVM 参数 -Djava.net.preferIPv4Stack=true,避免 DNS 解析卡顿。
❌ 经典陷阱
- 混用网络驱动:不要在同一个 docker-compose.yml 中同时声明 bridge 和 overlay 网络,会导致容器无法解析 DNS;
- 忽略 –advertise-addr:Swarm 初始化时若未指定,可能绑定 127.0.0.1,导致 Worker 无法加入;
- K8s 中未清理旧 CNI:安装 Flannel 前,务必删除 /etc/cni/net.d/ 下其他插件配置(如 10-calico.conflist),否则 kubelet 启动失败;
- Java RestTemplate 连接池未复用:高频调用跨主机服务时,务必配置 PoolingHttpClientConnectionManager,否则新建连接耗尽 socket。
🔍 调试黄金命令
# 查看容器网络命名空间路由
docker exec container-name ip route
# 查看宿主机 VXLAN 设备状态
ip -d link show vxlan0
# 抓包分析(在宿主机)
sudo tcpdump -i eth0 -n port 8472 # VXLAN 流量
sudo tcpdump -i docker0 -n port 8080 # 容器间 HTTP
# 检查 DNS 解析(容器内)
docker exec container-name nslookup inventory-service
🌟 结语:通信只是开始,治理才是未来
Docker 跨主机通信,表面是 IP 如何可达的技术问题,深层却是分布式系统可靠性的基石。从 Swarm 的简洁优雅,到 Calico 的企业严谨,再到 Istio 的智能治理,每一种方案都在回答同一个问题:“当我的服务散落于全球数据中心,我该如何信任它们之间的每一次对话?”
而 Java 开发者幸运的是,无论底层网络如何演进,RestTemplate、WebClient、甚至 FeignClient,都只需关注业务逻辑 —— 网络的复杂性,正被越来越成熟的开源项目悄然封装。
🌈 下一站,是服务网格的深度集成,是 eBPF 带来的内核级加速,是 WASM 边缘网络的轻量化革命。而此刻,理解这些方案的本质,便是你驾驭云原生浪潮最坚实的船桨 🚣♂️。
愿你在容器网络的世界里,既看得见协议栈的每一层,也写得出优雅的 Spring Boot 代码。 共勉。
🙌 感谢你读到这里! 🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。 💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友! 💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿 🔔 关注我,不错过下一篇干货!我们下期再见!✨



