如何不修改 Ingress 注解把 Kubernetes 从 Ingress NGINX 迁移到 Traefik
发布时间:2026/9/9 21:23:33 作者:尧图编辑部 阅读量:1,286

如何不修改 Ingress 注解把 Kubernetes 从 Ingress NGINX 迁移到 Traefik【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik如果你的集群目前用 Ingress NGINX Controller 做入口又不想逐个改写现有 Ingress 上的nginx.ingress.kubernetes.io/*注解Traefik 提供了直接的迁移路径它的 Kubernetes Ingress NGINX Provider 会自动把 NGINX 注解翻译成 Traefik 的动态配置现有 Ingress 资源可以原样保留、继续工作。背景是 Ingress NGINX Controller 项目已宣布在 2026 年 3 月退役此后不再有新版本、安全补丁或缺陷修复见 迁移指南 开头的说明。本文按官方迁移指南给出完整操作路径并行部署 Traefik、验证其能正确处理你现有的 Ingress、把流量从 NGINX 切到 Traefik、最后卸载 NGINX 并保留nginx这个 IngressClass。全程不改动任何 Ingress 对象。版本前提Kubernetes Ingress NGINX provider 要求Traefik v3.6.2 或更高版本。准备工作官方文档列出的前置条件集群中已有运行中的 Ingress NGINX Controller配好kubectl的集群访问权限且有集群管理员权限要创建 RBAC 资源集群支持在 80/443 端口上同时跑多个 LoadBalancer 类型的 Service并行期间需要已安装 Helm。先备份关键配置。以下命令只读取资源并导出为本地文件不影响集群# 导出所有 Ingress 资源 kubectl get ingress --all-namespaces -o yaml ingress-backup.yaml # 导出 NGINX ConfigMaps kubectl get configmap --all-namespaces -l app.kubernetes.io/nameingress-nginx -o yaml nginx-configmaps.yamlStep 0把全局 ConfigMap 设置翻译成 Traefik 配置Ingress 注解不用动但 ingress-nginx 的全局 ConfigMap 默认值需要人工翻译到 Traefik 侧否则全局行为会变。先导出你当前使用的控制器 ConfigMap这个 label selector 与命名空间、release 名无关kubectl get configmap --all-namespaces -l app.kubernetes.io/nameingress-nginx,app.kubernetes.io/componentcontroller -o yaml在 Traefik 中这些全局默认值分散在providers.kubernetesIngressNGINX静态配置、entryPoints、tls.options和 HTTP middlewares 里。对照官方映射表逐项迁移ingress-nginx ConfigMap keyTraefik 等价项provider options说明proxy-connect-timeoutproxyConnectTimeout用整数秒proxy-request-bufferingproxyRequestBufferingon/off转true/false注意 ingress-nginx 默认开启请求缓冲Traefik 默认falseclient-body-buffer-sizeclientBodyBufferSize16k这类值要转成字节proxy-bufferingproxyBufferingon/off转true/falseproxy-body-sizeproxyBodySize1m这类值要转成字节proxy-buffer-sizeproxyBufferSize8k这类值要转成字节proxy-buffers-numberproxyBuffersNumber保持整数proxy-next-upstreamproxyNextUpstream空格分隔的列表如error timeout http_502proxy-next-upstream-timeoutproxyNextUpstreamTimeout整数秒proxy-next-upstream-triesproxyNextUpstreamTries保持整数custom-http-errorscustomHTTPErrors如要全局错误页服务同时配置providers.kubernetesIngressNGINX.defaultBackendServiceglobal-allowed-response-headersglobalAllowedResponseHeaders不配置则custom-headers注解不生效allow-cross-namespace-resourcesallowCrossNamespaceResources跨命名空间引用资源时使用strict-validate-path-typestrictValidatePathTypeTraefik v3.7 起该选项默认为truessl-redirect/force-ssl-redirect对应注解或入口级 HTTP→HTTPS 重定向注解存在时 Traefik 会自动翻译要全局默认则在web入口配置重定向必要时设置httpEntryPoint/httpsEntryPointssl-protocols/ssl-ciphersTLS options通过入口级 TLS option 全局应用或按 Ingress 用traefik.ingress.kubernetes.io/router.tls.optionshsts、hsts-max-age、hsts-include-subdomains、hsts-preloadHeaders middleware用stsSeconds、stsIncludeSubdomains、stsPreload、forceSTSHeader挂在入口上作为全局默认use-proxy-protocol入口点proxyProtocol配置配置在每个位于 PROXY protocol 负载均衡器之后的入口点上access-log-pathaccessLog.filePath静态配置log-format-upstreamaccessLog.format只能选 Traefik 内置的common、genericCLF、json自定义 NGINX 日志格式没有 1:1 等价两类 key 可以直接丢弃worker 调优类worker-processes、worker-cpu-affinity、Lua shared dict 等和 snippet 类main-snippet、http-snippet、server-snippet、location-snippet、stream-snippet。Traefik 不暴露底层 NGINX 内部结构这类 key 要翻译其意图而不是照抄指令。provider 配置项的完整清单和默认值见 Kubernetes Ingress NGINX provider 配置文档。Step 1与 NGINX 并行安装 Traefik添加 Traefik Helm 仓库并启用 Kubernetes Ingress NGINX providerhelm repo add traefik https://traefik.github.io/charts helm repo updatehelm upgrade --install traefik traefik/traefik \ --namespace traefik --create-namespace \ --set providers.kubernetesIngressNGINX.enabledtrue更多配置可以用 values 文件最小形式# traefik-values.yaml providers: kubernetesIngressNGINX: enabled: truehelm upgrade --install traefik traefik/traefik \ --namespace traefik --create-namespace \ --values traefik-values.yamlprovider 的默认发现逻辑是controllerClass默认匹配k8s.io/ingress-nginxingressClass默认值为nginx——即直接接管你现在 Ingress 里ingressClassName: nginx指的那类资源无需改名。确认两个控制器都在跑# 检查 NGINX pods kubectl get pods -n ingress-nginx # 检查 Traefik pods kubectl get pods -n traefik # 检查两个 Service 是否都有 LoadBalancer IP kubectl get svc -n ingress-nginx ingress-nginx-controller kubectl get svc -n traefik traefik此时流量仍只走 NGINXDNS 指向 NGINX 的 LoadBalancerTraefik 处于影子运行状态。共存的已知问题Ingress status 竞态。两个控制器同时管理同一批 Ingress 时都会反复把各自的 LoadBalancer 地址写进status.loadBalancer.ingress[]日志里只有重复的Updated ingress status信息行、没有报错。路由本身不受影响但所有依赖 status 字段的组件都会受干扰ExternalDNS 会在两个 IP 之间来回改 DNS 记录GitOps 工具ArgoCD/Flux会持续报 drift监控告警也会抖动。官方推荐的处理是共存期间禁用 Traefik 的 status 发布# traefik-values.yaml providers: kubernetesIngressNginx: enabled: true publishService: enabled: false # Disable to prevent status updatesTraefik 照常服务 Ingress只是不再写 status 字段由 NGINX 保持唯一写入方。替代方案是给迁移中的 NGINX 一个独立的 IngressClass例如nginx-migration让两个控制器不同时拥有同一个 Ingress彻底避免竞争代价是用一次短暂切流替代渐进式 DNS 迁移。Step 2验证 Traefik 能正确处理你的 Ingress在把 Traefik 加进 DNS 之前先直接打它的 LoadBalancer IP 验证。用--connect-to把域名定向到指定 IP不需要改 DNS# 获取两个 LoadBalancer IP NGINX_IP$(kubectl get svc -n ingress-nginx ingress-nginx-controller -o go-template{{ $ing : index .status.loadBalancer.ingress 0 }}{{ if $ing.ip }}{{ $ing.ip }}{{ else }}{{ $ing.hostname }}{{ end }}) TRAEFIK_IP$(kubectl get svc -n traefik traefik -o go-template{{ $ing : index .status.loadBalancer.ingress 0 }}{{ if $ing.ip }}{{ $ing.ip }}{{ else }}{{ $ing.hostname }}{{ end }}) echo -e Nginx IP: $NGINX_IP\nTraefik IP: $TRAEFIK_IP # 分别对两边测 HTTPFQDN 换成你自己的域名 FQDNmyapp.example.com # 观察 HTTPS 重定向行为 curl --connect-to ${FQDN}:80:${NGINX_IP}:80 http://${FQDN} -D - curl --connect-to ${FQDN}:80:${TRAEFIK_IP}:80 http://${FQDN} -D - # 注意 Traefik 一侧响应头中的 X-Forwarded-Server 应为 traefik # 测 HTTPS curl --connect-to ${FQDN}:443:${NGINX_IP}:443 https://${FQDN} curl --connect-to ${FQDN}:443:${TRAEFIK_IP}:443 https://${FQDN}判断标准Traefik 一侧的响应头里X-Forwarded-Server显示为 traefik说明请求确实由 Traefik 处理且ssl-redirect这类注解的重定向行为与 NGINX 侧一致。另外确认 Traefik 发现了你的 Ingresskubectl logs -n traefik deployment/traefik | grep -i ingressTLS 证书的迁移期限制验证阶段 Traefik 没有公网入口Lets Encrypt HTTP challenge 不可用。文档给出的两条路你已在spec.tls里用tls.secretName引用现有证书cert-manager 或其他方式签发则同一批 TLS secret 两个控制器都能用保持原样即可或者给 Traefik 配置 ACME DNS challenge 获取证书。不要依赖curl -k跳过证书校验来通过验证——这会掩盖迁移后才会暴露的 TLS 配置问题。Step 3把流量从 NGINX 切到 TraefikOption ADNS 渐进迁移文档主路径。把 Traefik 的 LoadBalancer IP 加进 DNS 记录此时两个 IP 轮询接流量把 Traefik LoadBalancer IP 加入 DNS两边都收流量观察两侧流量与行为确认后从 DNS 移除 NGINX IP等待 DNS 缓存过期进入 Step 4 卸载 NGINX。一个必须知道的边界部分 ISP 会忽略 DNS TTL 以减少成本、缓存记录更久。所以从 DNS 移除 NGINX 后至少再等 24–48 小时、让 NGINX 保持运行再执行卸载否则持旧缓存的用户请求会落空。Option B外部负载均衡按权重切流可选分支。前提是你在基础设施里已有或愿意提前搭建一个外部负载均衡器。做法是把外部 LB 指向 NGINX LoadBalancer再按低权重如 10%加入 Traefik LoadBalancer逐步提高 Traefik 权重至 100%然后卸载 NGINX。文档给出一组示例权重进度90/10 → 50/50 → 10/90 → 0/100这只是示例数值实际节奏按你的监控结果决定。这一步属于独立的基建变更文档建议与 ingress 迁移分开规划和测试。如果希望最终 DNS 不变Traefik 接管 NGINX 原来的 IP文档还描述了零停机 IP 转移流程先把 Traefik IP 加入 DNS → 移除 NGINX IP 并等待传播 → 删除 NGINX LoadBalancer service 释放 IP → 用helm upgrade让 Traefik 认领该 IPservice.spec.loadBalancerIP指向原 IP。不同云平台AWS NLBEIP、Azure 静态 IP、GCP 区域保留 IP、OVHcloud 浮动 IP 等的 values 写法在 迁移指南 中有各自的说明按需查阅。Step 4保留 IngressClass然后卸载 NGINX这是不修改 Ingress能否长期成立的关键Traefik 依赖nginx这个 IngressClass 继续发现你的 Ingress。卸载前必须先确保它会留下来。如果 NGINX 是 Helm 装的用helm upgrade给 IngressClass 加helm.sh/resource-policy: keep注解helm upgrade ingress-nginx ingress-nginx \ --repo https://kubernetes.github.io/ingress-nginx \ --namespace ingress-nginx \ --reuse-values \ --set-json controller.ingressClassResource.annotations{helm.sh/resource-policy: keep} # 确认注解已生效 kubectl describe ingressclass nginx--reuse-values不可省它会保留你现有的全部 NGINX 配置缺了它 Helm 会把配置重置为默认。文档特别强调用kubectl annotate/patch/edit加这个注解不会奏效——Helm 对照的是自己内部存储的 release 状态只有helm upgrade会更新它。如果是 GitOpsArgoCD/Flux装的把nginxIngressClass 作为独立资源放进仓库与 NGINX Helm release 解耦。如果是手工部署的直接kubectl apply一个独立 IngressClasskubectl apply -f - EOF apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: nginx spec: controller: k8s.io/ingress-nginx EOF接着删除 NGINX 的 admission webhook否则 NGINX 移除后 Ingress 的修改可能出问题再卸载kubectl delete validatingwebhookconfiguration ingress-nginx-admission kubectl delete mutatingwebhookconfiguration ingress-nginx-admission --ignore-not-foundhelm uninstall ingress-nginx -n ingress-nginx如果注解加对了卸载输出中应看到文档示例输出These resources were kept due to the resource policy: [IngressClass] nginx release ingress-nginx uninstalled最后核对 IngressClass 还在并清理命名空间kubectl get ingressclass nginx kubectl delete namespace ingress-nginxkubectl get ingressclass nginx能返回该资源即迁移完成所有ingressClassName: nginx的 Ingress 保持原样包括注解改由 Traefik 服务。迁移后需要留意的行为差异注解不改不等于行为完全一致。注解支持与限制文档 列出的关键点默认值差异最常见请求缓冲ingress-nginx 默认开proxy-request-bufferingTraefik 的 provider 选项proxyRequestBuffering默认false要显式开启旧版 scheme 头应用若依赖X-Forwarded-Scheme或X-Scheme需在接收流量的入口上开启entryPoints.name.forwardedHeaders.addXForwardedSchemeHeaderstrueX-Forwarded-Proto不受影响。行为不同项负载均衡只支持 round_robinEWMA 和 IP hash 不支持load-balance注解会被静默忽略限流NGINX 是漏桶算法、超限返回503Traefik 是令牌桶、超限返回429limit-rps/limit-rpm/limit-connections均如此路径处理Traefik 默认保留尾部斜杠NGINX 默认去掉preserve-trailing-slash注解列在不受支持列表因为 Traefik 本来就这样Forward auth 行为不同Traefik 转发原始请求不支持子请求式认证与会话缓存重试不保证打到另一台服务器NGINX 保证换下一台proxy-next-upstream中error与timeout在 Traefik 里都按 TCP 层失败处理无差别。明确不受支持的注解limit-rate系列、proxy-redirect-from/proxy-redirect-to、mirror-target系列、modsecurity 系列、stream-snippet、session-cookie-change-on-failure、ssl-ciphers/ssl-protocols用 TLS options 替代等完整清单见上述Unsupported Annotations一节。另外后端协议上 FCGI 和 AUTO_HTTP 不支持。如果你怀疑某个注解没按预期工作按文档的排查顺序检查# 确认 IngressClass 存在 kubectl get ingressclass nginx # 看 Traefik provider 是否加载、是否发现 Ingress kubectl logs -n traefik deployment/traefik | grep -i nginx\|ingress # 确认 Ingress 的 ingressClassName 正确name 换成你的 Ingress 名 kubectl get ingress name -o yaml | grep ingressClassNameTLS 不工作时的检查点spec.tls条目原样保留、Traefik 用其引用的 secret 终结 TLS但 TLS secret 必须与 Ingress 在同一命名空间# namespace、tls-secret-name 换成实际值 kubectl get secrets -n namespace kubectl get secret tls-secret-name -n namespace -o yaml参考Migrate from Ingress NGINX Controller to Traefik本文操作的完整来源含各云平台 LoadBalancer IP 保留的细节Kubernetes Ingress NGINX provider 配置provider 全部配置项、默认值与 RBAC 要求非 Helm 安装时需自行添加 provider 的 RBACKubernetes Ingress NGINX 路由配置注解分类支持表、行为差异与不支持清单。【免费下载链接】traefikThe Cloud Native Application Proxy项目地址: https://gitcode.com/GitHub_Trending/tr/traefik创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考