改 CIDR 这种操作平时没人愿意碰可真轮到要碰的时候基本都是网段规划埋下的雷炸了集群搭到一半发现 Pod 段和内网冲突、Service 段把公司的私有网段占了、或者两套环境要合并必须统一网段。Kubernetes 的 Pod CIDR 和 Service CIDR 一旦进入生产修改牵扯的就不是一个配置文件而是控制面、节点、CNI、kube-proxy、DNS、所有存量 Service 和 Pod 一整条链路。这篇文章把我完整做过的 Pod CIDR 与 Service CIDR 修改过程整理出来包含了每一步操作、验证手段、遇到过的坑和回滚思路。特别适合集群已经建好、业务已经跑着、但因为各种原因必须调整网段的运维同学参考。内容基于 kubeadm 部署的集群展开二进制部署的大方向一致细节我会单独标注。整体思路不复杂难的是顺序和耐心。1. 先说清楚改 CIDR 为什么不是改个参数那么简单很多第一次接触这个操作的人以为改 CIDR 就是去控制平面组件里把--cluster-cidr和--service-cluster-ip-range两个参数改一下重启完事。我在早期规划集群时也这么想过直到真正看了一遍集群里这些网段的作用链路才明白CIDR 其实是整个集群网络的地基改地基必须连带改地基上的每一层建筑。1.1 CIDR 在集群里到底串起了哪些组件先梳理一下 Pod CIDR 的完整作用链。kube-controller-manager的--cluster-cidr参数职责是给每个 Node 划分一个spec.podCIDR子网段。例如整个 Pod 网段是 10.244.0.0/16那么 controller-manager 拿到一台新节点就会从里面划一个 /24 给这台节点。这个信息写在 Node 对象上kubectl get node -o jsonpath{.items[*].spec.podCIDR}可以直接看到。CNI 插件拿到 Node 上的 podCIDR 之后才知道该给这台机器上的 Pod 从哪个子网里分配 IP。以 flannel 为例它会读取 Node 对象上的 PodCIDR并以此为基准创建 VXLAN 设备、维护路由表。Calico 则是通过 IPPool 和 Node 上的 podCIDR 建立映射关系然后下发 Felix 配置。kubelet在启动 Pod 时会通过 CNI 插件请求分配 IPCNI 再基于节点 PodCIDR 从对应的子网池里分配。所以如果只改了 controller-manager 的 cluster-cidr而没有同步调整 CNI 侧的数据和路由新 Pod 要么分到 IP 后网络不通要么直接分配不了 IP。Service CIDR 的作用链相对隐蔽一些。API Server 的--service-cluster-ip-range参数维护了一个 ClusterIP 分配池所有 Service 的 ClusterIP 都从这个池子里分配。kube-proxy 在 node 上监听 Service 和 EndpointSlice 的变化生成 iptables 或 IPVS 规则时需要知道 Service 的 ClusterIP 属于哪个网段以便做地址过滤和转发判断。CoreDNS 的 ClusterIP 也是在创建时从 Service CIDR 里分的一个固定地址DNS 解析依赖的就是这个地址。这样一看就明白了Pod CIDR 改的是 Node、CNI、路由、Pod 地址四层的东西Service CIDR 改的是 API Server 分配池、kube-proxy 规则、Service 存量对象、DNS 依赖四层的东西。任何一层漏掉整个集群就会出现局部不通或者分配异常的诡异现象。1.2 最容易被低估的两个链路在实际操作里有两条链路特别容易被低估。第一条是 CNI 的“网段边界”校验。flannel 在kube-flannel-cfgConfigMap 里有一项Network默认配置的是整个大网段比如10.244.0.0/16。flannel 的 backend 在校验 Pod IP 时会检查这个 IP 是否落在大网段范围内一旦 Pod 的 IP 不在范围内flannel 会直接报错拒绝启动。所以只改节点子网范围、不改大网段配置flannel 阶段就会直接失败。Calico 则相对灵活IPPool 是独立的 CRD 资源只要改动 IPPool 和节点分配策略即可不必像 flannel 那样强绑定一个全局 Network 字段。第二条是 controller-manager 划分 Node 子网的“格式”逻辑。--cluster-cidr10.244.0.0/16只是一个大范围具体给每个 Node 分配多大的子网取决于 controller-manager 的--node-cidr-mask-size参数。在 IPv4 集群里默认是 /24也就是说一个 /16 的大网段最多容纳 256 个节点。如果你的集群节点数超过这个大网段的按 mask 计算出的上限新节点会一直处于无 podCIDR 的状态调度上去的 Pod 全部无法创建。这个知识点在规划新网段时很重要改 CIDR 时最好连node-cidr-mask-size一并重新核对。所以改 CIDR 前脑子里必须画清楚这张链路图网段参数 → Controller-manager 划段 → Node 对象 → CNI 分配 → Pod 地址 → 路由/iptables 规则 → 应用访问。改的是参数实际动的是整条链路。2. 动手之前先摸清现状并确定迁移策略盲目改参数是最危险的改之前必须把集群当前的全部网段状态、安装方式、CNI 类型和业务依赖摸清楚。我一般按下面几条线去收集信息。2.1 收集当前网段全景信息先把正在使用的 Pod CIDR 和 Service CIDR 完整列出来这一步是后面所有判断的基础。# 查看当前 Node 上的 PodCIDR kubectl get nodes -o jsonpath{range .items[*]}{.metadata.name}{ - }{.spec.podCIDR}{\n}{end} # 查看所有 Service 的 ClusterIP 分布 kubectl get svc -A -o wide # 查看集群配置中声明的网段kubeadm 方式 kubectl -n kube-system get configmap kubeadm-config -o jsonpath{.data.ClusterConfiguration} | grep -A5 networking还需要确认 CNI 类型和配置# flannel 查看 ConfigMap kubectl -n kube-flannel get cm kube-flannel-cfg -o yaml # calico 查看 IPPool kubectl get ippool -A收集这些信息有一个额外目的判断当前集群到底是 kubeadm 初始化时一次性写好的网段还是后来手工改过的。如果集群初始化之后从未动过网络配置那么控制面组件的启动参数文件和 kubeadm-config ConfigMap 里的内容应该是一致的改起来相对好对应如果两处对不上说明有人手工改过参数必须以控制面真实生效的参数为准而不是以 ConfigMap 里的为准。2.2 明确停机窗口与风险边界改 Pod CIDR 和 Service CIDR 不是滚动操作它会打断集群内所有业务流量。以下是我实际做这类操作时确认过的影响边界改 Pod CIDR 后存量 Pod 的 IP 会全部变化。如果业务之间通过 Pod IP 直连很多微服务调用链没走 Service直接用了 Pod IP必须让业务方提前知道并配合切换。改 Service CIDR 后所有 Service 的 ClusterIP 都会变。ClusterIP 被写死在配置文件或注册中心里的服务需要同时改配置。这个影响面往往比 Pod IP 变化更广因为外部系统对接集群内服务时用的基本都是 Service 的 ClusterIP。改网段期间集群网络会处于不可用或半可用状态必须规划一个明确的窗口期并且预备好回滚路径。有状态应用、StatefulSet、数据库相关的服务宁可先停掉也不要强行迁因为 IP 变化对它们的数据面和会话保持影响很大。我的建议是一个测试集群或者说能容忍长时间停机的环境优先做一次完整演练把时间开销和意外情况都跑一遍。生产环境迁移时按照“先加新网段、再迁数据面、最后删除旧网段”的原则操作不要想着一刀切直接替换。2.3 确定本次迁移的类型不是所有情况都需要同时改动两个 CIDR。常见的组合和场景如下场景改动范围操作复杂度仅 Pod 网段冲突只改 Pod CIDRService CIDR 不变中等仅 Service 网段冲突只改 Service CIDRPod CIDR 不变中等两网段都需要调整同时改两个 CIDR高只是缩容或扩容CIDR 不变不需要改 CIDR改 node-cidr-mask-size 或 IPPool低评估完类型之后再决定采用“一次性替换”还是“双网段并行迁移”。多数生产环境我推荐双网段并行先把新网段配置进去让集群开始支持新网段的 IP然后把工作负载一批批迁移过去最后再剥掉旧网段。虽然这个方案的时间周期更长但它能在每一步都保留回退空间不至于一步错全部崩盘。3. 修改 Pod CIDR 的完整操作链路在 kubeadm 部署的集群里Pod CIDR 的修改核心落在四个地方controller-manager 启动参数、Node 对象上的 podCIDR、CNI 插件配置、节点上的路由与接口状态。下面按执行顺序拆开讲。3.1 修改 controller-manager 层面在控制平面节点上编辑 kube-controller-manager 的静态 Pod 清单vim /etc/kubernetes/manifests/kube-controller-manager.yaml找到--cluster-cidr参数改为新规划的 Pod 网段- --cluster-cidr10.250.0.0/16 - --node-cidr-mask-size24静态 Pod 的清单文件一旦发生变化kubelet 会自动检测并重启对应的容器不需要手动操作。重启后验证一下容器是否正常kubectl -n kube-system get pod | grep controller-manager从这以后新加入集群的 Node 会开始从新网段分配spec.podCIDR。但对于已经存在的 Node它们原来拿到的 podCIDR 不会自动更新需要手工处理。注意kubeadm-configConfigMap 里也保存了一份网段信息。如果集群后续会复用kubeadm upgrade apply这类工具建议同步更新 ConfigMap否则升级时可能重新把旧网段带回来过一次kubectl -n kube-system edit configmap kubeadm-config在data.ClusterConfiguration.networking下把podSubnet改成新网段。3.2 逐台处理节点上的 podCIDR 和 CNI 数据处理存量节点最稳妥的方式是逐台操作而不是一次性全部改动。下面以其中一台节点 worker-01 为例。第一步驱逐节点上的全部工作负载kubectl drain worker-01 --ignore-daemonsets --delete-emptydir-data执行 drain 后节点上的 Pod 会被调度到其他节点但节点本身仍是 Ready 状态。此时如果改掉了它的 podCIDR原有 Pod 已经不在节点上了不会产生并发干扰。第二步删除节点上现有的 CNI 配置和虚拟网络数据。这一步是很多人体会不到“只是改配置但网络不动”的直接原因。以 flannel 为例节点上残留的cni0、flannel.1接口和/var/lib/cni/下的旧缓存必须清理否则新 Pod 启动时CNI 会拿着旧接口状态和旧路由继续干活rm -rf /var/lib/cni/networks/* rm -rf /var/lib/cni/state ip link delete cni0 ip link delete flannel.1如果是 Calico 集群则不需要删除这些接口但需要确认该节点的felix配置和 IPPool 分配情况必要时删除旧 binding 记录让 Calico 重新为该节点分配新网段的 IP。Calico 的清理动作我更倾向于在 IPPool 层面做# 先确认旧的 IPPool 和新网段的 IPPool 同时存在 calicoctl get ippool第三步修改节点对象上的spec.podCIDRkubectl patch node worker-01 --typejson -p[{op:replace,path:/spec/podCIDR,value:10.250.1.0/24}]也可以直接kubectl edit node worker-01修改spec.podCIDR。这里有一个细节controller-manager 的--cluster-cidr改完之后新 Node 会自动拿到新网段但旧 Node 的spec.podCIDR是历史分配结果不会自动重算所以手动 patch 是必须的。第四步uncordon 节点并让工作负载重新调度回来kubectl uncordon worker-01新调度到该节点的 Pod其 IP 会从新的 podCIDR 子网分配。3.3 修改 flannel 或 Calico 的全局网段边界这一步漏掉的话最常见的现象就是Pod 创建成功但一直 ContainerCreatingkubectl describe pod里报 CNI 插件分配地址失败。flannel 集群需要通过 ConfigMap 修改它的全局 Network 字段kubectl -n kube-flannel edit cm kube-flannel-cfg把 net-conf.json 里的Network改为和新的 Pod CIDR 一致{ Network: 10.250.0.0/16, Backend: { Type: vxlan } }改完 ConfigMap 之后需要重启每一台节点上的 flannel DaemonSet Pod让新的网络配置生效kubectl -n kube-flannel rollout restart daemonset kube-flannel-dsCalico 集群则需要创建新的 IPPool并且把节点分配策略切到新 IPPool 上cat EOF | kubectl apply -f - apiVersion: crd.projectcalico.org/v1 kind: IPPool metadata: name: new-pod-cidr spec: cidr: 10.250.0.0/16 ipipMode: Never natOutgoing: true disabled: false nodeSelector: all() EOF老 IPPool 先不要删除保证存量 Pod 还在跑等所有 Pod 迁出旧网段后再禁用并删除旧 IPPool。3.4 验证 Pod 网段切换是否真的生效改完全链路之后不能只看 Pod 在 Running 就认为成功了我习惯用下面四条命令做完整验证# 1. 确认节点上的 podCIDR 已经切到新网段 kubectl get nodes -o jsonpath{range .items[*]}{.metadata.name}{ - }{.spec.podCIDR}{\n}{end} # 2. 在集群内起一个测试 Pod看它的实际 IP kubectl run nettest --imageregistry.local/busybox:1.36 -- sleep 3600 kubectl get pod nettest -o wide # 3. 新增 Pod 的 IP 必须在新的子网范围内 # 4. 从任意一个 Pod 去 ping 不同节点上的其他 Pod验证跨节点通信 kubectl exec nettest -- ping -c 2 另一个节点的 Pod IP这一步最容易出现的故障是 Pod 能起来、IP 也是新网段但跨节点通信不通。原因是 CNI 数据面清理不彻底旧路由残留。如果遇到这个问题回到对应节点再执行一次ip route和ip -d link对比新旧网段的路由和接口是否同时存在清理干净后重启该节点的 flannel Pod 一般能解决。4. 修改 Service CIDR 的完整操作链路Service CIDR 的修改比 Pod CIDR 更“伤筋动骨”因为 ClusterIP 一旦重新分配所有存量 Service 对象都必须重建。下面说清楚我怎么安全地做这一步。4.1 修改 API Server 的 service-cluster-ip-rangekubeadm 部署的集群API Server 同样是静态 Pod 清单。编辑/etc/kubernetes/manifests/kube-apiserver.yaml修改--service-cluster-ip-range参数- --service-cluster-ip-range10.252.0.0/16同时更新 kubeadm-config ConfigMap 里的serviceSubnet字段避免后续升级工具覆盖回来。保持其他参数不动保存文件等待 kubelet 自动重建 API Server Pod。API Server 本身是一个集群的命脉重启时要注意两点。第一不要手动删除 API Server Pod等待静态 Pod 自动滚动重建即可第二重启完成后立刻查看日志确认 API Server 启动正常。如果新网段不合法或者格式有问题API Server 会直接启动失败这时候必须快速回滚清单文件。此前的 Service 对象仍然在使用旧 ClusterIPAPI Server 不会自动给它们重新分配。所以接下来的工作就是“重建所有 Service”。4.2 重建 CoreDNS 等系统级 Service系统级 Service 里最核心的是 CoreDNS。它自身的 ClusterIP 是从 Service CIDR 里分配的旧地址在新 CIDR 下已经失效必须删除重建。kubectl -n kube-system get svc kube-dns -o yaml coredns-svc-backup.yaml kubectl -n kube-system delete svc kube-dns kubectl -n kube-system apply -f coredns-svc-backup.yaml删除重建后CoreDNS 会拿到一个新的 ClusterIP。这里有个连锁反应所有节点上的 kubelet 配置里clusterDNS字段指向的是旧 CoreDNS ClusterIP。如果 kubelet 的配置是集群初始化时通过 kubeadm 写入的那么这个配置也需要一起更新否则节点上所有 Pod 的 DNS 解析都会失败。查看和更新 kubelet 配置# 在每台节点上查看 cat /var/lib/kubelet/config.yaml | grep clusterDNS # 改为新 CoreDNS 的 ClusterIP # 例如 clusterDNS: [10.252.0.10]改完之后重启 kubeletsystemctl restart kubelet这一步最容易踩坑的地方在于原本 CoreDNS 的 ClusterIP 可能不是标准配置里的10.96.0.10而是某个自定义地址。有些集群管理员会以为改完 API Server 参数后 CoreDNS 的 ClusterIP 会自动改变实际上 Service 是创建在旧地址上的如果不删除重建永远拿到的是旧 IP。对于 metrics-server、ingress-nginx 这类同样运行在 kube-system 下的服务检查方式一致所有ClusterIP落在旧 Service CIDR 里的 Service都需要按“导出清单-删除-重新应用”的流程处理。4.3 重建业务命名空间下的存量 Service业务侧 Service 的重建思路和系统级一致但更需要小心。因为业务 Service 可能带有复杂的 selector、externalIPs、nodePort 等配置个别 Service 可能还手动指定过 ClusterIP。对于手动指定过 ClusterIP 的 Service如果指定的 IP 不在新 CIDR 范围内重建时会直接报错必须在 YAML 里把spec.clusterIP字段删掉让 API Server 自动分配。我来给一个通用的批量重建思路# 1. 导出所有命名空间下的 Service 清单 kubectl get svc -A -o yaml all-services-backup.yaml # 2. 批量删除业务命名空间下的 Service建议按命名空间分批 kubectl -n namespace delete svc --all # 3. 重新应用原清单需过滤掉 clusterIP 字段中旧网段的地址 kubectl -n namespace apply -f all-services-backup.yaml --namespacenamespace实际上kubectl apply直接使用导出的 YAML 会有问题因为导出内容里包含了status和clusterIP等字段。我一般建议用kubectl get svc name -o jsonpath{.spec}提取核心 spec再手工组装一个干净的 Service YAML 重新应用。如果 Service 数量很大可以写一个脚本对全部 Service 做“提取 spec、删除 clusterIP、重新创建”的流程化处理。重建 Service 后所有工作负载与 Service 通信时使用的 ClusterIP 都会变。外部依赖如果写死了 ClusterIP必须同步更新如果是通过 DNS 名称访问只要 CoreDNS 正常业务侧不需要额外变更。4.4 kube-proxy 的配置和规则清理kube-proxy 在每台节点上有一个 ConfigMapkube-proxy里面也有clusterCIDR字段。这个配置用于 kube-proxy 判断 Service 所属网段虽然 kube-proxy 本身更多依赖动态监听 Service 对象但配置里保留旧网段会带来潜在隐患。kubectl -n kube-system edit cm kube-proxy更新clusterCIDR字段为新网段然后滚动重启 kube-proxy DaemonSetkubectl -n kube-system rollout restart daemonset kube-proxy如果之前使用的是 iptables 模式节点上会残留大量旧 ClusterIP 对应的 iptables 规则。虽然 kube-proxy 重启后会自动清理与现有 Service 不对应的规则但我见过一些残留规则导致访问异常的情况。稳妥起见在所有 Service 重建完成、业务验证正常情况下可以清理一次 iptables 中的 kube-proxy 自定义链iptables -t nat -F KUBE-SERVICES iptables -t nat -F KUBE-NODEPORTS注意这个清理只能在 kube-proxy 正常运行且 Service 已全部重建后进行否则会把当前有效规则也清掉立刻引发大规模网络故障。如果你觉得这一步风险过高可以直接跳过重建所有 Service 后 kube-proxy 自己会生成一套新规则残留旧规则一般不影响新 Service 的转发。5. 踩坑清单那些反复出现的问题这类迁移的坑有很强的共性我把实际操作中反复踩到的几个单独拉出来说每个都是血泪教训。5.1 新网段直接冲突但没提前测最常见的场景是规划了一个新网段觉得没问题就直接改改完发现宿主机所在内网网段正好命中了新 Pod 网段或者 Service 网段。比如新 Pod 网段选 10.250.0.0/16宿主机自己的管理网也是 10.250.0.0/16 的一部分CNI 的 VXLAN 流量和宿主机的管理流量立刻打架。预防方法很简单改之前在所有节点上跑一遍ip addr ip route确认新网段和所有节点的物理网卡、路由表没有交集。这条我放在第一因为它是唯一一个能从根源上避免的坑后面其他坑都只能补救。5.2 CoreDNS 重建后 Pod 还是解析失败这个坑我已经见过三次了。现象是 CoreDNS Pod 一直在 Running但所有 Pod 解析集群内 Service 都失败报错信息是server misbehaving或者直接超时。排查到最后原因基本都指向同一个点kubelet 的clusterDNS没有更新还在用旧 CoreDNS ClusterIP。这个坑之所以阴险是因为 DNS 访问超时或 failfast 的报错五花八门不会直接提示“kubelet config 指向的 DNS 失效”。所以我的建议是把 CoreDNS 重建和 kubelet clusterDNS 更新绑在一起做重建完 CoreDNS 立刻检查所有节点上的 kubelet config确认集群里每一台节点包括控制面节点的clusterDNS都指向新的 ClusterIP。for node in $(kubectl get nodes -o name | cut -d/ -f2); do echo $node ssh $node grep clusterDNS /var/lib/kubelet/config.yaml done5.3 手动指定 clusterIP 的 Service 重建时报错有些老项目在创建 Service 时习惯手动指定 clusterIP比如写成了clusterIP: 10.96.0.50。新 CIDR 范围是 10.252.0.0/16这个 IP 不在范围内重建时 API Server 会直接拒绝。更隐蔽的是有些 YAML 是从kubectl get svc -o yaml导出的里面老 clusterIP 被原样带出来重新 apply 也会报错。我的做法是写脚本把每个 Service 的spec.clusterIP字段清掉再 apply。如果你不想写脚本也可以手动编辑每个 Service 的 YAML删掉clusterIP行再重新应用。5.4 只改 Pod CIDR 但忘记清理 CNI 缓存只改 Pod CIDR 的场景下很多人会把各个参数都改好但忘了 CNI 在节点上留下的缓存。结果新 Pod 调度到节点上后CNI 插件拿着旧缓存继续工作分配出来的 IP 还是旧网段。这个现象和 flannel 配置没改很像排查起来比较费时间。解决方案我在前文写过drain 节点后删除/var/lib/cni/下的内容删除旧的虚拟网卡接口再重新调度 Pod。这是“逐节点处理”环节里最关键的一步不要跳。5.5 回滚预案要预演到命令级别CIDR 修改这种操作回滚不是简单改回参数就完事。我建议在动手之前把下面这些信息整理成文件存档所有节点当前的 podCIDR 列表kube-controller-manager.yaml、kube-apiserver.yaml 的原始内容kubeadm-config ConfigMap 的原始内容所有 Service 的完整 YAML 备份CoreDNS 的 Service YAML 备份kube-flannel 或 Calico 的配置备份一旦发现新网段问题无法短期内解决就按备份逐项回滚。回滚的执行顺序是从控制面参数回滚开始再回滚节点 podCIDR再回滚 CNI 配置最后恢复 Service。整个回滚过程同样需要停机窗口。6. 验证工作的最后一公里这部分单独说一下验证细节。前面几章已经穿插了一些验证命令但完整的验收逻辑值得串一遍。6.1 静态验证检查集群层面所有网段是否统一kubectl get nodes -o jsonpath{range .items[*]}{.metadata.name}{ - }{.spec.podCIDR}{\n}{end} kubectl get svc -A -o custom-columnsNS:.metadata.namespace,NAME:.metadata.name,CLUSTERIP:.spec.clusterIP新 Pod 网段范围内不应再有旧 IP 的 Service ClusterIP新 Service 网段范围内不应再有旧 Pod 网段地址。6.2 动态验证动态验证要覆盖三类访问路径Pod 到 PodPod 到 Service外部到 Service。Pod 到 Pod 的验证方法起两个分布在节点 A 和节点 B 的测试 Pod互相 ping 和 curl。Pod 到 Service 的验证方法在 Pod 里访问新 CoreDNS 的 ClusterIP 做 DNS 解析再访问业务 Service 的名称解析。外部到 Service 的验证则要看 Service 类型如果是 NodePort对外访问地址不变宿主机 IP端口只需要验证新规则是否生效如果是 LoadBalancer则需要配合云平台侧确认后端实例抓取是否正常。6.3 持续观察网段切换后的一段时间内建议盯着这几个指标CoreDNS 解析成功率、kube-proxy sync 是否有异常日志、CNI 插件是否持续报分配失败、节点上是否有大量容器反复重启。任何一项出现异常都要立即对应该项涉及的链路去排查不要等业务方报障。我在一次实际迁移中就是在切换后的几小时里发现有个节点上的 flannel Pod 反复 CrashLoopBackOff排查下来发现是该节点没有正确清理旧路由和新的 VXLAN 接口冲突手动清理后重启恢复。如果当时直接下班第二天必然是一堆应用报网络异常。7. 最后分享几组实用的命令不同安装方式和网络方案之下命令会有差异。以下命令组合基本覆盖了 kubeadm 集群的常见场景推荐收藏备用。7.1 一键导出所有关键网络配置备份# 一次性备份控制面和网络组件配置 mkdir -p /backup/k8s-net-$(date %Y%m%d%H%M%S) cd /backup/k8s-net-$(date %Y%m%d%H%M%S) cp /etc/kubernetes/manifests/kube-controller-manager.yaml . cp /etc/kubernetes/manifests/kube-apiserver.yaml . kubectl -n kube-system get cm kubeadm-config -o yaml kubeadm-config.yaml kubectl -n kube-system get cm kube-flannel-cfg -o yaml kube-flannel-cfg.yaml kubectl -n kube-system get cm kube-proxy -o yaml kube-proxy.yaml kubectl get svc -A -o yaml all-services.yaml7.2 批量重建除系统级之外的 Service# 备份并重建指定命名空间的 Service去掉 .status 和 .metadata.uid/resourceVersion kubectl get svc -n my-ns -o json | jq .items[] | {metadata: {name: .metadata.name, namespace: .metadata.namespace}, spec: .spec} | .spec.clusterIP null svc-clean.json kubectl delete svc -n my-ns --all # 手工拆分 json 后逐一 apply或使用 kubectl apply -f svc-clean.json7.3 快速检查 DNS 是否全局可用kubectl run dnstest --imageregistry.local/busybox:1.36 --rm -it --restartNever -- nslookup kubernetes.default.svc.cluster.local如果这条命令返回正常解析结果说明 CoreDNS 和 kubelet 的 clusterDNS 配置已经对齐系统级 DNS 链路基本可用了。7.4 快速检查全集群节点路由一致性# 在每台节点上执行 ip route | grep -E 10\.250\.|10\.252\.检查新网段的路由是否在每台节点上都存在且没有旧网段的残留路由。以我的经验来说这类网络调整方案很难第一次就100%顺畅但只要把链路理解清楚、备份做全、逐步推进每次都能在预定的窗口内恢复稳定。改完网段之后的那段时间人会不自觉地反复看监控和数据面日志这种“心里没底”的感觉恰恰说明你在意的是什么。