Kubernetes (K8s) 的核心设计要求之一是“IP-per-Pod”模型,即每个 Pod 都有一个唯一的 IP 地址,并且所有 Pod 都可以无需 NAT 地互相通信,无论它们位于哪个节点上。在单节点内部,这相对容易实现(通常通过 veth 对和 Linux 网桥)。但是,当 Pod 位于不同的物理或虚拟节点上时,就需要一个复杂的机制来确保这种无缝通信,这就是 K8s CNI 插件(如 Flannel 或 Calico)提供的覆盖网络(Overlay Network),其中最常见且具代表性的是 VXLAN 隧道技术。
1. 为什么需要隧道?
想象两个 Pod:
* Pod A (IP: 10.244.1.5) 位于 Node 1 (IP: 192.168.1.10)
* Pod B (IP: 10.244.2.8) 位于 Node 2 (IP: 192.168.1.20)
当 Pod A 试图连接 Pod B 时,数据包的目标 IP 是 10.244.2.8。底层的物理网络路由器只知道 192.168.x.x 这个 Node IP 段,不知道 10.244.x.x 这个 Pod IP 段。为了让数据包能够跨越物理网络到达 Node 2,数据包必须被“封装”到 Node IP 地址空间中,这就是隧道的任务。
2. VXLAN:Mac-in-UDP 隧道技术
VXLAN(Virtual Extensible LAN)是一种网络虚拟化技术,它允许我们在现有的 L3 网络(IP 网络)上构建虚拟 L2 网络。它通过将原始的 L2 帧(带有 Pod 的 MAC/IP 地址)封装进一个标准的 UDP 数据包来实现这一目的。
关键组件:VTEP 和 VNI
- VTEP (VXLAN Tunnel Endpoint): 这是 K8s 节点上用于封装和解封装 VXLAN 数据包的虚拟网络接口,通常在 Flannel 中表现为 flannel.1 接口。
- VNI (VXLAN Network Identifier): 一个 24 位的 ID,用于标识一个特定的 VXLAN 网络。在 K8s 集群中,所有节点上的 Pod IP 都在同一个 VNI 下,确保它们属于同一个逻辑 L2 网络。
3. 跨节点通信的实操流程
我们以 Pod A (Node 1) 发送数据到 Pod B (Node 2) 为例,演示 VXLAN 如何工作:
步骤 1: 流量路由到 VTEP
当 Pod A 发送数据到 10.244.2.8 时,数据包离开 Pod A 的网络命名空间。Node 1 的主路由表会告诉内核:所有发往 10.244.2.0/24 子网的流量,都必须通过 flannel.1 (VTEP) 接口发送。
您可以在 Node 1 上使用以下命令查看路由表(假设 Flannel 为 10.244.1.0/24):
# 在 K8s Node 上执行
ip route | grep 10.244
# 预期输出示例 (注意,指向其他子网的流量通过 flannel.1 接口)
# 10.244.1.0/24 dev cni0 proto kernel scope link src 10.244.1.1
# 10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink
步骤 2: 数据包封装
- 数据包到达 flannel.1 接口。
- Flannel 需要知道 Node 2 的物理 IP (192.168.1.20) 才能发送数据。
- Flannel 通过其内置的 Forwarding Database (FDB) 查找(这些 FDB 条目通常由 Flannel DaemonSet 监听 K8s API Server 自动创建)。
- Flannel 将原始的 IP 数据包封装在一个 VXLAN 头中(包含 VNI)。
- 这个 VXLAN 数据包被进一步封装进一个标准的 UDP 数据包(目标端口 8472,目标 IP 192.168.1.20)。
封装层次:
| 物理网络头 (Node 2 IP) | UDP 头 (Port 8472) | VXLAN 头 (VNI) | 原始数据包 (Pod A -> Pod B) |
|---|---|---|---|
步骤 3: 跨越物理网络
现在,这个 UDP 数据包的目标是 192.168.1.20。它被视为普通的网络流量,顺利通过底层物理网络,从 Node 1 发送到 Node 2。
步骤 4: 数据包解封装
- Node 2 接收到这个 UDP 数据包(端口 8472)。
- 内核识别出这是 VXLAN 流量,并将其传递给 flannel.1 (VTEP) 接口。
- flannel.1 接口剥离 UDP 头和 VXLAN 头,还原出原始的 IP 数据包。
- 内核检查原始数据包的目标 IP (10.244.2.8),发现它属于 Node 2 上的一个 Pod,于是通过 Node 2 上的 CNI 网桥 (如 cni0) 转发给目标 Pod B。
检查 VTEP 转发数据库
您可以通过检查 VTEP 的 FDB 来查看 Node 是如何知道如何路由到其他子网的:
# 在 K8s Node 上执行,查看 flannel.1 的 FDB
# 这里的 MAC 地址是目标节点 flannel.1 接口的 MAC,以及对应的物理 IP
bridge fdb show dev flannel.1
# 预期输出示例
# 01:23:45:67:89:ab dev flannel.1 dst 192.168.1.20 permanent
# (表示:要到达这个 MAC 地址,请通过隧道发送到物理 IP 192.168.1.20)
总结
VXLAN 隧道是 K8s 实现跨节点通信的基石。它巧妙地将 Pod 的虚拟 L2 网络流量封装在底层物理网络的 L3 流量中,使得 Pod 间通信可以忽略底层物理拓扑的限制,实现了 K8s 所要求的“扁平网络”目标。
汤不热吧