首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >一次 Ingress 重复报错引发的思考:内网从域名到 Pod 的全链路与根因分析

一次 Ingress 重复报错引发的思考:内网从域名到 Pod 的全链路与根因分析

作者头像
Wangzy
发布2026-06-22 19:20:06
发布2026-06-22 19:20:06
100
举报

前记:上周公司内部一次变更引出了在生产环境的k8s的一个部署因为ingress 重复发现的一个报错,复盘下来觉得有必要把整个过程给整理下来,顺便也让自己了解下从客户端发起对主域名的接口请求,是如何一步一步最终请求到k8s的pod。

不同公司的架构可能不一致,这里仅针对笔者公司的架构做一个梳理,顺带对目前架构优化的一些思考总结,如果文中有不对的地方,也欢迎各位老师批评指正。

起因是机房 A 里有一条重复的 Ingress:新旧两条可以并存,已经并存运行了好几年了,期间也有一些巡检通知,但巡检通知始终没有触达到应用负责人,所以这个问题点一直没被发现,线上的流量走的是那条老 Ingress,工作得好好的。

所以本文我想把内网这条「从主域名到 Pod」的链路,连同它背后的管理体系,系统地捋一遍。这篇就分四块来讲:

  1. K8s 内网管理:用 Wayne、再套一层自研页面,到底合不合理?企业级最佳实践是什么?
  2. 内网流量全链路:主域名 → GSLB → SLB → Ingress → Service → Pod,每一跳都干什么。
  3. Ingress 最佳实践与未来:包括那句「重复」报错从哪来,以及 ingress-nginx 退役后该往哪走。
  4. 全链路监控与根因分析:怎么发现入口异常,又怎么进一步快速定位到根因。

一、Wayne 之上再套一层自研页面,到底合不合理?

笔者所在公司一开始引入的是开源 Wayne 作为 Kubernetes 管理入口,再叠加一层公司内部自研平台,而底层应用仍主要以 Deployment、ConfigMap、Ingress、Service 这些原生对象为核心来管理。

很多人第一反应是「套这么多层,是不是过度设计」。但笔者研究下来,结论没那么简单——问题的关键不是「用没用 Wayne」,而是「管理入口和控制入口有没有解耦」。

1.1 先说 Wayne 这一层

Wayne 是 360 开源的多集群 Kubernetes 管理平台,覆盖了多集群、访问控制、发布管理与审计,本身是个不错的东西。但它有一个现实问题:公开 release 基本停在 2020 年初,技术基线偏老。所以更合适的定位是:把它当成一个过渡期的控制面,而不是未来几年企业平台能力的核心支点。

1.2 真正的病根:「双平台」

当你在 Wayne 之上再做一层自研平台,而这层平台仍然直接去装配 Deployment / ConfigMap / Ingress / Service,那它和 Wayne 在职责上就重叠了——两个系统都想管权限、管发布、管模板、管审计。这种「双平台」结构,大概率会长出四个毛病:

  1. 职责重叠:平台层和控制层都在干「收敛集群状态」的活,边界模糊。
  2. 真实源不清晰:到底以 Git、Wayne 数据库、自研平台的元数据,还是集群的实际状态为准?没人说得清。
  3. 原生表达力不足:Secret、有状态负载、渐进式发布、网关新模型,硬塞进自研那套抽象里,越塞越别扭。
  4. 升级和兼容压力,全压在你自己身上

我们前记提到的问题,就是第 2 条「真实源不清晰」活生生的案例。 自研平台只信自己创建的记录,不以集群里 etcd 的真实对象为准,于是那条「非它创建」的重复 Ingress 就成了它视野里的盲区。运维盯着一幅残缺的地图操作,很容易出问题。

1.3 那到底该怎么分层?

通过 ChatGPT 调研了一下业界相对成熟的方案,笔者认为答案是:把「平台层、控制层、集群层」明确拆开,各司其职。

