从 Ingress NGINX Controller 迁移到 Traefik¶
如何以零停机方式从 Ingress NGINX Controller 迁移到 Traefik。
Ingress NGINX Controller 退役
Kubernetes Ingress NGINX Controller 项目已宣布于 2026年3月退役。此后:
- 不再发布新版本或更新
- 不再提供安全补丁
- 不再修复缺陷
更多信息请参阅 Kubernetes 官方博客公告。
迁移后的结果¶
完成迁移后,现有 Ingress 资源无需修改就能由 Traefik 提供服务。Traefik Kubernetes Ingress NGINX 提供者会自动将 NGINX 注解转换为 Traefik 配置:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp
annotations:
# These NGINX annotations are automatically translated by Traefik
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
spec:
ingressClassName: nginx # ← Traefik will watch this class
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: whoami
port:
number: 80apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami
spec:
replicas: 2
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: traefik/whoami
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: whoami
spec:
selector:
app: whoami
ports:
- protocol: TCP
port: 80
targetPort: 80完整的注解支持列表和行为差异,请参阅 Ingress NGINX 路由配置文档。
Traefik 版本要求
Kubernetes Ingress NGINX 提供者要求 Traefik v3.6.2 或更新版本。
前置条件¶
开始迁移前,确保具备:
- Kubernetes 集群中正在运行的现有 Ingress NGINX Controller
- 已配置
kubectl的 Kubernetes 集群访问能力 - 集群支持多个 LoadBalancer 服务同时监听 80/443 端口
- Helm
- 可创建 RBAC 资源的集群管理员权限
- 关键配置备份,包括 Ingress 资源、ConfigMap 和 Secret
备份建议
# Export all Ingress resources
kubectl get ingress --all-namespaces -o yaml > ingress-backup.yaml
# Export NGINX ConfigMaps
kubectl get configmap --all-namespaces -l app.kubernetes.io/name=ingress-nginx -o yaml > nginx-configmaps.yaml
迁移策略概览¶
本迁移通过让 Traefik 与 NGINX 并行运行实现零停机。两个控制器同时为相同的 Ingress 资源提供服务,因此可以逐步切换流量,再移除 NGINX。
Current: DNS → LoadBalancer → NGINX → Your Services
Migration: DNS → LoadBalancer → NGINX → Your Services
→ LoadBalancer → Traefik → Your Services
Final: DNS → LoadBalancer → Traefik → Your Services
迁移流程:
- 步骤 0:检查 ingress-nginx ConfigMap,将集群级默认值转换为 Traefik 配置
- 步骤 1:在 NGINX 旁部署 Traefik
- 步骤 2:验证 Traefik 正确处理流量
- 步骤 3:逐步将流量从 NGINX 切换至 Traefik
- 步骤 4:从 DNS 移除 NGINX,保留 IngressClass,然后卸载
步骤 0:迁移全局 ConfigMap 设置¶
安装 Traefik 前,检查当前 ingress-nginx ConfigMap 中设置的全局默认值。
在 ingress-nginx 中,控制器 ConfigMap 是集群级配置层。
在 Traefik 中,相同行为分布在以下位置:
providers.kubernetesIngressNGINX静态配置,提供 ingress-nginx 兼容性默认值- 入口点,控制 HTTP 到 HTTPS 重定向、PROXY 协议等监听器行为
- 动态
tls.options和 HTTP 中间件,控制 TLS 策略、HSTS 及其他 HTTP 头行为 - Traefik 访问日志配置,记录请求日志
先导出现有 ConfigMap,并检查自定义过的键:
kubectl get configmap --all-namespaces -l app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/component=controller -o yaml
无论安装 ingress-nginx 时使用什么命名空间或发布名称,该标签选择器都可以定位控制器 ConfigMap。
复制数值前先转换 NGINX 单位
部分 ingress-nginx ConfigMap 键使用 16k、1m 或 30s 等 NGINX 格式的值。
Traefik 中对应的 providers.kubernetesIngressNGINX 选项要求:
- 消息体大小和缓冲设置使用原始字节数
proxyConnectTimeout和proxyNextUpstreamTimeout使用整数秒proxyRequestBuffering和proxyBuffering使用布尔值
ConfigMap 到 Traefik 的映射¶
| ingress-nginx ConfigMap 键 | Traefik 对应项 (提供者选项) |
说明 |
|---|---|---|
proxy-connect-timeout |
proxyConnectTimeout |
使用整数秒。 |
proxy-request-buffering |
proxyRequestBuffering |
将 on / off 转换为 true / false。ingress-nginx 默认启用请求缓冲,Traefik 则默认为 false。 |
client-body-buffer-size |
clientBodyBufferSize |
将 16k 等值转换为字节。 |
proxy-buffering |
proxyBuffering |
将 on / off 转换为 true / false。 |
proxy-body-size |
proxyBodySize |
将 1m 等值转换为字节。 |
proxy-buffer-size |
proxyBufferSize |
将 8k 等值转换为字节。 |
proxy-buffers-number |
proxyBuffersNumber |
保留整数值。 |
proxy-next-upstream |
proxyNextUpstream |
使用空格分隔的重试条件列表,例如 error timeout http_502。 |
proxy-next-upstream-timeout |
proxyNextUpstreamTimeout |
使用整数秒。 |
proxy-next-upstream-tries |
proxyNextUpstreamTries |
保留整数值。 |
custom-http-errors |
customHTTPErrors |
如需全局错误页面服务,还应配置 providers.kubernetesIngressNGINX.defaultBackendService。 |
global-allowed-response-headers |
globalAllowedResponseHeaders |
nginx.ingress.kubernetes.io/custom-headers 注解生效所必需。 |
allow-cross-namespace-resources |
allowCrossNamespaceResources |
迁移后的 Ingress 需要引用其他命名空间中受支持的资源时使用。 |
strict-validate-path-type |
strictValidatePathType |
Traefik v3.7 中此选项默认为 true。 |
ssl-redirect / force-ssl-redirect |
nginx.ingress.kubernetes.io/ssl-redirect 和 nginx.ingress.kubernetes.io/force-ssl-redirect 注解,或集群级入口点重定向 |
存在注解时,Traefik 会转换它们。如需全局默认值,在 web 入口点上配置 HTTP 到 HTTPS 重定向;如果需要显式选择入口点,则设置 providers.kubernetesIngressNGINX.httpEntryPoint / httpsEntryPoint。 |
ssl-protocols / ssl-ciphers |
TLS 选项 | 通过入口点 TLS 选项全局应用,或通过 traefik.ingress.kubernetes.io/router.tls.options 按 Ingress 应用。 |
hsts, hsts-max-age, hsts-include-subdomains, hsts-preload |
Headers 中间件 | 使用 stsSeconds、stsIncludeSubdomains、stsPreload 和 forceSTSHeader。将中间件附加到入口点,即可作为集群级默认值。 |
use-proxy-protocol |
入口点 proxyProtocol 配置 |
在位于 PROXY 协议负载均衡器之后的每个入口点上配置。 |
access-log-path |
accessLog.filePath |
静态配置。 |
log-format-upstream |
accessLog.format |
使用 Traefik 内置的 common、genericCLF 或 json 格式。自定义 NGINX 日志格式字符串没有一一对应项。 |
没有直接对应项的 ConfigMap 键¶
部分 ingress-nginx ConfigMap 键专属于 NGINX,在迁移时可以移除,因为 Traefik 不暴露原始 NGINX 内部配置。 常见例子包括:
worker-processes、worker-cpu-affinity和 Lua 共享字典设置等工作进程调优项main-snippet、http-snippet、server-snippet、location-snippet和stream-snippet等片段类键- 超出 Traefik 内置访问日志格式的自定义 NGINX 日志模板
遇到这类键时,应转换它们想达到的目的,而不是逐字复制指令。
参考页面¶
- Kubernetes Ingress NGINX 提供者配置
- Traefik TLS 选项
- Traefik Headers 中间件
- Traefik 入口点配置
- ingress-nginx ConfigMap 参考
步骤 1:在 NGINX 旁安装 Traefik¶
安装 Ingress NGINX Controller
如果尚未安装 Ingress NGINX Controller,可以按以下步骤全新安装:
安装 Ingress NGINX Controller¶
helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace
启用 Kubernetes Ingress NGINX 提供者并安装 Traefik。两个控制器将同时为相同的 Ingress 资源提供服务。
先阅读状态竞态说明
两个控制器共同管理相同 Ingress 时,会争用 status.loadBalancer.ingress[] 字段。安装前,先阅读步骤 3 中的 Ingress 状态竞态,决定采用哪种缓解方式:关闭 Traefik 的 publishService,或使用过渡 IngressClass。
添加 Traefik Helm 仓库¶
helm repo add traefik https://traefik.github.io/charts
helm repo update
安装 Traefik¶
helm upgrade --install traefik traefik/traefik \
--namespace traefik --create-namespace \
--set providers.kubernetesIngressNGINX.enabled=true
也可以通过 values 文件进行更多配置:
...
providers:
kubernetesIngressNGINX:
enabled: true
...helm upgrade --install traefik traefik/traefik \
--namespace traefik --create-namespace \
--values traefik-values.yaml
确认两个控制器均在运行¶
# Check NGINX pods
kubectl get pods -n ingress-nginx
# Check Traefik pods
kubectl get pods -n traefik
# Check both services have LoadBalancer IPs
kubectl get svc -n ingress-nginx ingress-nginx-controller
kubectl get svc -n traefik traefik
此时 NGINX 和 Traefik 都已运行,能够为相同 Ingress 资源提供服务。但由于 DNS 仍指向 NGINX LoadBalancer,流量仍只经过 NGINX。
步骤 2:验证 Traefik 正确处理流量¶
将 Traefik 加入 DNS 前,先确认它能够正确服务现有 Ingress 资源。
通过 Traefik 的 LoadBalancer IP 测试¶
获取 Traefik 的 LoadBalancer IP,并使用 --resolve 测试,无需修改 DNS:
# Get LoadBalancer IPs
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"
# Test HTTP for both
FQDN=myapp.example.com
# Observe HTTPS redirections:
curl --connect-to "${FQDN}:80:${NGINX_IP}:80" "http://${FQDN}" -D -
curl --connect-to "${FQDN}:80:${TRAEFIK_IP}:80" "http://${FQDN}" -D - # note X-Forwarded-Server which should be traefik
# Test HTTPS
curl --connect-to "${FQDN}:443:${NGINX_IP}:443" "https://${FQDN}"
curl --connect-to "${FQDN}:443:${TRAEFIK_IP}:443" "https://${FQDN}"
迁移期间的 TLS 证书
NGINX 和 Traefik 都必须提供有效 TLS 证书,HTTPS 测试才能通过。由于在这个验证阶段 Traefik 尚未公开暴露,Let's Encrypt HTTP 挑战无法工作。
迁移期间可以采用以下 TLS 证书方案:
- 通过
tls.secretName使用现有证书:如果使用 cert-manager 或其他外部工具,spec.tls引用的现有 TLS Secret 可同时供两个控制器使用。 - Let's Encrypt DNS 挑战:配置 Traefik 的 ACME DNS 挑战,无需公开暴露服务即可获取证书。
避免使用 curl -k(跳过证书验证),因为它会掩盖 TLS 配置问题,导致迁移后才暴露故障。
确认 Ingress 发现¶
检查 Traefik 日志,确认已发现现有 Ingress 资源:
kubectl logs -n traefik deployment/traefik | grep -i "ingress"
步骤 3:将流量切换到 Traefik¶
确认两个控制器均在运行且验证通过后,逐步将流量从 NGINX 切换到 Traefik。
方案 A:基于 DNS 的迁移¶
将 Traefik LoadBalancer IP 与 NGINX 地址一起加入 DNS 记录,让两个控制器都可以接收流量。
获取 LoadBalancer 地址:
# NGINX LoadBalancer
echo $(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 LoadBalancer
echo $(kubectl get svc -n traefik traefik -o go-template='{{ $ing := index .status.loadBalancer.ingress 0 }}{{ if $ing.ip }}{{ $ing.ip }}{{ else }}{{ $ing.hostname }}{{ end }}')
逐步迁移 DNS:
- 将 Traefik 加入 DNS:把 Traefik LoadBalancer IP 加入 DNS 记录,此时两个 IP 通过轮询接收流量。
- 监控:观察两个控制器上的流量模式。
- 从 DNS 移除 NGINX:确认无误后,移除 NGINX LoadBalancer IP。
- 等待 DNS 传播:留出时间让 DNS 缓存过期。
- 卸载 NGINX:进入步骤 4。
DNS TTL 可能不被遵守
有些 ISP 为降低流量成本会忽略 DNS TTL,让缓存记录保留得更久。从 DNS 移除 NGINX 后,至少继续运行 NGINX 24–48 小时再卸载,避免仍使用过期 DNS 缓存的用户流量中断。
并行运行期间的 Ingress 状态竞态
当两个控制器管理相同 Ingress 资源(相同的 ingressClassName: nginx)时,它们都会尝试把 LoadBalancer 地址写入各自管理的每个 Ingress 的 status.loadBalancer.ingress[]。两边在密集协调循环中不断相互覆盖,日志却不报错,只在两侧反复出现 Updated ingress status 信息。
路由本身不受影响,两个控制器在并行期间都能正确处理流量。但持续变化的状态字段会影响所有监听者:
- ExternalDNS 可能在两个 LoadBalancer IP 之间反复切换 DNS 记录。
- 观察 Ingress 状态的 kube-state-metrics、监控仪表盘和告警规则。
- ArgoCD 或 Flux 等 GitOps 工具会为每个受影响的 Ingress 持续报告配置漂移。
- 根据 Ingress 状态字段执行协调的自定义 Operator。
推荐缓解方式(方案 1):并行期间关闭 Traefik 状态发布
-
安装 Traefik 时关闭
publishService:# traefik-values.yaml providers: kubernetesIngressNginx: enabled: true publishService: enabled: false # Disable to prevent status updatesTraefik 继续正常服务 Ingress,只是不再写状态字段,由 NGINX 成为唯一写入者。
-
测试 Traefik,使用端口转发或独立测试主机名。
-
通过 NGINX 切换 DNS(仅适用于 ExternalDNS 用户)。配置 NGINX 发布 Traefik 服务地址,让 ExternalDNS 将流量指向 Traefik:
# nginx-values.yaml controller: publishService: pathOverride: "traefik/traefik" # Points to Traefik's service -
确认流量经过 Traefik。此时仍可通过移除
pathOverride回滚。
替代缓解方式(方案 2):使用过渡 IngressClass
为正在迁移的 NGINX 设置独立 IngressClass,例如 nginx-migration,让两个控制器永远不同时拥有同一 Ingress。这也是 SUSE 为 RKE2 迁移记录的方法,参见 SUSE:从 Ingress NGINX 迁移到 Traefik。它能完全避免争用 status.loadBalancer.ingress[],代价是需要一次短暂的流量切换步骤,而不是逐步调整 DNS。
方案 B:使用外部负载均衡器分配加权流量¶
如需更精确地控制流量分配,可以在两个 Kubernetes LoadBalancer 前放置外部负载均衡器,例如 Traefik、Cloudflare、AWS ALB 或专用负载均衡器。
基础设施前置条件
本方案假设基础设施中已经有外部负载均衡器,或愿意在迁移开始前搭建。添加外部负载均衡器属于重要基础设施变更,应与入口控制器迁移分开规划和测试。
配置步骤:
- 创建指向 NGINX Kubernetes LoadBalancer 的外部负载均衡器。
- 更新 DNS,使其指向外部负载均衡器。
- 将 Traefik Kubernetes LoadBalancer 以较低权重(例如 10%)加入外部负载均衡器。
- 逐渐增加 Traefik 权重,同时降低 NGINX 权重。
- NGINX 不再接收流量后,将其卸载。
权重调整示例:
| 阶段 | NGINX 权重 | Traefik 权重 | 持续时间 |
|---|---|---|---|
| 初始 | 100% | 0% | - |
| 开始 | 90% | 10% | 1 小时 |
| 增加 | 50% | 50% | 2 小时 |
| 接近完成 | 10% | 90% | 4 小时 |
| 最终 | 0% | 100% | - |
外部负载均衡器选项
- Cloudflare Load Balancing:带健康检查的流量调度。
- AWS Global Accelerator:在端点之间进行加权路由。
- Google Cloud Load Balancing:流量分配。
- Traefik / HAProxy / NGINX(外部部署):支持加权后端的自托管方案。
- ……
保留 LoadBalancer IP¶
如果希望 Traefik 最终使用与 NGINX 相同的 LoadBalancer IP,以简化 DNS 管理,可以在迁移后转移 IP。由于 Traefik 已经使用自己的 LoadBalancer 运行,这一过程可以实现零停机。
零停机 IP 转移流程:
- Traefik 已使用自己的 LoadBalancer IP 运行(来自步骤 1)。
- 将 Traefik LoadBalancer IP 加入 DNS,此时流量同时到达 NGINX 和 Traefik。
- 从 DNS 移除 NGINX IP,等待传播。
- 删除 NGINX LoadBalancer 服务以释放 IP。
- 升级 Traefik,申请已释放的 IP。
- 新 IP 生效后,可选地从 DNS 移除 Traefik 的旧 IP。
这样在 IP 转移期间,流量始终能够到达 Traefik。
获取当前 NGINX LoadBalancer 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 }}'
AWS(使用弹性 IP 的 Network Load Balancer)
AWS 不支持为 Classic Load Balancer 使用静态 IP,应改用带弹性 IP 的 Network Load Balancer(NLB)。这要求集群中已安装 AWS Load Balancer Controller。
预先分配弹性 IP,每个可用区一个:
aws ec2 allocate-address --domain vpc --region <your-region>
# Note the AllocationId (eipalloc-xxx) for each EIP
更新 traefik-values.yaml:
service:
type: LoadBalancer
loadBalancerClass: service.k8s.aws/nlb # Requires AWS Load Balancer Controller
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-eip-allocations: "eipalloc-xxx,eipalloc-yyy"
更多详情请参阅 AWS Load Balancer Controller 注解文档。
Azure
Azure 支持为 Load Balancer 使用静态公网 IP。
确定现有公网 IP:
az network public-ip list --resource-group <your-resource-group> \
--query "[?ipAddress=='<your-ip>'].name" -o tsv
更新 traefik-values.yaml:
service:
type: LoadBalancer
annotations:
# Only needed if the public IP is in a different resource group than the AKS cluster
service.beta.kubernetes.io/azure-load-balancer-resource-group: "<public-ip-resource-group>"
spec:
loadBalancerIP: "<your-existing-ip>"
更多详情请参阅 Azure AKS 静态 IP 文档。
GCP
GCP 通过保留区域 IP 地址支持静态 IP。
保留或确定现有 IP:
# List existing static IPs
gcloud compute addresses list
# Or reserve a new regional static IP (must be in the same region as your GKE cluster)
gcloud compute addresses create traefik-ip --region <your-cluster-region>
更新 traefik-values.yaml:
service:
type: LoadBalancer
spec:
loadBalancerIP: "<your-static-ip>"
更多详情请参阅 GKE LoadBalancer Service 参数文档。
OVHcloud
OVHcloud Public Load Balancer 支持静态 IP;它基于 Openstack Octavia,为 LoadBalancer 服务分配浮动 IP。这要求集群安装 Openstack Cloud Controller Manager。如果使用 OVHcloud Managed Kubernetes Service(MKS),Openstack Cloud Controller Manager 已由平台安装和管理。
从 NGINX 迁移到 Traefik 时,如需保留现有浮动 IP:
确定现有公网 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 }}')
echo "NGINX IP: $NGINX_IP"
编辑现有 NGINX LoadBalancer 服务,确保删除负载均衡服务时不释放浮动 IP:
kubectl annotate svc my-lb-svc loadbalancer.openstack.org/keep-floatingip=true
keep-floatingip 注解可防止删除或修改服务时释放浮动 IP。
删除 NGINX LoadBalancer 服务,释放浮动 IP 的服务绑定
更新 traefik-values.yaml:
service:
type: LoadBalancer
spec:
loadBalancerIP: "<your-existing-floating-ip>"
其他云提供商
- DigitalOcean: 支持通过浮动 IP 设置
loadBalancerIP。 - Linode: 支持指定
loadBalancerIP。 - 裸机(MetalLB): 使用 IP 地址池。
转移 IP:
DNS 已指向 Traefik,且 values 已配置目标 IP 后:
# Ensure Traefik is already receiving traffic via its current LoadBalancer
kubectl get svc -n traefik traefik
# Delete NGINX LoadBalancer service to release the IP
kubectl delete svc -n ingress-nginx ingress-nginx-controller
# Upgrade Traefik to claim the released IP
helm upgrade traefik traefik/traefik \
--namespace traefik \
--values traefik-values.yaml
# Verify Traefik now has the old NGINX IP
kubectl get svc -n traefik traefik
Helm 升级期间零停机
Helm 升级只重启 Traefik Pod,不重启 LoadBalancer 服务。Traefik 默认采用 RollingUpdate 部署策略,因此新 Pod 会先启动,旧 Pod 再终止。如需进一步保障,可配置高可用:
# In traefik-values.yaml
deployment:
replicas: 2
# Spread pods across nodes to survive node failures
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: traefik
app.kubernetes.io/instance: traefik
topologyKey: kubernetes.io/hostname
# Ensure at least one pod is always available during disruptions
podDisruptionBudget:
enabled: true
minAvailable: 1
多副本分布在不同节点,并配合 PodDisruptionBudget 后,升级和节点维护期间始终至少有一个 Pod 运行。
步骤 4:卸载 Ingress NGINX Controller¶
NGINX 不再接收流量后,将其从集群移除。卸载前,必须确保保留 nginx IngressClass,Traefik 需要它继续发现现有 Ingress。
保留 IngressClass¶
通过 Helm 安装 NGINX 的情况
添加 helm.sh/resource-policy: keep 注解,通知 Helm 保留 IngressClass:
# Add the required annotation
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"}'
# Check that the annotation is really here
kubectl describe ingressclass nginx
--reuse-values 参数至关重要,它会保留全部现有 NGINX 配置。不使用此参数,Helm 会将所有配置重置为默认值,可能破坏现有部署。
kubectl annotate/patch/edit 不起作用
通过 kubectl annotate、kubectl patch 或 kubectl edit 添加注解,并不能让 Helm 保留 IngressClass。Helm 内部存储发布状态,检查的是内部清单中的注解,而不是集群实时状态。只有 helm upgrade 会更新 Helm 内部状态。
通过 GitOps(ArgoCD、Flux)安装 NGINX 的情况
确保 nginx IngressClass 在 Git 仓库中定义为独立资源,与 NGINX Helm 发布分离:
# ingressclass.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
手动安装 NGINX 的情况
将 IngressClass 创建为独立资源:
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
EOF
删除 NGINX 准入 Webhook¶
应删除准入 Webhook,避免 NGINX 移除后修改 Ingress 时出现问题:
kubectl delete validatingwebhookconfiguration ingress-nginx-admission
kubectl delete mutatingwebhookconfiguration ingress-nginx-admission --ignore-not-found
卸载 NGINX¶
helm uninstall ingress-nginx -n ingress-nginx
如果已添加 helm.sh/resource-policy: keep 注解,应看到:
These resources were kept due to the resource policy:
[IngressClass] nginx
release "ingress-nginx" uninstalled
确认 IngressClass 存在¶
kubectl get ingressclass nginx
如果 IngressClass 意外被删除,可以使用保留 IngressClass一节中的命令重新创建。
清理 NGINX 命名空间¶
kubectl delete namespace ingress-nginx
迁移完成
恭喜,你已经以零停机方式从 Ingress NGINX Controller 迁移到 Traefik。现有 ingressClassName: nginx 的 Ingress 继续工作,现在由 Traefik 提供服务。
故障排查¶
Traefik 提供仪表盘,可帮助了解运行情况。 参阅专门文档启用仪表盘。
Traefik 未发现 Ingress
# Verify IngressClass exists
kubectl get ingressclass nginx
# Check Traefik provider configuration
kubectl logs -n traefik deployment/traefik | grep -i "nginx\|ingress"
# Verify Ingress has correct ingressClassName
kubectl get ingress <name> -o yaml | grep ingressClassName
注解未按预期工作
一些 NGINX 注解在 Traefik 中存在行为差异,详见限制文档。
TLS 证书无法工作
现有 TLS 配置可以继续用于 Traefik:
spec.tls条目原样保留;Traefik 使用引用的 Secret 终止 TLS。- TLS Secret 必须保留在与 Ingress 相同的命名空间中。
- NGINX 的
ssl-redirect/force-ssl-redirect注解仍会被遵守。
# Verify TLS secret exists in the same namespace as Ingress
kubectl get secrets -n <namespace>
# Check secret format
kubectl get secret <tls-secret-name> -n <namespace> -o yaml
未分配 LoadBalancer IP
# Check service status
kubectl describe svc -n traefik traefik
# Check for events
kubectl get events -n traefik --sort-by='.lastTimestamp'
后续步骤¶
进一步了解 Traefik:
- Kubernetes Ingress NGINX 安装配置:详细的提供者配置。
- Kubernetes Ingress NGINX 路由配置:路由规则与注解支持。
- HTTP 中间件:扩展 NGINX 注解之外的功能。
- TLS 配置:高级 TLS 与证书管理。
增强部署:
- 启用指标和追踪。
- 配置访问日志,提高可观测性。
- 探索 Traefik 中间件,实现高级流量管理。
- 从基于 Nginx 的配置迁移到 Traefik IngressRoute 或 Kubernetes Gateway API。
- 考虑使用 Traefik Hub,获取 AI 与 API 网关、API 管理和高级安全等企业功能。
反馈与支持¶
如果迁移中遇到问题,或对本指南有改进建议:
- 报告问题: GitHub Issues
- 社区支持: Traefik 社区论坛
- 企业支持: Traefik Labs 商业支持
欢迎为本迁移指南贡献改进。开始前请阅读贡献指南。