系列导航:Kubernetes 重建迁移教程系列。本文中的地址均使用
<...>占位符,不包含真实网络信息。
同一个 Kubernetes 集群中同时出现多段 IP 并不代表网络混乱。节点、Pod、Service 本来就承担不同职责,真正的问题是:地址段是否互不重叠、组件配置是否一致、应用是否错误地依赖了某个临时 IP。
先看一次请求经过哪里
flowchart LR
A["客户端 Pod"] --> B["Service DNS"]
B --> C["ClusterIP"]
C --> D["kube-proxy 或 eBPF Service 转发"]
D --> E["EndpointSlice"]
E --> F["目标 Pod IP"]
F --> G["目标节点"]
这里至少有四类地址:
| 地址 | 由谁分配 | 是否直接绑定进程 | 主要用途 |
|---|---|---|---|
| Node IP | 物理网络、虚拟化平台或云平台 | 是 | 节点管理、跨节点承载 |
| Pod IP | CNI,例如 Calico | 是 | Pod 到 Pod 通信 |
| Service ClusterIP | kube-apiserver | 否 | 稳定虚拟入口和负载转发 |
| 外部入口 IP | LB、VIP、Ingress 或路由器 | 视实现而定 | 集群外访问 |
Kubernetes 官方网络模型要求 Node、Pod 和 Service 使用互不重叠的地址范围。Service 只是逻辑入口,后端由 EndpointSlice 持续更新。Cluster Networking 和 Service 对此有完整定义。
Node IP:数据包最终要到达的机器
kubectl get nodes -o wide
kubectl get node <node> -o jsonpath='{.status.addresses}'
Node IP 来自现有基础网络。Calico、kubelet、API Server、存储挂载和运维 SSH 都可能使用它。
规划时记录:
- 节点管理地址段。
- 默认网关和 MTU。
- 物理机或虚拟化宿主机故障域。
- 防火墙允许的 Pod 地址段。
- 是否存在 VPN、办公网或专线重叠。
不要为了“统一”把 Node IP 并入 Pod CIDR。它们位于不同网络层。
Pod CIDR:CNI 分配给工作负载
Pod CIDR 在 kubeadm 中常写为:
networking:
podSubnet: <pod-cidr>
Calico 也必须使用相同地址池:
kubectl get ippools.crd.projectcalico.org -o wide
kubectl get pod -A -o wide
每个普通 Pod 获得一个 Pod IP。Pod 重建后 IP 可能改变,因此:
- 不能把 Pod IP 写进 Nacos 配置。
- 不能让客户端保存某个 Pod IP。
- 应通过 Service 或 Headless Service 发现后端。
跨节点 Pod IP 不通时,优先检查 CNI 路由、封装模式、MTU 和 firewalld,而不是修改 Service DNS。
Service CIDR:没有网卡的虚拟地址池
Service CIDR 在 kubeadm 中常写为:
networking:
serviceSubnet: <service-cidr>
ClusterIP 不会像 Node IP 一样出现在某块网卡上。kube-proxy 的 iptables、IPVS,或 CNI 的 eBPF 数据面负责将它转发到 Endpoint。
kubectl get service -A -o wide
kubectl get endpointslice -A
Service CIDR 只应在集群内部使用。应用应该配置 DNS:
<service>.<namespace>.svc.cluster.local
而不是:
<cluster-ip>
Service 删除重建后 ClusterIP 可能变化,DNS 名称只要 Service 名和 namespace 不变就仍然有效。
CoreDNS 没有创建第四套业务网络
CoreDNS 监听 Kubernetes API,为 Service 和 Pod 生成 DNS 记录。普通 ClusterIP Service 的 DNS 最终解析为 ClusterIP;Headless Service 则返回后端 Pod IP。
kubectl run dns-check --rm -it --restart=Never \
--image=<approved-dns-image> -- \
nslookup <service>.<namespace>.svc.cluster.local
DNS 正常只证明名称能够解析,不代表:
- Service selector 正确。
- Endpoint 非空。
- 目标端口正在监听。
- kube-proxy 转发表正确。
因此还要继续检查:
kubectl -n <namespace> get service <service> -o yaml
kubectl -n <namespace> get endpointslice \
-l kubernetes.io/service-name=<service> -o wide
为什么不能把三类 IP 统一成一段
假设 Node、Pod 和 Service 使用重叠范围,一个目标地址可能同时被理解为:
- 本地二层网络中的某台服务器。
- 需要交给 Calico 的远端 Pod。
- 需要交给 kube-proxy 的虚拟 Service。
最终路由优先级可能把流量送到错误接口,常见现象包括:
No route to host
connect timed out
某些节点能访问,某些节点不能访问
访问一个 Service 却命中另一台真实主机
“统一”应该指统一规划和统一配置,而不是把所有用途塞进同一个 CIDR。
第 1 步:迁移前收集全部网络
创建 network-plan.csv:
type,cidr,owner,purpose,changeable
node,<node-cidr>,network-team,node-management,false
pod,<pod-cidr>,kubernetes-team,calico,true
service,<service-cidr>,kubernetes-team,clusterip,true
vpn,<vpn-cidr>,network-team,remote-access,false
还要收集:
kubectl -n kube-system get configmap kubeadm-config -o yaml
kubectl get service -A -o json
kubectl get pod -A -o wide
ip route
第 2 步:检查重叠
使用团队认可的 IPAM 或 CIDR 工具检查:
Pod CIDR ∩ Service CIDR = 空集
Pod CIDR ∩ Node CIDR = 空集
Service CIDR ∩ Node CIDR = 空集
三者 ∩ VPN/办公网/专线 = 空集
还要为未来扩容预留余量。不能只按当前 Pod 数计算;滚动发布、Job、DaemonSet 和故障漂移都会临时增加地址消耗。
第 3 步:冻结到版本化配置
至少固定:
manifests/kubeadm.yaml
manifests/calico.yaml
inventory/network-plan.csv
scripts/network-smoke.sh
在创建控制平面后临时修改 Pod CIDR 或 Service CIDR,通常不是普通配置变更,而是一次网络迁移。不要在业务启动期间尝试“顺手统一”。
第 4 步:执行四层冒烟
Pod 到 Pod
kubectl exec <source-pod> -- ping -c 3 <target-pod-ip>
Pod 到 ClusterIP
kubectl exec <source-pod> -- nc -vz <service-ip> <service-port>
Pod 到 Service DNS
kubectl exec <source-pod> -- \
nc -vz <service>.<namespace>.svc.cluster.local <service-port>
集群外到 Ingress
curl --resolve app.example.com:443:<ingress-address> \
https://app.example.com/<health-path>
测试 Pod 要覆盖不同节点,否则发现不了单节点 kube-proxy 或防火墙故障。
第 5 步:清理配置中的地址依赖
按以下规则治理:
| 发现的地址 | 处理方式 |
|---|---|
| Pod IP | 必须改为 Service |
| ClusterIP | 优先改为 Service DNS |
| Node IP + NodePort | 确认是否为必要外部入口 |
| Kafka broker 地址 | 单独处理 advertised listener |
| 外部数据库或专线 | 保留并登记所有者 |
不要盲目把所有 IPv4 字符串替换成 .svc.cluster.local。
完成定义
- Node、Pod、Service、VPN 和办公网地址段互不重叠。
- kubeadm 与 CNI 使用相同 Pod CIDR。
- 所有节点都具备正确的 Pod 路由和防火墙规则。
- 跨节点 Pod、ClusterIP、Service DNS 和 Ingress 冒烟通过。
- Kubernetes 内部应用不再依赖 Pod IP。
- 固定 ClusterIP 仅限经过评审的兼容白名单。
一个集群存在多段 IP 是正常设计;真正应该统一的是网络规划、配置来源和验证方法。
DISCUSSION
讨论与反馈