层次

谁来做

职责

一句话定位

平台层

自研平台

服务申请、模板生成、审批、成本视图、审计聚合、开发者体验

组织流程与体验的「门面」

控制层

标准控制器

GitOps(Argo CD/Flux)、准入策略(Kyverno/Gatekeeper)、密钥同步(External Secrets)、观测(Prometheus Operator)、备份(Velero)、网关(Gateway API)

状态收敛与治理的「执行器」

集群层

标准 K8s

K8s + CNI/CSI + 节点池 + 运行时

真正承载工作负载

一句话总结这套思路:

你的自研平台应该做「产品化入口」,而不该再做「第二个 Kubernetes 控制器」。 平台层是门面,控制层才是执行器,集群的真实状态由控制器来收敛——而不是由两个平台各写各的。

所以回到最初的问题:自研前台合理吗?合理,而且有价值(权限、审批、流程集成、屏蔽复杂度,这些都是真需求)。但前提是——管理入口必须和控制入口解耦:自研平台只负责「把人的意图变成 Git 声明或标准 CRD」,剩下的交给 GitOps 控制器去收敛到集群。做到单一事实来源、去双写、去双控、去双权限模型。这样,就不会再出现「平台看到的」和「集群真有的」对不上的盲区。

1.4 落地不是「一刀切」

对 Wayne 这种存量,靠谱的做法是三段式处置,而不是一夜切换:

  1. 第一阶段:把 Wayne 收缩成「遗留系统 + 应急(break-glass)入口」,禁止它继续做日常发布的首选路径
  2. 第二阶段:让自研平台直接输出 Git 声明或标准 CRD,由 GitOps 控制器收敛到集群。
  3. 第三阶段:再决定 Wayne 是长期保留作 break-glass 工具,还是被 Rancher / OpenShift / 自研直连控制器体系彻底替代。

选型上也有个朴素的判断原则:单集群、团队能力强、自研成熟,就「保留自研前台 + 标准化控制层 + 弱化 Wayne」;多集群、混合云、强合规、平台团队又小,就认真评估 Rancher / OpenShift / Tanzu 这类商业平台。


二、内网流量全链路:从主域名到 Pod

把管理体系讲完,再看流量本身。一个内网请求从域名到落地 Pod,要依次穿过这么几跳:

代码语言:javascript
复制
   主域名 (FQDN)
       │  ① DNS 解析
       ▼
 ┌───────────┐
 │   GSLB    │  ② 跨机房选址 / 健康检查 / 流量切换(DNS 层,L4 决策)
 │ (F5 BIG-IP│     
 │   DNS)    │
 └───────────┘
       │  返回某个机房的入口 IP
       ▼
 ┌───────────┐
 │ SLB(Nginx)│  ③ 机房入口七层反代 / SSL 卸载(L7)
 │           │     
 └───────────┘
       │
       ▼
 ┌───────────┐
 │ Ingress   │  ④ 暴露 Ingress Controller 的入口 VIP
 │   VIP     │
 └───────────┘
       │
       ▼
 ┌──────────────────┐
 │ Ingress(host+path)│  ⑤ 集群内七层路由规则(L7)
 │                   │     —— 前记里提到的重复的ingress就在这
 └──────────────────┘
       │
       ▼
 ┌───────────┐
 │  Service  │  ⑥ 集群内四层负载均衡(L4,稳定 VIP + 动态 Endpoints)
 └───────────┘
       │
       ▼
 ┌───────────┐
 │   Pod     │  ⑦ 真正承载业务逻辑
 └───────────┘

逐跳拆开看:

