
不同公司的架构可能不一致,这里仅针对笔者公司的架构做一个梳理,顺带对目前架构优化的一些思考总结,如果文中有不对的地方,也欢迎各位老师批评指正。
起因是机房 A 里有一条重复的 Ingress:新旧两条可以并存,已经并存运行了好几年了,期间也有一些巡检通知,但巡检通知始终没有触达到应用负责人,所以这个问题点一直没被发现,线上的流量走的是那条老 Ingress,工作得好好的。
所以本文我想把内网这条「从主域名到 Pod」的链路,连同它背后的管理体系,系统地捋一遍。这篇就分四块来讲:
笔者所在公司一开始引入的是开源 Wayne 作为 Kubernetes 管理入口,再叠加一层公司内部自研平台,而底层应用仍主要以 Deployment、ConfigMap、Ingress、Service 这些原生对象为核心来管理。
很多人第一反应是「套这么多层,是不是过度设计」。但笔者研究下来,结论没那么简单——问题的关键不是「用没用 Wayne」,而是「管理入口和控制入口有没有解耦」。
Wayne 是 360 开源的多集群 Kubernetes 管理平台,覆盖了多集群、访问控制、发布管理与审计,本身是个不错的东西。但它有一个现实问题:公开 release 基本停在 2020 年初,技术基线偏老。所以更合适的定位是:把它当成一个过渡期的控制面,而不是未来几年企业平台能力的核心支点。
当你在 Wayne 之上再做一层自研平台,而这层平台仍然直接去装配 Deployment / ConfigMap / Ingress / Service,那它和 Wayne 在职责上就重叠了——两个系统都想管权限、管发布、管模板、管审计。这种「双平台」结构,大概率会长出四个毛病:
我们前记提到的问题,就是第 2 条「真实源不清晰」活生生的案例。 自研平台只信自己创建的记录,不以集群里 etcd 的真实对象为准,于是那条「非它创建」的重复 Ingress 就成了它视野里的盲区。运维盯着一幅残缺的地图操作,很容易出问题。
通过 ChatGPT 调研了一下业界相对成熟的方案,笔者认为答案是:把「平台层、控制层、集群层」明确拆开,各司其职。
层次 | 谁来做 | 职责 | 一句话定位 |
|---|---|---|---|
平台层 | 自研平台 | 服务申请、模板生成、审批、成本视图、审计聚合、开发者体验 | 组织流程与体验的「门面」 |
控制层 | 标准控制器 | GitOps(Argo CD/Flux)、准入策略(Kyverno/Gatekeeper)、密钥同步(External Secrets)、观测(Prometheus Operator)、备份(Velero)、网关(Gateway API) | 状态收敛与治理的「执行器」 |
集群层 | 标准 K8s | K8s + CNI/CSI + 节点池 + 运行时 | 真正承载工作负载 |
一句话总结这套思路:
你的自研平台应该做「产品化入口」,而不该再做「第二个 Kubernetes 控制器」。 平台层是门面,控制层才是执行器,集群的真实状态由控制器来收敛——而不是由两个平台各写各的。
所以回到最初的问题:自研前台合理吗?合理,而且有价值(权限、审批、流程集成、屏蔽复杂度,这些都是真需求)。但前提是——管理入口必须和控制入口解耦:自研平台只负责「把人的意图变成 Git 声明或标准 CRD」,剩下的交给 GitOps 控制器去收敛到集群。做到单一事实来源、去双写、去双控、去双权限模型。这样,就不会再出现「平台看到的」和「集群真有的」对不上的盲区。
对 Wayne 这种存量,靠谱的做法是三段式处置,而不是一夜切换:
选型上也有个朴素的判断原则:单集群、团队能力强、自研成熟,就「保留自研前台 + 标准化控制层 + 弱化 Wayne」;多集群、混合云、强合规、平台团队又小,就认真评估 Rancher / OpenShift / Tanzu 这类商业平台。
把管理体系讲完,再看流量本身。一个内网请求从域名到落地 Pod,要依次穿过这么几跳:
主域名 (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)。它的负载均衡方法分两类:
应急时,可以把 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 其实是三个东西配合在一起:
nginx.conf」。这里要破除一个常见误解:「不能有重复 Ingress」并不是 Kubernetes 与生俱来的规则。
CreationTimestamp),其余忽略并打个 warning」,并不会拒绝。它自带的 admission webhook 主要是把配置渲染成 nginx.conf 跑一次 nginx -t,抓语法/注解/正则错误——重复 host+path 是合法配置,webhook 不拦。这也正好解释了前记里那条重复 Ingress 为什么能静默并存好几年:默认根本没人拦它。这个机制本身是好的——它从源头上帮你防路由冲突。但要记住它的边界:它只能挡住「以后新建的重复」,对已经躺在 etcd 里的历史重复对象无能为力,那些还得靠巡检和治理去清理(见 3.2、3.3)。
这里有个必须知道的硬事实。据 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)这类高危漏洞。一个不再有人补安全洞的入口组件,继续摆在生产入口上,本身就是定时炸弹。 迁移已经从「优化」变成「必须偿还的硬性技术债」。
方向有两个,配套着走:
GatewayClass/Gateway/HTTPRoute 分给基础设施、集群运维、应用开发)、表达力更强(流量切分、Header 操作、跨 namespace 引用都是原生能力)、厂商中立。注意:Ingress API 已冻结,新能力都在 Gateway API 上。策略上,社区的共识是:旧 Ingress 稳态保留、新服务优先上 Gateway API,迁移时重点核对历史注解、TLS、Header routing、跨 namespace backend 这些容易踩坑的行为差异。
我们目前看请求,主力是 SLB(Nginx)这一层的 access log——统一采集到日志平台展示,并配了 4xx / 5xx 类的告警规则(按比例或数量)。一旦某个机房出现大量 4xx 返回,access log 里整片飘红、告警触发,就能顺着往下定位了。
access log 这一层能看到的东西其实很丰富:状态码、上游响应耗时(upstream_response_time)、真实客户端 IP(real_ip / X-Forwarded-For)、请求 ID(request_id)等。它是排障的硬通货。
笔者公司针对 access log 对应的告警有一定的提升空间:
把整条链路按层铺开,每层都该有「指标 / 日志 / 追踪」三类信号:
层 | 关键指标(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 |
几个重点:
X-Request-ID 或 W3C traceparent。这样一个请求从 GSLB 到 Pod 能串成一条 trace,「断在哪一跳」一目了然。API 网关/代理是分布式追踪最容易断裂的地方,务必显式转发。前面三节解决的是「看得见、能串起来」。但光看得见还不够——排障真正想要的,是「在最短时间内,从现象定位到根因,并给出一条可解释的证据链」。
这两者差距有多大?设想一个任何企业都可能遇到的场景:某条业务链路的成功率突然从 99.9% 掉到 92%,告警响了。
差别不在「有没有数据」,而在「数据能不能自动拼成因果」。这就引出一个观念:
全链路平台不应只是「展示工具」,更应是根因推理的「数据底座 + 分析引擎」。
可观测的三件套(指标/日志/追踪)是底座,但要把它们变成「能定位根因」的引擎,通常还要具备下面几类能力。它们不针对某一家的架构,而是任何一条「域名→GSLB→网关→Service→Pod」链路都适用的通用要求:
同一个对象(某台网关、某条 Ingress、某个 Service、某个 Pod、某台宿主机)在追踪、日志、指标、告警、变更、CMDB 各系统里得是同一个 ID。否则各系统各叫各的名,根本关联不上——这其实和第一章「平台与集群对不上账」是同一类毛病把它和 4.3 那张「分层三信号」表对照看:4.3 保证「每一层都有数据」,这一节保证「这些数据能拼成一条因果链」。 前者是底座,后者是引擎,缺一不可。
把上面的能力串起来,同样一次「某条链路成功率突降」,理想的排障过程大致是:
整个过程追求的是有证据链、可解释,而不是靠老师傅的经验去猜。
写到这里回头看,这篇其实是被一个小小的「Ingress 重复报错」牵出来的——一个本身没影响业务、并存了好几年的重复对象,逼着笔者把内网这条「从主域名到 Pod」的路重新捋了一遍。捋下来,大概是这么几件事:
最后想多聊一句对可观测和 RCA 的展望。很多情况下,ingress 出了问题,靠的其实还是经验加上人工翻日志;但链路越来越长、机房越来越多,靠人在一条七八跳的链路上挨个猜,迟早是要吃亏的。笔者越来越觉得,可观测的下一站不是「堆更多的大盘」,而是把指标、日志、追踪、CMDB、变更用一套统一的对象 ID 串起来,让平台自己把因果链拼出来——再往前一步,大概率就是 AIOps 把这套根因分析的流程自动化,真正做到「现象一出,根因和证据链直接摆到面前」。
那一天到来之前,把对象 ID 统一好、把全链路追踪打通、把变更老老实实接进来,就是现在能为「那一天」铺的路。