文章目录一、背景灰度发布前的例行变更二、完整时间线从变更到全站网络分割2.1 时间线均为北京时间2.2 每一步发生了什么三、根因分析不是一条路由的问题是三层网络的联动失效3.1 根因链3.2 为什么申请单上写着预计影响无3.3 三个技术层面的失效点四、诊断命令汇总事故中用到的每一条命令4.1 路由层诊断4.2 DNS 层诊断4.3 连接状态层诊断4.4 服务发现层诊断4.5 连接池层诊断五、反思网络变更应该怎么做5.1 路由变更的完整检查清单5.2 变更窗口的灰度策略5.3 为什么网络变更特别需要变更隔离六、预防措施从这次事故中学到的6.1 技术层面的改进6.2 组织层面的改进七、尾声从故障复盘到防御体系核心问题一次不谨慎的 VPC CIDR 调整如何引发了全站网络分割路由变更的连锁反应是如何一步步传导的一、背景灰度发布前的例行变更某中型互联网公司Kubernetes 集群规模约 200 个节点业务覆盖华东和华南两个区域采用阿里云 VPC 网络架构。2026 年 6 月 19 日网络团队发起了一项例行变更为即将上线的新微服务网段10.20.0.0/16添加 VPC 路由表条目允许集群节点访问新网段的 API Gateway。变更申请单内容变更类型网络路由新增 涉及范围VPC 主路由表 变更内容新增路由 10.20.0.0/16 → NATGW-xxxxNAT 网关 变更时间2026-06-19 14:00 ~ 14:30 预计影响无 审批人网络团队负责人 抄送应用运维申请单上写着预计影响无——这是整个事故的起点。二、完整时间线从变更到全站网络分割2.1 时间线均为北京时间14:00变更执行添加 10.20.0.0/16 路由14:03部分 Pod 无法解析内网 DNSCoreDNS 超时14:05华东区 API Gateway 报错上游服务全部不可达14:08应用运维接到告警尝试重启 CoreDNS Pod14:12重启后短暂恢复14:14 再次崩溃14:15数据库连接池异常连接超时14:18灰度发布被紧急中止14:22网络团队确认 NAT 网关路由异常14:35回滚 10.20.0.0/16 路由14:38服务完全恢复2.2 每一步发生了什么14:00 —— 变更执行网络工程师在阿里云控制台为主路由表新增了一条路由目标网段10.20.0.0/16 下一跳类型NAT 网关NATGW-xxxx这看似是一条无害的路由添加——只是告诉 VPC去 10.20.0.0/16 的包走 NAT 网关。然而阿里云 VPC 的路由表中已经存在一条默认路由目标网段0.0.0.0/0 下一跳类型NAT 网关NATGW-xxxx14:03 —— CoreDNS 解析超时CoreDNS Pod 尝试解析一个内网服务的域名inventory.prod.svc.cluster.local。解析路径是应用 Pod → kubedns本地 DNS 缓存→ CoreDNS集群 DNS 服务→ 上游 DNSVPC DNS 168.63.129.16CoreDNS 向 VPC 内网 DNS168.63.129.16发起递归查询时包需要经过 NAT 网关出公网再回来——而 NAT 网关此时正同时处理新网段的路由和原有的 DNS 递归返回流量出现了路由优先级冲突。根因VPC DNS 的回程路由经过 NAT 网关而 NAT 网关同时处理了新的10.20.0.0/16路由。阿里云路由表中存在双重 default 路由的隐性冲突新网段路由和 NAT 网关 default 路由都指向同一个 NAT 网关导致 NAT 网关的 SNAT 表源地址转换表溢出。这一步的诊断关键命令# 在节点上查看 DNS 解析路径的每一步延迟digtrace all inventory.prod.svc.cluster.local 168.63.129.16# 查看 NAT 网关的 SNAT 连接表使用量阿里云控制台 → NAT 网关 → 监控# 如果 SNAT 连接数接近规格上限说明 SNAT 表溢出了14:05 —— 上游服务不可达当 CoreDNS 解析超时后应用 Pod 的 Kubernetes Service 域名无法解析。Kubernetes Service 的 DNS 解析是延迟绑定的——解析失败时Envoy/Istio Sidecar 无法获取目标 endpoint只能返回 503。应用 Pod → Envoy Sidecar15001→ DNS 解析 inventory.prod.svc.cluster.local ↓ 超时3s 默认 ↓ 无 endpoint 返回 ↓ HTTP 50314:08 ~ 14:14 —— 短暂恢复后再次崩溃应用运维尝试重启 CoreDNS Pod 以刷新 DNS 缓存。CoreDNS Pod 重启后短暂恢复了 DNS 解析因为新的 CoreDNS Pod 重新建立了到 VPC DNS 的连接但由于 NAT 网关的 SNAT 资源仍未释放30 秒后再次触发连接超时。14:15 —— 数据库连接池异常上游服务API Gateway长期调用超时连接池中的 HTTP 连接被长时间占用无法释放。当数据库连接请求到达时连接池已经没有可用连接——连接池满触发了快速失败fail-fast策略直接拒绝新请求。数据库连接池max100 ├─ 业务请求占用 85 个等待上游响应 ├─ 空闲连接 15 个 └─ 新请求 20 个 → 15 个成功5 个被拒绝pool exhausted14:18 —— 灰度发布紧急中止由于所有区域的服务健康检查都在失败灰度发布流水线自动触发了中止条件——这是 CI/CD 流水线中服务健康检查不通过自动回滚机制的正确触发说明该机制在这次事故中没有让故障进一步扩大。14:22 —— 根因定位网络团队在阿里云控制台发现主路由表中除了原有的0.0.0.0/0default 路由外新增的10.20.0.0/16路由覆盖了原有 NAT 网关的流量路径——新网段路由与 NAT 网关 default 路由存在隐性竞争关系导致 NAT 网关的 SNAT 表资源异常消耗。14:35 —— 回滚删除10.20.0.0/16路由条目服务开始逐步恢复。14:38 —— 完全恢复三、根因分析不是一条路由的问题是三层网络的联动失效3.1 根因链根因VPC 路由表变更新增 10.20.0.0/16 → NAT 网关第一层NAT 网关 SNAT 表溢出默认路由 新网段路由同时竞争同一个 NAT 网关的 SNAT 资源第二层VPC DNS 递归查询失败CoreDNS 的上游查询无法返回第三层Kubernetes Service DNS 解析失败域名无法解析为 Pod IPendpoint 为空第四层Envoy/Istio Sidecar 无法路由无 endpoint → HTTP 503第五层数据库连接池耗尽上游超时 → 连接占用 → 新请求被拒第六层全站服务降级API Gateway、支付、订单等依赖链全线崩溃3.2 为什么申请单上写着预计影响无这是整个事故中组织层面最值得反思的点网络团队的变更申请单只评估了新网段能不能通没有评估这条路由会不会影响 NAT 网关的既有流量。具体来说路由优先级评估缺失。阿里云 VPC 路由表中最长前缀匹配LPM原则决定路由选路——10.20.0.0/16比0.0.0.0/0更精确理论上应该优先走新路由。但 NAT 网关的 SNAT 表资源是共享的新旧流量同时到达同一个 NAT 网关造成了 SNAT 连接数超出规格上限。DNS 依赖链未纳入评估。变更申请没有评估 CoreDNS 对 VPC DNS 的依赖路径——DNS 解析失败是这次事故的第一个可见症状但申请单中完全没有提到 CoreDNS 或 DNS 相关的服务。跨团队通知流于形式。变更抄送了应用运维但应用运维只看到了抄送没有理解这条变更会如何影响 CoreDNS 和 Service 间的 DNS 解析。3.3 三个技术层面的失效点失效点一路由变更与 DNS 递归的隐式耦合VPC DNS168.63.129.16的响应包返回路径依赖 NAT 网关。当 NAT 网关 SNAT 表溢出时响应包无法正确返回CoreDNS 的上游查询一直等待最终超时。大多数工程师知道VPC DNS 在内网不需要 NAT 网关——但这个认知是基于 SNAT 资源充足的前提的。一旦 NAT 网关的 SNAT 连接数接近上限所有经过该 NAT 网关的出站流量都会受影响。失效点二健康检查未能提前发现Kubernetes ReadinessProbe 和 livenessProbe 都是针对 Pod 自身的检查HTTP 探测端口不检查 Pod 到核心依赖CoreDNS、数据库的连通性。这意味着即使 CoreDNS 已经解析超时Pod 自身的健康检查仍然通过Kubernetes 不会主动驱逐这个 Pod。失效点三灰度发布流水线的健康检查阈值灰度发布流水线的健康检查默认等待 3 分钟initialDelaySecondsperiodSeconds × failureThreshold。在这 3 分钟内CoreDNS 已经反复重启了一次但流水线仍在等待。如果健康检查阈值更严格例如 60 秒内失败 2 次立即回滚可以在第一轮 CoreDNS 崩溃时就中止灰度发布。四、诊断命令汇总事故中用到的每一条命令4.1 路由层诊断# 确认节点的路由表验证变更是否已生效iprouteiproute show table all# 验证到目标网段的路由路径iproute get10.20.0.1# 检查是否有重复的 default 路由iproute show|grep-Edefault|^0\.0\.0\.0# 阿里云查看 VPC 路由表OpenAPIaliyun vpc DescribeRouteTables--VpcIdvpc-xxxx4.2 DNS 层诊断# DNS 递归查询的完整路径trace 输出每一跳digtrace all inventory.prod.svc.cluster.local# 查看 CoreDNS 的实时查询延迟进入 CoreDNS Pod 执行kubectlexec-nkube-system deploy/coredns -- coredns-dig metrics# 或直接看 CoreDNS 日志kubectl logs-nkube-system deploy/coredns-f|greptimeout# 验证 VPC DNS 是否可达dig168.63.129.16 kubernetes.default.svc.cluster.local4.3 连接状态层诊断# 查看当前节点的 SNAT 连接数阿里云 NAT 网关监控# 控制台路径NAT 网关 → 监控 → SNAT 连接数# 查看节点上的 NAT 转发状态cat/proc/net/nf_conntrack|grepNAT# 查看 NAT 表溢出时的内核日志dmesg-T|grepnf_conntrack|tail-20# 如果看到 nf_conntrack: table full, dropping packet# 说明连接跟踪表已满这是 NAT 网关 SNAT 溢出的内核层表现4.4 服务发现层诊断# 查看某 Service 的 endpoint 是否存在kubectl get endpoints inventory-nprod# 如果 endpoint 为空说明没有 Pod 被 Kubernetes 选中可能是 DNS 解析失败# 对比有 endpoint 时的状态kubectl get endpoints nginx-ndefault# 查看 Consul如果使用 Consul 做服务注册的健康检查状态consul services health-namespaceprod# 如果显示 critical说明 Consul 健康检查也在失败4.5 连接池层诊断# 查看数据库连接池状态假设使用 PgBouncerpsql-hlocalhost-p5432-Upgbouncer-cshow pools# 查看应用层的连接等待时间应用 metricscurl-slocalhost:9090/metrics|grepconnection_pool_wait_time# 如果该指标持续上升说明连接池正在积压等待请求五、反思网络变更应该怎么做5.1 路由变更的完整检查清单在执行任何 VPC 路由表变更之前应该逐项检查检查项1. 新路由是否与现有路由重叠2. 新路由的下一跳NAT 网关/网关的规格是否支撑总流量3. NAT 网关的SNAT/DNAT 连接数是否有余量4. 核心依赖CoreDNS/数据库/缓存的出站路径是否经过该 NAT 网关5. DNS 递归查询的返回路径是否会受到变更影响检查项一路由重叠。用最长前缀匹配原则验证新路由不会意外覆盖重要流量。检查项二NAT 网关规格。SNAT 连接数有规格上限阿里云 NAT 网关 Basic 版默认每秒新建连接数 10 万最大并发连接数 100 万。如果新流量预计超过规格的 50%应该提前扩容或分流。检查项三核心依赖的出站路径。这一步最容易被忽略——CoreDNS、数据库、Redis 的健康检查请求都经过 NAT 网关如果 NAT 网关 SNAT 表满这些健康检查全部超时。5.2 变更窗口的灰度策略对于涉及网络路由的变更建议采用以下灰度策略第一步先在测试 VPC 验证不连接生产网络在独立的测试 VPC 中添加相同的路由规则验证 NAT 网关规格是否足够。第二步在非核心命名空间先执行影响范围最小先在测试命名空间执行变更观察 CoreDNS 日志是否有异常kubectl logs -n test deploy/coredns | grep timeout。第三步生产环境分区域执行先在单个可用区AZ的节点上执行变更观察 5 分钟后确认无异常再推广到全量节点。第四步回滚预案必须提前验证变更前必须验证回滚命令能在 2 分钟内完成执行。这次事故的回滚耗时 3 分钟14:22 确认根因到 14:35 完成回滚大部分时间花在确认哪条路由是罪魁祸首上——如果申请单中记录了每条路由的上线时间和审批人确认根因只需要 2 分钟。5.3 为什么网络变更特别需要变更隔离网络层与业务层的本质区别在于网络是所有业务的前置依赖。Linux 内核参数调错影响的是当前节点上的进程网络路由配置错误影响的是所有跨节点通信——包括 DNS 解析、服务注册、健康检查、数据库连接等。这意味着网络变更的错误成本远高于普通应用变更。应对策略不是更加谨慎而是隔离执行每次网络变更影响的节点数量要严格控制变更窗口要有硬性的观察期回滚时间要纳入 SLO 计算。六、预防措施从这次事故中学到的6.1 技术层面的改进改进项具体措施验证方式NAT 网关 SNAT 监控告警当 SNAT 连接数超过规格 70% 时触发 P2 告警超过 90% 时触发 P1 告警模拟 NAT 网关高负载场景验证告警是否及时触发CoreDNS 健康检查增强在 CoreDNS 的 health check 中增加对168.63.129.16:53的探测不仅仅是 HTTP 探测kubectl exec deploy/coredns -- wget -q -O- http://168.63.129.16:53DNS 解析的熔断机制应用侧设置 DNS 解析超时建议 ≤ 2s和重试策略最多 2 次在 DNS 解析超时的场景下验证重试逻辑是否生效灰度发布健康检查收紧健康检查失败 2 次间隔 30s即触发自动回滚而非等待 3 分钟修改流水线配置后执行一次模拟演练6.2 组织层面的改进一、变更申请需要包含影响路径分析路由变更申请必须附上受影响的 NAT 网关及其 SNAT 连接数当前使用量CoreDNS 到 VPC DNS 的路径依赖说明需要通知的团队不能只抄送要确认对方已阅读并理解二、网络团队和应用团队的联合 Review涉及 NAT 网关或 VPC 路由表的所有变更必须由网络团队和应用团队的 SRE 共同 Review。特别是 NAT 网关规格的变化SNAT 连接数这是大多数变更申请中最容易被忽视的指标。三、变更文档化每条上线的路由都必须记录上线时间、审批人、变更原因、回滚命令。事故发生时3 分钟的排查时间有一半浪费在确认’哪条路由是罪魁祸首’上——这个成本本可以通过文档化完全消除。七、尾声从故障复盘到防御体系这次事故的根因不是一条路由配置错误而是网络层与 DNS 层、服务发现层之间的隐式依赖从未被显式管理。当任何一个前置依赖出现问题时级联影响从故障发生到被发现之间存在 3 分钟以上的延迟窗口——这段时间足够让一个原本局部的故障演变成全站网络分割。整个网络与安全系列始终围绕一条核心叙事线展开排查即线索。TCP 连接失败不是连接不上是队列溢出还是端口耗尽DNS 解析失败不是域名解析不到是上游 DNS 超时还是本机 DNS 缓存被污染网络路由变更也不只是加一条路由是 NAT 网关 SNAT 资源、CoreDNS 依赖路径、连接池状态的联动。掌握这些细节就是在掌握网络故障的主动权。