① 主域名 → ② GSLB(全局负载均衡,DNS 层) GSLB 本质是「DNS 负载均衡 + 智能路由策略」,工作在 DNS 层,根据健康检查、就近、负载,在多个机房之间选址。我们用的应该是 F5 BIG-IP DNS(原 GTM)。它的负载均衡方法分两类:

  • 动态方法:按实时性能指标选,比如 RTT(往返时延)、Completion Rate(完成率)、按比例加权——我们平时就是按比例(约 1:9)把流量分到两个机房。
  • 静态方法:其中 Global Availability 是「按配置顺序选第一个可用的成员」,效果相当于单边 / 主备——把流量全压到一侧。

应急时,可以把 GSLB 从「按比例的动态路由」切成「单边 Global Availability」,把流量整体压到正常的一侧。 但要注意 GSLB 的一个固有约束:它靠 DNS 生效,受 TTL 和递归缓存影响,切换不是瞬时的,会有一段收敛时间。

③ SLB(Nginx) 机房入口的七层软件反向代理,做 SSL 卸载、转发到集群入口。它的 access log 是我们排障的主力(详见第四章)。

④ Ingress VIP 对外暴露 Ingress Controller 的入口 VIP,SLB 把流量打到这里,正式进入 K8s 的七层入口。

⑤ Ingress(host + path) 集群内的七层路由规则:按域名(host)和路径(path)决定请求转发到哪个 Service。如果 Ingress 被删或下线,请求进了集群却找不到匹配的路由,就会异常返回(笔者公司就遇到过类似情况,access log 中观测到的返回码是 405)。

⑥ Service 集群内的四层负载均衡:一个稳定的 VIP + 一组自动维护的 Endpoints,把流量分发到当前健康的 Pod。顺便点破一个冷知识——Service 底层 kube-proxy 的 IPVS 模式,内核能力其实就是 LVS。我们在传统架构里用来做 L4 的 LVS,到了 K8s 里下沉成了每个节点上的 Service 转发引擎。技术没变,位置变了。

⑦ Pod 最终承载业务逻辑的容器。


三、Ingress 最佳实践与未来发展

这次的主角是 Ingress,单独拎出来讲透。

3.1 先搞懂「重复 Ingress」报错从哪来

Ingress 其实是三个东西配合在一起:

  • Ingress 资源:一份描述路由规则(host/path → Service)的 YAML,提交后作为对象存进 K8s 的 etcd,它只声明意图、自己不干活。
  • Ingress Controller:真正干活的组件,watch(监听)Ingress 资源变化,翻译成反向代理配置并执行。Nginx Ingress 说穿了就是「把传统 Nginx 搬进集群,自动生成并 reload nginx.conf」。
  • 准入校验(Admission):在对象写进 etcd 之前,API Server 会先过一遍准入控制(含各种 ValidatingWebhook)。注意:这一层是否拦「重复 Ingress」,取决于你装了什么校验,而不是 K8s 自带的。

这里要破除一个常见误解:「不能有重复 Ingress」并不是 Kubernetes 与生俱来的规则。

  • K8s 核心(API Server)本身不做跨 Ingress 的 host+path 唯一性校验。 Ingress 规范明确把「多条规则重叠时怎么办」交给具体 Controller(implementation-specific)。所以默认你完全可以创建多条 host+path 相同的 Ingress,API Server 照单全收存进 etcd,不报错。
  • 谁生效由 Controller 决定:ingress-nginx 的默认行为是「最早创建的那条赢(按 CreationTimestamp),其余忽略并打个 warning」,并不会拒绝。它自带的 admission webhook 主要是把配置渲染成 nginx.conf 跑一次 nginx -t,抓语法/注解/正则错误——重复 host+path 是合法配置,webhook 不拦。这也正好解释了前记里那条重复 Ingress 为什么能静默并存好几年:默认根本没人拦它。
  • 那「重复」报错从哪来? 它是后来额外加的一层校验——可能是 Ingress Controller 升级后启用的策略,更常见的是自研管控平台 / 策略引擎(Kyverno、Gatekeeper、自建 webhook,或新版 ValidatingAdmissionPolicy)里显式写的 host+path 唯一性规则。笔者公司就是某次版本之后,管控平台才开始校验重复 host+path 的;在那之前,重复 Ingress 是能并存的。

