Kubernetes网络隔离翻车,Pod IP全乱套了
ACK集群中两套节点池因共用可用区导致Terway网络隔离失效,Pod IP混杂、公网出口错乱。根因是Terway的eni-config按可用区分配IP,无法区分同可用区内不同网段的交换机。解决方案是将节点池2迁移至eni-config未配置的可用区E/F,利用Terway降级回退机制,使Pod IP从节点eth0所在交换机分配,实现物理隔离。
一、背景
同一个 ACK 集群内建有两套节点池,目的是通过不同的交换机网段 + 对应的 SNAT 规则,让不同节点池内的服务走不同的公网出口 IP。
1.1 原始架构
两套节点池共用相同的可用区 G/L/M/N,但各自使用不同网段的交换机:
| 节点池 | 可用区 | 交换机网段 | 公网出口 |
|---|---|---|---|
| 节点池 1 | G / L / M / N | 网段 A(4 个 vSwitch) | 出口 IP-A |
| 节点池 2 | G / L / M / N | 网段 B(4 个 vSwitch) | 出口 IP-B |
Terway eni-config 只配置了创建集群时指定的 N、M 区交换机(共 2 个),后来集群扩容至 G/L/M/N 共8个交换机。
核心诉求:节点池 2 的 Pod 只能使用网段 B 的交换机 IP,节点池 1 的 Pod 只能使用网段 A 的交换机 IP,二者绝不混杂。
1.2 修复后
| 节点池 | 可用区 | 交换机 | 公网出口 |
|---|---|---|---|
| 节点池 1 | G / L / M / N | 共8个 vSwitch(每区2个) | 出口 IP-A |
| 节点池 2 | E / F | 共 2 个 vSwitch(每区1个) | 出口 IP-B |
二、问题描述
2.1 现象
节点池 2 新增服务上线后,发现 Pod 分配到的 IP 与所在节点 IP 不在同一网段,属于节点池 1 的交换机网段,导致:
- Pod 流量走了节点池 1 的 SNAT 公网出口(出口 IP-A),而非预期的出口 IP-B
- 出口 IP 混淆,业务逻辑异常
- Pod 网段和节点 ECS 主机网段混杂,网络拓扑混乱
2.2 排查过程
- 节点池 2 的 ECS 节点 IP 网段确认正常(网段 B),但 Pod 分配的 IP 却属于节点池 1 的网段 A
- 查阅 Terway
eni-configConfigMap,发现配置了 M/N 共2个交换机,且为全局扁平列表,没有按节点池区分,Terway 随机分配,节点池 2 的 Pod 仍可能拿到节点池 1 的交换机 IP - 最后确认:Terway 优先使用 eni-config 中配置的可用区交换机分配 IP,找不到匹配可用区交换机时,才回退到节点主网卡 eth0 所在交换机
三、根因分析
3.1 Terway IPAM 分配逻辑
Pod 调度到节点
│
▼
Terway 查找 eni-config 中的 vswitches 配置
│
├── 找到匹配可用区 → 从配置的交换机列表中分配 IP
│
└── 未找到匹配可用区 → 回退到节点 eth0 所在交换机分配 IP
3.2 问题演进过程
阶段一:两套节点池共用 G/L/M/N 可用区
节点池 1:G区(网段A1)、L区(网段A2)、M区(网段A3)、N区(网段A4)
节点池 2:G区(网段B1)、L区(网段B2)、M区(网段B3)、N区(网段B4)
eni-config:只配了 N/M 区交换机(创建集群时指定的)
当节点池 2 的 Pod 调度到 M 区或 N 区的节点时,Terway 在 eni-config 中找到 M/N 区 → 没有触发降级回退到 eth0,而是从已配置的 N/M 区交换机中分配 IP → Pod 拿到了节点池 1 的交换机 IP。
阶段二:将 G/L 区交换机加入 eni-config(扩容至 8 个)
eni-config vswitches:
G区:[vsw-1-A1, vsw-1-B1] ← 网段A和网段B的交换机混在一起
L区:[vsw-2-A2, vsw-2-B2]
M区:[vsw-3-A3, vsw-3-B3]
N区:[vsw-4-A4, vsw-4-B4]
Terway 看到的只是一个可用区下的交换机列表,完全不区分这些交换机属于哪个节点池。Pod 分配到哪个交换机的 IP 是随机的,节点池 2 的 Pod 仍然可能拿到网段 A 的 IP → 出口仍然串。
关键教训:eni-config 无法按节点池粒度区分交换机,同可用区内多套网段的交换机对它来说没有区别。
3.3 关键认识
eni-config 的 vswitches 字段是全局扁平映射(可用区 → 交换机列表),不支持按节点池粒度区分。同一个可用区内存在多套不同网段交换机时,Terway 无法感知「哪个交换机属于哪个节点池」,会导致两个节点池的 Pod IP 随机混杂。
结论:只要两套节点池共用可用区,就无法通过 eni-config 实现网络隔离。必须从可用区层面物理隔离。
四、解决方案
4.1 方案设计思路
利用 Terway 的降级回退机制实现物理隔离:
- 节点池 1 跑在 Terway 已配置的可用区(G/L/M/N)→ Pod IP 从 eni-config 的交换机分配
- 节点池 2 跑在 Terway 未配置的可用区(E/F)→ Pod IP 从节点 eth0 所在交换机分配
这样两套节点池的 Pod IP 来源天然不同,实现了网络平面的物理隔离。
4.2 最终架构
┌─────────────────────────────────────────────────────┐
│ ACK 集群 │
│ │
│ Terway eni-config vswitches: │
│ G区×2, L区×2, M区×2, N区×2 (共8个) │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 节点池 1 │ │ 节点池 2 │ │
│ │ 可用区: G/L/M/N │ │ 可用区: E/F │ │
│ │ 节点 IP: 配置内 │ │ 节点 IP: 配置外 │ │
│ │ Pod IP: 配置内 │ │ Pod IP: eth0回退 │ │
│ │ SNAT → IP-A │ │ SNAT → IP-B │ │
│ └──────────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────┘
4.3 操作步骤
- 新建 E/F 区交换机,指定节点池 2 规划的网段(与节点池 1 的网段无重叠)
- 配置 NAT 网关 SNAT 规则,将 E/F 区交换机绑定到出口 IP-B
- 创建/重建节点池 2,指定 E/F 区可用区和对应的交换机
- 部署服务到节点池 2,通过节点选择器/亲和性确保 Pod 调度到节点池 2 的节点
- 验证:
- Pod IP 与所在节点 IP 是否属于同一网段
- Pod 出公网的 IP 是否为预期的出口 IP-B
- 灰度切流,确认业务正常
- 清理:下线旧的节点池 2 节点(N/M 区的节点)
五、此方案铁律(不可违反)
Terway eni-config 绝不能加入 E/F 区交换机
| 操作 | 是否允许 |
|---|---|
| 在 eni-config 的 vswitches 中添加 E/F 区交换机 | ❌ 禁止 |
| 修改 eni-config 中已有的 G/L/M/N 区交换机列表 | ⚠️ 允许但需评审 |
违反后果:Terway 会从 eni-config 中的 E/F 区交换机为节点池 2 的 Pod 分配 IP,但由于 eni-config 是全局配置,节点池 1 的 Pod 也可能拿到 E/F 交换机 IP → 出口再次混淆。
六、中长期优化建议
当前方案是利用降级行为的隐式依赖,长期来看建议迁移到:
- Terway PodNetworking CRD(需 Terway 1.4+):通过 CRD 显式绑定节点标签 → 交换机,不依赖降级逻辑,天然解决同 AZ 多网段问题
- 或考虑按节点池拆分集群,彻底解耦网络平面