1. nginx pod 代理 traefik 后 502/404 的链路断点在哪在 k8s 集群里用 nginx 的 pod 反向代理到 traefik再由 traefik 按 IngressRoute 规则调度到后端业务 pod这套结构本身很常见nginx 负责统一入口和静态资源traefik 负责动态服务发现和负载均衡。但真正跑起来之后很多人会遇到一个很别扭的现象——刚部署完访问正常改一次 Service 或者滚动更新一次 yamlnginx 这边就开始 502 Bad Gateway 或者 404 Not Found而直接访问 traefik 的 Service 又是通的。这个问题的核心不是 nginx 配置写错了也不是 traefik 的 IngressRoute 规则有问题而是nginx pod 里 proxy_pass 指向的那个上游地址在 Service 重建后 IP 变了而 nginx 的 resolver 没有跟着更新。nginx 默认在启动时解析一次域名就缓存住除非显式配置 resolver 和变量式 proxy_pass否则它不会重新去查 CoreDNS。Service 被 replace 或者 selector 变更后 ClusterIP 重新分配nginx 还拿着旧 IP 去连自然 502。另一个容易混淆的点是 404。404 通常不是 nginx 连不上而是请求已经透传到 traefik 了但 traefik 根据 Host 或者 Path 匹配不到对应的 IngressRoute于是返回自己的 404 页面。这时候你要区分502 是链路断在 nginx→traefik 这一段404 是断在 traefik→后端 service 这一段。两者排查方向完全不同。我试过在同一个集群里同时跑 nginx Deployment 和 traefik Deployment用 nginx 的 configMap 挂载配置改完配置 nginx reload 就能恢复但过一段时间 Service 变动后又挂。后来才定位到是 ClusterIP 漂移 nginx DNS 缓存的问题。这篇就把可复制的 nginx.conf 代理段、traefik IngressRoute YAML、固定 ClusterIP 的 Service 写法以及用 TaoToken 统一 Key 核对上游鉴权头的验证命令都整理出来让你从 nginx pod 到 traefik 后端这条链路稳定透传。适合正在搭 k8s 入口层、被 nginx 反代 traefik 的 502/404 卡住的运维和 backend 同学也适合想把 nodePort 换成更优雅方案的人。2. 前置TaoToken 统一 Key 与 API 通道准备在排查 nginx→traefik 链路之前先要把上游鉴权这一层理清楚。很多 502 其实不是网络不通而是 traefik 后面的后端服务要求带 Authorization 头nginx 转发时把 header 丢了或者 Key 不对后端直接拒绝。这时候用 TaoToken 的统一 Key 和 API 通道来核对请求头能快速判断是链路问题还是鉴权问题。TaoToken 是一个统一的大模型 API 接入通道官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。它的作用是把你对不同模型服务的调用收敛到一个 Base URL 和一把 Key 上这样在 k8s 里做上游鉴权核对时不用来回切换多套凭证。你需要准备的东西不多一个 TaoToken 账号一把 API Key以及集群里能跑 curl 的 pod。Key 的获取路径是登录后进控制台在 API Keys 页面创建。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite API Keys 页面是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。创建完把 Key 复制出来后面在 nginx 的 proxy_set_header 里会用到。这里要强调一个概念TaoToken 的统一 Key 不是用来替代 traefik 的而是用来做上游鉴权头的统一管理。你的 nginx pod 在 proxy_pass 到 traefik 时可以带上这个 Key 作为 Authorization 头traefik 再往后端转发。这样整条链路的鉴权凭证是一致的排查时只要用同一个 Key 去 curl就能判断是 nginx 没转发 header还是 traefik 的 middleware 把 header 吃掉了。如果你后面要做长期编码或者 Agent 类任务可以了解 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。模型对话调试入口在 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。Claude Code 相关的 Anthropic 接入说明在 https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecode-anthropicutm_campaignrewrite 。前置准备清单确认 CoreDNS 正常、确认 traefik 的 Service 有 ClusterIP、确认 nginx pod 能解析集群内域名、确认 TaoToken Key 已创建。这四件事做完再往下配 nginx.conf 和 IngressRoute排查效率会高很多。3. 可复制配置nginx.conf 代理段 traefik IngressRoute 固定 ClusterIP这一节是整篇的核心直接给可复制的配置。先说 nginx 的 configMap关键是 resolver 和变量式 proxy_pass这两点决定了 Service IP 变化后 nginx 能不能重新解析。# nginx-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: nginx-proxy-config namespace: default data: nginx.conf: | user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for upstream$upstream_addr; access_log /var/log/nginx/access.log main; # 关键指向 CoreDNS让 nginx 能动态解析集群内 Service resolver kube-dns.kube-system.svc.cluster.local valid10s ipv6off; server { listen 80; server_name _; location /a1app/ { # 变量式 proxy_pass强制每次请求走 resolver set $traefik_upstream traefik.default.svc.cluster.local; proxy_pass http://$traefik_upstream:80; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 带上 TaoToken 统一 Key 作为上游鉴权头 proxy_set_header Authorization Bearer sk-你的TaoTokenKey; proxy_connect_timeout 5s; proxy_read_timeout 30s; proxy_send_timeout 30s; } } }注意 resolver 那行的valid10s意思是 DNS 缓存 10 秒。Service IP 变了之后最多 10 秒 nginx 就会重新解析。如果你不写变量式 proxy_passnginx 启动时解析一次就固定了这就是为什么改 Service 后必须 reload 才能恢复。然后是 traefik 的 IngressRoute这里用 CRD 方式比传统 Ingress 更灵活# traefik-ingressroute.yaml apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: a1app-route namespace: default spec: entryPoints: - web routes: - match: PathPrefix(/a1app) kind: Rule services: - name: a1app-service port: 8080 middlewares: - name: auth-check --- apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: auth-check namespace: default spec: headers: customRequestHeaders: X-Forwarded-By: nginx-proxy再给固定 ClusterIP 的 Service 写法这是解决 IP 漂移最直接的方式# nginx-service-fixed.yaml apiVersion: v1 kind: Service metadata: name: my-nginx namespace: default labels: app: my-nginx spec: clusterIP: 10.254.63.240 ports: - port: 80 targetPort: 80 protocol: TCP selector: app: my-nginx type: ClusterIP把 clusterIP 写死之后即使 Service 被 replace只要这个 IP 没被占用k8s 就会复用。这样 nginx 里 proxy_pass 指向的地址就稳定了。不过要注意固定 IP 要选在 Service CIDR 范围内且没被其他 Service 占用否则创建会失败。如果你用 Cline MCP 或者 Codex 的 auth.json 做本地调试配置三件套是 Base URL、Key、Model ID。Base URL 填 https://taotoken.net/api Key 填你的 TaoToken KeyModel ID 按文档填对应模型标识。这三样对齐了本地请求才能和集群内请求走同一套鉴权逻辑。4. 验证请求从 nginx pod 到 traefik 后端的 curl 命令配置写完必须验证。验证要分层做从 nginx pod 内部往外打一层层确认。第一步进 nginx podkubectl exec -it deploy/my-nginx -- /bin/sh第二步在 pod 内解析 traefik 的 Service 域名确认 CoreDNS 正常nslookup traefik.default.svc.cluster.local正常应该返回 traefik Service 的 ClusterIP。如果这里就失败说明 CoreDNS 或者 Service 有问题先解决这个。第三步直接 curl traefik 的 Service绕过 nginxcurl -v http://traefik.default.svc.cluster.local/a1app/health \ -H Authorization: Bearer sk-你的TaoTokenKey如果这一步返回 200说明 traefik 和后端是通的问题在 nginx 配置。如果返回 404说明 traefik 的 IngressRoute 匹配规则有问题检查 PathPrefix 和 Host。如果返回 502说明 traefik 连不上后端 Service检查后端 pod 的 readiness 和端口。第四步curl nginx 自己的入口验证整条链路curl -v http://my-nginx.default.svc.cluster.local/a1app/health \ -H Authorization: Bearer sk-你的TaoTokenKey这一步如果 502回到 nginx pod 里看 error.logkubectl logs deploy/my-nginx --tail50重点看upstream后面的地址如果是一个已经不存在的旧 IP那就是 DNS 缓存问题确认 resolver 和变量式 proxy_pass 都写对了。第五步用 TaoToken 的模型对话接口做一次端到端验证确认鉴权头透传正确curl -v https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-你的TaoTokenKey \ -d { model: 你的模型ID, messages: [{role: user, content: ping}] }这个请求如果返回正常说明你的 Key 和 Base URL 是对的。然后把这个 Authorization 头原样放到 nginx 的 proxy_set_header 里再走一遍 nginx→traefik 链路对比结果。实测下来最容易出问题的是 header 大小写和空格。nginx 的 proxy_set_header 里Bearer后面必须有一个空格Key 不能有多余换行。traefik 的 middleware 如果配了 customRequestHeaders可能会覆盖掉 nginx 传过来的 Authorization这时候要么去掉 middleware 里的覆盖要么在 middleware 里显式保留。验证通过的标准是从集群外访问 nginx 的 nodePort 或者 LoadBalancer能稳定拿到后端响应且 Service 滚动更新后不需要手动 reload nginx。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth这一节把真实会撞到的报错列出来对照着查。401 Unauthorized这个最常见。表现是 nginx 返回 401但 traefik 日志里看不到请求。原因通常是 nginx 的 proxy_set_header Authorization 没写对或者 Key 过期。排查方法是在 nginx pod 里 curl 后端带上和不带 Authorization 各试一次。如果带 Key 通、不带不通说明后端确实要鉴权检查 nginx 配置里 header 有没有被覆盖。TaoToken 的 Key 可以在 API Keys 页面重新生成地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。local proxy failed这个报错通常出现在本地调试工具或者 Cline MCP 场景。意思是本地代理进程连不上目标地址。在 k8s 场景下等价于 nginx 连不上 traefik。检查三件事traefik 的 Service 是否存在、ClusterIP 是否和 nginx 里配的一致、网络策略 NetworkPolicy 是否放行了 nginx pod 到 traefik pod 的流量。如果用了固定 ClusterIP确认这个 IP 没被其他 Service 抢走。reading choices 相关报错这类报错一般出现在调用大模型接口时响应体解析失败。在 nginx→traefik 链路里如果后端是一个模型服务nginx 的 proxy_read_timeout 太短会导致连接被切断客户端读到半截响应就报解析错误。把 proxy_read_timeout 调到 60s 以上并且确认 proxy_buffering 设置合理。如果响应是流式的还要加proxy_set_header Connection 和proxy_http_version 1.1。OAuth 相关报错如果 traefik 前面挂了 OAuth middlewarenginx 转发时可能会丢掉 cookie 或者 state 参数。检查 nginx 是否透传了 Cookie 头traefik 的 OAuth middleware 配置里 redirect 地址是否和 nginx 暴露的地址一致。OAuth 回调地址不匹配会直接 400 或者 403。404 但后端明明有服务检查 traefik IngressRoute 的 match 规则。PathPrefix 是区分大小写的/a1app和/A1App不一样。另外如果 nginx 的 location 是/a1app/proxy_pass 后面没有斜杠路径拼接会多一层或者少一层。用curl -v看实际请求的 path 是什么。502 且 nginx error.log 显示 no resolver defined说明 proxy_pass 用了变量但没配 resolver。加上resolver kube-dns.kube-system.svc.cluster.local valid10s;即可。Service 更新后必须 reload nginx 才恢复这就是 DNS 缓存问题。确认 proxy_pass 用的是变量且 resolver 的 valid 时间不要太长。如果还是不行检查 nginx 版本老版本对变量式 proxy_pass 的 resolver 支持有差异。排查顺序建议先看 nginx error.log 的 upstream 地址再看 traefik 的 access log最后看后端 pod 的日志。三层日志对时间戳很快能定位断点在哪。6. 稳定透传后的接入方式与长期使用建议链路调通之后日常使用就顺了。nginx pod 负责统一入口traefik 负责动态路由后端 pod 滚动更新不影响入口。固定 ClusterIP 这个做法比 nodePort 优雅的地方在于nodePort 会占用每个节点的端口端口范围有限而且节点 IP 变化后客户端要改配置。ClusterIP 固定在集群内部外部通过 nginx 的 LoadBalancer 或者 nodePort 进来内部链路稳定。如果你要把这套结构用到模型服务上TaoToken 的接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有 Base URL、Key、Model ID 的完整说明。模型对话调试可以用 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。长期跑编码或者 Agent 任务Coding Plan 在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。最后给几个实用技巧。第一nginx 的 resolver valid 时间设 10s 到 30s 之间太短会增加 CoreDNS 压力太长会导致 Service 变更后恢复慢。第二固定 ClusterIP 要记录在案避免和后续创建的 Service 冲突。第三traefik 的 IngressRoute 用 PathPrefix 时注意和 nginx location 的路径拼接最好在 nginx 里用 rewrite 把前缀去掉再转发。第四所有鉴权头统一用 TaoToken 的 Key这样排查时只需要核对一个凭证不用在多个 Key 之间切换。这套配置我在多个集群里跑过稳定运行的关键就是 resolver 变量式 proxy_pass 固定 ClusterIP 这三件套。少任何一个Service 变更后都可能要手动 reload。把这三样配齐nginx pod 到 traefik 后端的透传就不会再断。