这个机制本身是好的——它从源头上帮你防路由冲突。但要记住它的边界:它只能挡住「以后新建的重复」,对已经躺在 etcd 里的历史重复对象无能为力,那些还得靠巡检和治理去清理(见 3.2、3.3)。

3.2 多机房 / 多集群下 Ingress 的真实难点

  • 重复与归属不清:同一个 host+path 在不同时间、不同入口被创建多次,谁是谁的、哪条在生效,全靠人脑记。
  • 删除影响面大:删一条 Ingress,可能直接掐断一整个机房的入口。
  • 孤儿残留:上层平台删了记录,etcd 里的对象没删干净;或反过来。

3.3 最佳实践

  • 命名与归属规范:Ingress 名字 / label 里带上机房、应用、负责人,一眼能看出归属。
  • host + path 唯一性治理:定期扫描冲突与重复,别等 Webhook 拦截时才发现。
  • 声明式 / GitOps:Ingress 配置进 Git,用 Argo CD/Flux 收敛——变更可追溯、可 review、可回滚,从源头上消灭「页面上手删错对象」。
  • 孤儿对象巡检:定期拿「平台记录」和「集群 etcd 真实对象」做 diff,孤儿早发现早清理。
  • 删除防呆:删除前展示「这条规则影响哪个机房、哪些流量」,跨机房操作做隔离和二次确认。

3.4 未来:旧王已死,该往哪走

这里有个必须知道的硬事实。据 Kubernetes 官方博客(2025-11-11):

「In March 2026, Ingress NGINX maintenance will be halted, and the project will be retired.」——2026 年 3 月起,ingress-nginx 停止维护并退役,此后不再有版本发布、bug 修复或安全补丁

按今天的时间点,ingress-nginx 实际上已经退役了。它据估计仍被约一半的云原生环境依赖,而且已经爆出 CVE-2026-3288(rewrite-target 注入,CVSS 8.8)这类高危漏洞。一个不再有人补安全洞的入口组件,继续摆在生产入口上,本身就是定时炸弹。 迁移已经从「优化」变成「必须偿还的硬性技术债」。

方向有两个,配套着走:

  • Gateway API:Kubernetes 官方定位的「下一代 Ingress」。角色分离(GatewayClass/Gateway/HTTPRoute 分给基础设施、集群运维、应用开发)、表达力更强(流量切分、Header 操作、跨 namespace 引用都是原生能力)、厂商中立。注意:Ingress API 已冻结,新能力都在 Gateway API 上。
  • Higress:一个值得评估的落地实现,基于 Envoy/Istio 内核,兼容 ingress-nginx 注解可平滑迁移,且把流量网关、微服务网关、AI 网关三合一——AI 网关能力在当下尤其有吸引力。

策略上,社区的共识是:旧 Ingress 稳态保留、新服务优先上 Gateway API,迁移时重点核对历史注解、TLS、Header routing、跨 namespace backend 这些容易踩坑的行为差异。


四、监控:从 GSLB 到 Pod 怎么观测

4.1 现状:靠 SLB access log + 4xx / 5xx 告警

我们目前看请求,主力是 SLB(Nginx)这一层的 access log——统一采集到日志平台展示,并配了 4xx / 5xx 类的告警规则(按比例或数量)。一旦某个机房出现大量 4xx 返回,access log 里整片飘红、告警触发,就能顺着往下定位了。

access log 这一层能看到的东西其实很丰富:状态码、上游响应耗时(upstream_response_time)、真实客户端 IP(real_ip / X-Forwarded-For)、请求 ID(request_id)等。它是排障的硬通货。

4.2 现状的局限

