首页 / 资讯中心 / 文章详情

Kubernetes Ingress NGINX紧急迁移:公告解读、升级方案与避坑指南

Kubernetes Ingress NGINX紧急迁移:公告解读、升级方案与避坑指南 ★ FEATURED ARTICLE
最近两个星期不少 Kubernetes 运维群都被一条公告刷了屏。消息标题很直接Kubernetes 官方再次发布公告强调需要立即迁移 Ingress NGINX。我第一反应也和大家一样升级控制器而已至于用“立即”这种词吗但把公告完整读下来就明白了这次确实不是例行催更而是给出了明确的兼容性与安全窗口。很多团队的控制器版本已经停在大版本若干年业务没出问题就没人动它直到公告出现才发现升级难度已经被自己拖高了。这里说的 Ingress NGINX指的是社区维护的 ingress-nginx 控制器不是云厂商控制台里那个一键绑定的负载均衡器也不是那种随节点自带的 Nginx 反向代理。它是 Kubernetes 集群里最常用的入口流量组件之一负责把集群外部的 HTTP/HTTPS 流量按 Ingress 规则转发到后端 Service。正因为用的人多、暴露面大官方对它的版本生命周期和安全补丁节奏一向盯得很紧。这篇文章我会把公告背后的逻辑、受影响范围、迁移方案选型、实操步骤和踩坑点一次性梳理清楚排期的时候你可以直接拿来对照。1. 公告核心解读这次“立即迁移”到底在催什么1.1 公告内容拆解EOL、API 移除与升级顺序把公告完整读下来核心信息其实可以拆成三块。第一块是版本生命周期问题官方明确某些旧版本已经进入 EOL 状态维护团队不再为这些版本提供安全补丁。第二块是 Kubernetes API 兼容问题旧版本控制器内部依赖的部分 Kubernetes 内置 API 在后续集群版本中会被移除也就是说不是控制器想不想兼容的问题是集群升级后控制器可能直接废掉的问题。第三块是升级顺序问题官方强调如果集群版本已经接近或超过旧控制器的兼容范围必须先把控制器迁移到受支持版本再考虑集群本身的升级。这三块内容放在一起翻译成大白话就是你的集群和控制器之间有一个安全的版本交集这个交集正在不断缩小。旧版本控制器在旧集群上可能看起来一切正常但一旦集群跨版本升级控制器就会成为那个最先崩掉的组件。而且由于它承担着所有外部流量入口崩掉的影响范围不会是几个 Pod 重启那么简单而是整个入口流量中断。为什么是“再出公告”因为维护团队通常不会上来就下最后通牒。一般会先发预公告给出建议迁移时间线然后随着时间推移逐渐收窄支持窗口。这次用“立即”这种措辞说明已经过了“可以观望”的阶段。我自己的判断是还在用两年前甚至更早版本的集群基本都踩在公告点名的范围内即使你用的是相对新的版本也值得把这次公告当成一次配置体检的契机。1.2 受影响场景自查三类集群最危险第一类是控制器版本长期停留在两个大版本之前的集群。这类集群通常遵循“能不动就不动”的运维原则业务运行稳定没有明显的故障驱动于是升级计划永远排在最低优先级。但 Ingress 控制器恰恰是会持续接收安全补丁的组件版本越旧已知漏洞清单越长暴露在公网环境下的风险就越高。第二类是控制器版本和集群版本严重不匹配的集群。比如集群已经升到比较新的 Kubernetes 版本但控制器还是早期版本这种组合在升级当时可能勉强可用但官方兼容矩阵里已经找不到对应的支持组合。一旦触发某些新版本对 API 的校验逻辑控制器可能连启动都会失败更别提正常转发流量。第三类是高度依赖默认配置或大量自定义 Annotation 的存量业务集群。这类集群最大的问题不是迁移本身而是迁移过程中很难发现自己到底用了哪些旧行为。很多 Annotation 在旧版本里被宽松处理新版本校验增强后直接静默失效业务侧只报“502”或者“404”排查起来非常痛苦。后面我会专门展开讲这个坑。1.3 公告措辞背后为什么这次特别着急官方在公告里反复强调“立即”我理解有三层现实原因。第一层是安全补丁断供。Ingress 组件是整个集群的流量入口通常直接暴露在公网或对公网提供服务一旦出现路由绕过、权限提升这类漏洞影响范围是所有使用该版本的用户。EOL 版本不再发布补丁意味着这些漏洞会一直存在而且攻击者会专门盯着旧版本打。第二层是依赖链断裂。Kubernetes 本身也在持续演进部分 API 资源从 v1beta1 到 v1 再到废弃移除是一个固定流程。旧版控制器内部还在使用一些已经进入移除流程的 API 字段在集群升级后可能无法正常调用。这个风险不像安全漏洞那么直观但爆发时往往是整个控制器 crash 级别的故障。第三层是运维排期风险。官方一旦把“立即”这个措辞放出来意味着接下来的维护资源只会向新版本集中旧版本的已知问题不会再修社区问题也不会再给出适配旧版本的解决方案。越晚动手遇到问题时的参考文档越少可用的 help 资源也越少。很多团队在公告出来后还觉得可以再等等实际等到的是更加狭窄的迁移窗口和更高难度的故障排查。2. 迁移目标选型先别急着升级想清楚迁到哪2.1 方案A升级到受支持的 ingress-nginx 新版本对绝大多数存量集群来说最稳妥的方案不是推翻重来而是把现有 Ingress NGINX 控制器平滑升级到当前受支持的新版本。这个方案的最大优势是兼容性好原有的 Ingress 资源定义方式不变绝大多数 Annotation 依然有效DNS 解析、证书配置、Service 暴露方式都可以保留原样。整个迁移的核心动作是替换控制器镜像和更新 Helm Chart 配置而不是重新梳理业务流量模型。从工作量角度来说这可能是性价比最高的路线。你不需要改造应用不需要改 Ingress 资源也不需要给业务方重新讲一遍新配置模型的用法。你需要做的是把当前使用的 Helm values 完整导出来对照新版本默认值逐项比对跑一遍测试环境验证然后执行升级。整个过程如果提前准备充分快的话一个变更窗口就能完成。不过这里有个前提你的配置不能太“脏”。如果之前手动改过 Controller 的 ConfigMap、Service 或 RBAC 资源且这些改动没有沉淀到 Helm values 里升级时这些改动很可能会被覆盖。后面我在实操部分会讲怎么把这类风险用备份和 diff 提前拦下来。2.2 方案B借机评估 Gateway API 路线第二种路线是放弃 Ingress NGINX 控制器转向 Gateway API 体系。这是 Kubernetes 社区在流量治理方面主推的方向优点是配置模型更统一支持跨 namespace 的策略引用灰度发布、Header 修改、traffic split 等能力是原生模型的一部分而不是靠一堆 Annotation 拼出来的。但说实话我不建议在公告压力下临时切换。Gateway API 虽然成熟度已经不错但它和 Ingress 的配置模型差异非常大迁移相当于把所有入口流量配置重写一遍。你需要重新规划 GatewayClass、Gateway、HTTPRoute 这些资源还要额外部署一个支持 Gateway API 的控制器实现。业务侧也需要重新学习和适配如果团队里大家刚把 Ingress 的 Annotation 记熟这时候突然换模型学习成本和故障风险都会集中爆发。最合理的使用场景是新业务、新集群或者你已经计划做大规模流量治理改造Gateway API 可以顺势落地。而老集群里跑着几十上百个 Ingress 资源就不建议在这种节点上做模型级迁移。2.3 决策维度版本、团队和流量的三角关系选型本质上就是在这三件事之间找平衡。版本维度看你的集群版本和控制器版本相差多大相差越大滚动升级的中间态越难处理。团队维度看有没有熟悉新旧配置差异的人平时是不是有人专门负责集群流量组件。如果团队只是顺手维护别给自己找大工程老老实实选方案A。流量维度看你的业务对路由能力的依赖有多深。如果只用到了 path 转发、Host 转发和 TLS 终止这几个基础能力Ingress 和 Gateway API 对你的区别不大选哪个都行选升级更省事。如果涉及复杂的灰度、流量权重、请求头改写、跨服务故障转移Gateway API 长期来看会更顺手但你要为这个“长期顺手”付一笔短期的迁移学费。我个人的建议是先做版本升级把兼容性和安全性问题解掉如果后续业务复杂度确实到了 Ingress 注解体系撑不住的程度再单独立项评估 Gateway API。两个目标混在一起做最后往往哪个都做不利索。对比维度升级 ingress-nginx迁移 Gateway API配置兼容成本低Ingress 资源基本无需改动高需要重写为 HTTPRoute 等新资源团队学习成本低中高灰度能力依赖 Annotation 组合原生支持配置更清晰迁移风险中等集中在版本差异较高模型级重构适用时机公告催迁移时优先选择新集群或流量治理大改造时选择3. 实操迁移步骤与参数校验3.1 迁移前盘点三条命令摸清家底动手之前别急着升级先把你集群里的 Ingress 控制器现状摸清楚。下面这几条命令是我每次做这类迁移前固定会跑的你可以直接复制使用。# 查看当前集群里的 IngressClass并确认 controller 字段指向谁 kubectl get ingressclasses -o wide # 查看 ingress-nginx 命名空间下控制器的运行状态和镜像版本 kubectl get pods -n ingress-nginx -o wide | grep controller # 如果控制器是通过 Helm 部署的导出当前 release 的 values helm list -n ingress-nginx helm get values ingress-nginx -n ingress-nginx current-values.yaml第一条命令关注的是 IngressClass 的 controller 字段是否和 ingress-nginx 的期望值一致。很多团队在迁移过程中遇到过一个问题IngressClass 里写的是某个云厂商的 controller 名称但实际业务流量走的是 ingress-nginx两边不匹配的时候Ingress 资源创建后永远处于等待状态。第二条命令看 Pod 的镜像 tag 就能快速判断版本新旧。如果你发现当前版本已经落后官方稳定版一到两个大版本那基本就是这次公告直接覆盖的对象。第三条命令则是为了导出现有配置升级时 diff 会非常有用。如果你不是用 Helm 部署的也没有现成的 release 记录就需要手动导出控制器相关的 Deployment、Service、ConfigMap、ServiceAccount 和 ClusterRole。这里不展开 YAML 细节但建议至少把kubectl get deployment -n ingress-nginx -o yaml的结果存一份后面做回滚和对比都用得上。3.2 备份与回滚设计留好后路再动手升级 Ingress 控制器最大的忌讳是“没备份就升级”。虽然 Helm 本身支持 rollback但如果你过程中手动改过资源或者升级时用了不完整的 values 文件回滚可能不是简单的helm rollback就能解决。我的习惯是把状态备份做成三道保险。第一道是配置备份。导出集群当前所有 Ingress 资源、控制器 ConfigMap、以及相关的 Secret 到本地文件。命令如下kubectl get ingress -A -o yaml ingress-backup.yaml kubectl -n ingress-nginx get cm ingress-nginx-controller -o yaml controller-cm-backup.yaml kubectl -n ingress-nginx get secret -o yaml controller-secret-backup.yaml注意如果集群里有自管的 ingress-nginx-token 或 Webhook 证书 Secret升级过程可能涉及重建这部分一定要提前确认否则升级后 Webhook 会由于证书不匹配而反复报错。第二道是 Helm 版本记录。在升级前用helm list -n ingress-nginx查看当前 revision 号把它记下来。这样即使升级后不理想也可以通过helm rollback ingress-nginx 上一版本号 -n ingress-nginx快速回到升级前状态。第三道是测试环境验证。如果公司有预发或测试集群先在那边跑一遍完整升级流程把差异和坑点都处理完再在生产环境执行。这一步听起来像废话但很多团队在控制器升级时确实会跳过理由是“业务流量又没有变化升个镜像而已”。实际触发过的告警会告诉你Inert 控制器升级引发的问题从来不只在控制器本身。3.3 执行升级Helm 升级与滚动更新细节在正式升级前先更新 Helm 仓库并查看目标版本的默认 values了解新版本默认行为的变更点。这一步能预先发现大部分兼容性问题。helm repo update helm show values ingress-nginx/ingress-nginx --version 目标版本 new-default-values.yaml然后用现网导出的 current-values.yaml 作为基准和新版本默认值做一次 diff重点看几个高风险配置项controller 镜像版本、admissionWebhook 开关、config 里的 proxy 相关参数、metrics 端口是否变化。这几个配置对流量转发行为影响最大。确认没有意外差异后执行升级helm upgrade ingress-nginx ingress-nginx/ingress-nginx \ --version 目标版本 \ -n ingress-nginx \ -f current-values.yaml \ --history-max 5升级过程会触发控制器的滚动更新。这时候要观察的是 Pod 能不能顺利 Ready而不是急着刷页面看流量是否正常。用下面这条命令跟踪状态kubectl rollout status deployment/ingress-nginx-controller -n ingress-nginx如果控制器是通过 DaemonSet 部署的命令换成kubectl rollout status daemonset/ingress-nginx-controller -n ingress-nginx。滚动更新完成后检查 Pod 是否都处于 Running 状态然后看 controller 日志里有没有明显的报错。我在实际迁移中就遇到过一种情况Pod 显示 Running但 controller 一直往日志里打 “Error building handler” 之类的错误入口流量实际上全部 502。所以 Pod Ready 只是一个最低条件日志检查必须跟上。如果升级后发现问题第一时间回滚不要尝试在故障状态下修配置。回滚命令如下helm rollback ingress-nginx 上一版本号 -n ingress-nginx3.4 Annotation 与 IngressClass 兼容检查升级完成后最容易被忽略的是存量 Ingress 资源里的 Annotation 是否在新版本下仍然生效。ingress-nginx 的 Annotation 体系非常庞大新版本会在校验逻辑、参数语义、默认值上做调整。我自己的经验是把所有在用 Annotation 整理成一张清单逐个核对两个关键点是否还支持、语义是否有变化。比较典型的几类检查项包括与代理超时相关的配置比如nginx.ingress.kubernetes.io/proxy-connect-timeout、proxy-read-timeout这些通常变化不大但数值单位或边界值可能收紧。重写规则相关比如rewrite-target新版本对正则表达式的转义要求更严格旧的写法可能在新版本里静默失效。灰度相关比如canary、canary-weight、canary-by-header这组 Annotation新版本对权重和策略的优先级有更明确的定义如果你之前依赖权重灰度需要重新确认配置。IngressClass 方面要确认 Ingress 资源中是否显式声明了ingressClassName如果声明了要确保这个 Class 对应的 controller 名称与新版本控制器的 controller 字段一致。不一致时Ingress 会一直处于 pending 状态流量完全不进来排查时还容易误判成网络问题。我习惯在升级前先用测试域名建一个最小 Ingress指向一个固定返回当前版本信息的测试服务然后在升级后逐个检查基础转发、TLS、重写和超时配置。这个小动作成本很低但能帮你第一时间定位 Annotation 兼容性问题而不是等业务侧反馈“某个接口突然 404”。3.5 验证清单从流量到 TLS 的一次完整体检控制器滚动更新完成后不能只看 Pod Ready 就宣布成功。我通常会按下面的顺序做一轮完整验证。第一步检查后端服务连通性确认 Ingress 到 Service 到 Pod 的链路没有断裂。可以用一条简单的请求命令验证curl -H Host: your-domain.example https://INGRESS_NODE_IP/healthz -k -v第二步检查 TLS 证书是否正确加载。如果你用的是 ingress-nginx 自动管理的证书 Secret需要确认 Secret 在集群中依然存在且 Ingress 中引用的 Secret 名称没有变化。证书加载错误时curl -v里会直接看到证书相关的报错信息。第三步检查 Webhook 是否正常工作。升级后ValidatingWebhookConfiguration里的 service 指向需要和新控制器的 service 名称、端口匹配。验证方式很简单随便创建一个带非法字段的 Ingress看是否能被拦截如果完全不拦截说明 Webhook 配置可能失效了。kubectl get validatingwebhookconfigurations -o wide | grep ingress-nginx第四步是检查流量转发日志。查看 controller 日志历史确认升级前后请求记录连续没有出现大段时间盲区。同时观察错误状态码分布如果突然出现一批 502、404说明上面的某个检查项漏掉了一环。4. 常见问题与坑点实录4.1 Webhook 升级后反复报错这是控制器升级后最常见的坑之一。现象是控制器 Pod 正常运行但创建或更新 Ingress 资源时API Server 会返回 webhook 调用失败通常是因为ValidatingWebhookConfiguration里的 service 指向的还是旧的 service 名称或者证书不匹配。新版本控制器如果调整了 service 名称旧 webhook 配置就会失效。排查时先看 webhook 配置里指向的 service 是否存在、端口是否和新版本一致然后检查 Secret 中保存的证书是否和 webhook 配置里的 caBundle 对应。证书不匹配时把新的 caBundle 更新进去即可。踩了这个坑之后的经验是升级前先检查 webhook 配置链路完整再动控制器。别等升级完再回头看那时问题已经扩散到所有 Ingress 变更请求都失败了。4.2 旧 Annotation 静默失效导致路由与重写异常升级后业务方反馈某些接口 404 或返回异常但 Ingress 资源本身没有变化这是最让人头疼的情况。多数时候问题出在 Annotation 上而且旧版本不会报任何警告新版本把旧的无效 Annotation 直接忽略导致路由规则和后端转发行为发生了变化。比如rewrite-target里面的正则路径在旧版本里宽匹配了多个服务新版本校验严格以后不再匹配行为就变了。这类问题很难通过日志发现因为控制器日志里往往干净得像个新装环境。我的处理方式是提前做一次 Annotation 全量扫描把每一条 Annotation 都和新版本文档核对一遍尤其是路径重写和灰度相关的高频配置。这个方法很笨但救过我好几次。遇到查不到头绪的 404 时我会把对应 Ingress 的完整 YAML 拉出来逐行看 annotation而不是先怀疑后端服务。4.3 金丝雀发布流量切分异常版本升级后金丝雀异常也很常见。症状是设置了canary-weight的服务的灰度流量割接不正常要么全部打到了旧版本要么灰度比例完全错乱。原因通常是新旧版本对灰度 Annotation 的优先级定义有差异。新版本对canary-by-header、canary-by-cookie、canary-weight同时存在时的处理顺序更严格如果之前的配置同时声明了多个条件新版本可能按照不同的规则决定流量去向。处理方法是先砍掉大部分灰度配置只保留一个条件验证确认逻辑正确后再逐步加回。别指望一次把全部灰度策略都迁移过来这种复杂场景需要分步验证。4.4 快速排查参考表故障现象常见原因优先排查命令处理建议Pod 一直 CrashLoopBackOff镜像版本与集群版本不兼容kubectl logs -n ingress-nginx检查兼容矩阵回退到受支持版本创建 Ingress 失败webhook 报错Webhook 配置指向旧 servicekubectl get validatingwebhookconfigurations -o wide更新 service 指向和 caBundle升级后大量 502ConfigMap 中 proxy 参数异常kubectl -n ingress-nginx logs controller-pod检查后端服务连通性和超时配置部分路由 404Annotation 被静默忽略kubectl get ingress -A -o yaml逐项核对旧 annotation 是否存在灰度流量比例异常多个 canary 条件冲突kubectl describe ingress name先保留单一条件验证后再加回5. 最后说几句实操体会控制器这类流量组件的升级最忌讳的就是把它当成普通镜像升级来排期。它和业务服务不同业务服务升级后最多影响自己这条链路而 Ingress 控制器升级影响的是集群所有入口流量。我在实际踩坑后养成了一个习惯无论升级范围多小都把 Webhook 配置、证书 Secret、IngressClass 指向这三件事放在变更前检查清单里缺一项都不动工。另外升级顺序也值得反复强调优先升控制器再升集群。有不少团队反过来操作先升集群后发现入口控制器崩了流量中断后只能紧急回滚集群版本场面非常混乱。按公告的节奏来该给的提醒官方早就给了真正决定代价大小的是咱们自己动手的速度。这次迁移之后我也建议你把控制器的版本检查加入定期巡检脚本。每个季度花几分钟看一次镜像 tag 和官方稳定版的差距至少不会再被突然的公告打得措手不及。动一次手把下一次的坑也提前填上这笔账怎么算都划算。
阅读完成 · 觉得有帮助?
咨询建站