Kubernetes SIG Network 的 ingress-nginx controller 将在 2026 年 3 月退役。这个变化的重点不是“项目不再时髦”,而是它会直接改变生产集群的风险模型:继续停留在退役控制器上,意味着后续 CVE 可能没有补丁,新特性也会停止进入这条路线。对负责平台和业务稳定性的团队来说,现在该把入口层迁移放进路线图,而不是等到最后一个季度临时搬家。
退役真正影响的是运维边界
Ingress controller 不是一个普通 Deployment。它通常站在公网入口,处理 TLS、Host/Path 路由、Header、超时、重试、上传大小、WebSocket、gRPC,甚至还挂着外部负载均衡器和 DNS 记录。
所以 ingress-nginx 退役后的风险主要有三类:
- 安全补丁断档:摘要中明确提到继续使用会带来未修补 CVE 的严重运维风险。入口层暴露面大,这类风险不能靠“内部服务没事”来抵消。
- 功能停滞:Kubernetes Gateway API、云厂商 L7 能力、可观测性接口都在演进。如果 controller 停止功能更新,平台会被旧抽象锁住。
- 事故恢复变慢:一旦遇到版本兼容、证书、负载均衡行为差异,退役项目的社区响应和维护资源会明显减少。
迁移不是简单替换镜像。更现实的做法是把它拆成资产盘点、候选控制器验证、双跑、流量切换和回滚预案。
先盘点:你到底用了多少 ingress-nginx 特性
很多集群表面上只有几十个 Ingress,实际依赖的是一堆 NGINX annotation。比如 rewrite、proxy body size、backend protocol、whitelist、auth、CORS、canary。迁移难度通常不由 Ingress 数量决定,而由这些 annotation 决定。
可以先跑一轮只读盘点,找出所有 Ingress、IngressClass 和 annotation:
kubectl get ingress -A -o json \
| jq -r '.items[] | [
.metadata.namespace,
.metadata.name,
(.spec.ingressClassName // "<none>"),
((.metadata.annotations // {}) | keys | join(","))
] | @tsv'
运行前需要本机有 kubectl 和 jq,并且当前 kubeconfig 指向目标集群。输出可以导入表格,按 annotation 分类评估:
kubectl get ingress -A -o json \
| jq -r '.items[]
| .metadata.annotations // {}
| keys[]?' \
| sort \
| uniq -c \
| sort -nr
这一步的目标不是马上选型,而是回答几个具体问题:哪些业务只用了标准 Ingress 字段,哪些业务深度依赖 NGINX 行为,哪些路由必须在迁移窗口内重点压测。
可以这样实践:新旧控制器并行,而不是原地覆盖
下面示例是一个可改造的迁移骨架,假设你要引入一个新的入口控制器,并通过不同的 IngressClass 做并行验证。具体 controller 可以是你们选定的替代方案;这里不声明某个特定实现是来源推荐,只展示迁移方法。
先保留旧的 nginx class,再新增一个候选 class:
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: candidate-gateway
spec:
controller: example.com/candidate-ingress-controller
应用它:
kubectl apply -f candidate-ingressclass.yaml
kubectl get ingressclass
然后复制一个低风险服务的 Ingress,改到新 class,并使用测试域名:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: echo-candidate
namespace: default
spec:
ingressClassName: candidate-gateway
rules:
- host: echo-candidate.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: echo
port:
number: 80
应用并检查地址分配:
kubectl apply -f echo-candidate-ingress.yaml
kubectl get ingress -n default echo-candidate
kubectl describe ingress -n default echo-candidate
如果你们有外部 DNS 自动化,测试域名可能会自动指向新负载均衡器;如果没有,就临时用 curl --resolve 验证,避免提前改公共 DNS:
curl -I --resolve echo-candidate.example.com:443:203.0.113.10 \
https://echo-candidate.example.com/
把 203.0.113.10 改成新入口负载均衡器的 IP。这个方法适合验证 TLS、路由、Header、响应码和超时行为,不会影响原生产域名。
迁移检查表:别只测 200 OK
入口层迁移最容易漏掉的是“非主路径”行为。建议把检查项写进变更单,而不是靠值班工程师临场记忆。
HOST=echo-candidate.example.com
IP=203.0.113.10
curl -sv --resolve "$HOST:443:$IP" "https://$HOST/" -o /dev/null
curl -sv --resolve "$HOST:443:$IP" "https://$HOST/not-found" -o /dev/null
curl -sv --resolve "$HOST:443:$IP" -H 'X-Request-ID: migration-test-001' "https://$HOST/" -o /dev/null
实际项目里还要补充:
- TLS 证书链和 SNI 是否正确。
- HTTP 到 HTTPS 跳转是否符合预期。
- 大文件上传、长连接、WebSocket、gRPC 是否正常。
- 真实客户端 IP 是否还能进入应用日志。
- WAF、认证、限流、白名单等边界能力是否有等价实现。
- Prometheus 指标、日志字段和告警是否同步迁移。
如果大量依赖 nginx.ingress.kubernetes.io/* annotation,不要假设新控制器能逐字兼容。应逐项映射,能迁到标准字段就迁到标准字段,必须保留特殊行为的地方要写清楚替代配置。
采用建议:把 2026 年 3 月当作截止线,不当作开始线
比较稳妥的节奏是:先在非生产集群完成候选 controller 验证,再选择一两个低风险生产服务双跑,最后按业务域分批迁移。每一批都要有回滚路径,例如保留旧 Ingress、DNS TTL 降低、负载均衡器切换可逆。
不要等到 ingress-nginx 退役后才开始评估。那时你面对的不是一个技术迁移任务,而是安全风险、合规压力和生产变更窗口挤在一起。现在开始盘点 annotation、清理历史 Ingress、收敛入口策略,才有空间慢慢把入口层从“能跑”改成“可维护”。