笔者公司针对 access log 对应的告警有一定的提升空间:

  • 缺跨层关联:access log 只是 SLB 这一层。一个请求从 GSLB 到 Pod 走了七跳,没有一条贯穿的 request-id / trace,就很难快速判断到底断在哪一跳——这次靠经验猜到是 Ingress,下次未必这么快。
  • 偏被动:很多不重要的业务主要靠「真实流量打出错误」才发现。缺少主动黑盒探测(定时拨测每个机房的入口),否则只能等用户的请求来触发告警。

4.3 全链路应该怎么监控

把整条链路按层铺开,每层都该有「指标 / 日志 / 追踪」三类信号:

关键指标(Metrics)

日志(Logs)

追踪(Traces)

GSLB / DNS

解析量、解析成功率、健康检查状态、各站点命中占比

高速 DNS 日志

F5 / SLB

VS 连接数、SSL TPS、吞吐、5xx 率、池成员可用性

access log(含上游耗时、real_ip)

iRule 注入请求 ID

Nginx / Ingress

RED 指标(请求量/错误/延迟)、/metrics、reload 成功与否、证书过期时间

访问日志(含 upstream 变量)

OTel 透传

Service / Pod

RED 指标、业务自定义指标

结构化日志(含 trace_id)

业务 span

几个重点:

  • 一条贯穿全链路的关联 ID:在每一层统一注入并透传 X-Request-ID 或 W3C traceparent。这样一个请求从 GSLB 到 Pod 能串成一条 trace,「断在哪一跳」一目了然。API 网关/代理是分布式追踪最容易断裂的地方,务必显式转发。
  • 主动黑盒探测 + SLO 告警:用 blackbox_exporter 定时拨测各机房入口;告警从单纯阈值升级为 SLO + 多窗口多燃尽率,兼顾「快发现」和「低误报」。
  • 统一观测栈:指标 Prometheus、日志 Loki、追踪 Tempo,用 OpenTelemetry 统一采集,三信号能互跳。

4.4 从「看得见」到「查得出根因」

前面三节解决的是「看得见、能串起来」。但光看得见还不够——排障真正想要的,是「在最短时间内,从现象定位到根因,并给出一条可解释的证据链」。

这两者差距有多大?设想一个任何企业都可能遇到的场景:某条业务链路的成功率突然从 99.9% 掉到 92%,告警响了。

  • 只有「可观测」:你打开日志平台看到错误飘红,再跳到网关 metrics 确认错误率确实涨了,再去翻 DNS/GSLB、翻后端 Pod 日志……在好几个系统间来回跳转、人工拼凑证据,往往要花几十分钟。
  • 具备「根因分析」:点开告警,平台直接给出结论和证据——「错误集中在入口路由这一跳,且只发生在某个机房;该时间点附近有一次相关变更」,几分钟就能锁定方向。

差别不在「有没有数据」,而在「数据能不能自动拼成因果」。这就引出一个观念:

全链路平台不应只是「展示工具」,更应是根因推理的「数据底座 + 分析引擎」。

4.5 一条「域名→Pod」链路上,根因分析依赖哪些能力

可观测的三件套(指标/日志/追踪)是底座,但要把它们变成「能定位根因」的引擎,通常还要具备下面几类能力。它们不针对某一家的架构,而是任何一条「域名→GSLB→网关→Service→Pod」链路都适用的通用要求:

代码语言:javascript
复制
同一个对象(某台网关、某条 Ingress、某个 Service、某个 Pod、某台宿主机)在追踪、日志、指标、告警、变更、CMDB 各系统里得是同一个 ID。否则各系统各叫各的名,根本关联不上——这其实和第一章「平台与集群对不上账」是同一类毛病

把它和 4.3 那张「分层三信号」表对照看:4.3 保证「每一层都有数据」,这一节保证「这些数据能拼成一条因果链」。 前者是底座,后者是引擎,缺一不可。

4.6 一次理想的排障是什么样

把上面的能力串起来,同样一次「某条链路成功率突降」,理想的排障过程大致是:

  1. 从告警下钻:点开成功率告警,直接拿到这段时间内的失败请求样本(关键错误请求最好全量采样,免得故障期被采样率丢掉证据)。
  2. 聚合定位:系统告诉你这些失败「最早都断在入口路由这一跳,且集中在某一个机房」,嫌疑范围从「整条链路」收敛到「某机房的入口」。
  3. 拓扑 + 告警回溯:在该机房的依赖链上着色,看到入口路由异常;时间线上最早的事件指向一次配置/对象变更。
  4. 变更关联:故障前不久正好有一次相关变更,诱因基本锁定。
  5. 止血:一边修复入口,一边用上层流量调度(如 GSLB 切换)把问题机房的流量临时摘走。

整个过程追求的是有证据链、可解释,而不是靠老师傅的经验去猜。


结语

写到这里回头看,这篇其实是被一个小小的「Ingress 重复报错」牵出来的——一个本身没影响业务、并存了好几年的重复对象,逼着笔者把内网这条「从主域名到 Pod」的路重新捋了一遍。捋下来,大概是这么几件事:

  • 管理上:问题不在用没用 Wayne,而在「管理入口和控制入口有没有解耦」。平台只该做门面,真正收敛集群状态的活,交给标准控制器去干。
  • 链路上:一个请求从域名出发,经 GSLB、SLB、Ingress、Service 最后落到 Pod,每一跳干什么、是 L4 还是 L7,心里得有这么一张图。
  • Ingress 这块:「重复」校验并不是 K8s 自带的;老牌的 ingress-nginx 也走到了头,往后是 Gateway API 和 Higress 的方向。
  • 监控上:光有 access log 和 4xx 告警,只够「看得见」,还没到「查得出根因」。

最后想多聊一句对可观测和 RCA 的展望。很多情况下,ingress 出了问题,靠的其实还是经验加上人工翻日志;但链路越来越长、机房越来越多,靠人在一条七八跳的链路上挨个猜,迟早是要吃亏的。笔者越来越觉得,可观测的下一站不是「堆更多的大盘」,而是把指标、日志、追踪、CMDB、变更用一套统一的对象 ID 串起来,让平台自己把因果链拼出来——再往前一步,大概率就是 AIOps 把这套根因分析的流程自动化,真正做到「现象一出,根因和证据链直接摆到面前」。

那一天到来之前,把对象 ID 统一好、把全链路追踪打通、把变更老老实实接进来,就是现在能为「那一天」铺的路。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 周银杂谈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前记:上周公司内部一次变更引出了在生产环境的k8s的一个部署因为ingress 重复发现的一个报错,复盘下来觉得有必要把整个过程给整理下来,顺便也让自己了解下从客户端发起对主域名的接口请求,是如何一步一步最终请求到k8s的pod。
    • 一、Wayne 之上再套一层自研页面,到底合不合理?
      • 1.1 先说 Wayne 这一层
      • 1.2 真正的病根:「双平台」
      • 1.3 那到底该怎么分层?
      • 1.4 落地不是「一刀切」
    • 二、内网流量全链路:从主域名到 Pod
    • 三、Ingress 最佳实践与未来发展
      • 3.1 先搞懂「重复 Ingress」报错从哪来
      • 3.2 多机房 / 多集群下 Ingress 的真实难点
      • 3.3 最佳实践
      • 3.4 未来:旧王已死,该往哪走
    • 四、监控:从 GSLB 到 Pod 怎么观测
      • 4.1 现状:靠 SLB access log + 4xx / 5xx 告警
      • 4.2 现状的局限
      • 4.3 全链路应该怎么监控
      • 4.4 从「看得见」到「查得出根因」
      • 4.5 一条「域名→Pod」链路上,根因分析依赖哪些能力
      • 4.6 一次理想的排障是什么样
    • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档