
1. 为什么要在 K8s 里用 Traefik 做反向代理很多同学第一次接触 Kubernetes 的 Ingress都是从 Nginx Ingress Controller 开始的。它稳定、资料多但配置热更新依赖 reload服务频繁上下线时偶尔会看到几秒的 502。Traefik 走的是另一条路它原生监听 Kubernetes APIService、Pod、Endpoint 一有变化就自动感知配置热重载进程不重启用户基本无感知。这就是我这次在集群里换用 Traefik 做反向代理的直接原因。Traefik 是什么一句话面向微服务的 HTTP 反向代理和负载均衡器。它能对接 Docker、Swarm、Kubernetes、Consul、Etcd 等多种后端自动发现服务并刷新路由。适合谁适合已经在跑 K8s、想让外部流量按 Host/Path 精准落到后端服务、又不想天天手动改 Nginx 配置的运维和开发同学。这次实践的目标有两个第一用 Traefik 的 IngressRoute 和 Middleware 把外部流量按域名和路径路由到集群内的 dashboard、Kibana 等服务第二把 AI 工具调用的 Base URL 统一改到 TaoToken 的 API 通道让本地脚本、CI、Agent 都走同一个入口省得每个工具单独配 Key。下面从环境准备一路写到 curl 验证和报错排查命令和 YAML 都可以直接复制。需要提前说明的是Traefik 在 K8s 里有两种 CRD 风格老的 Ingress靠 annotation和新的 IngressRouteTraefik 自己的 CRD。前者兼容性好后者表达力强Middleware 就是靠 CRD 才能用的。本文两种都会给重点放在 IngressRoute Middleware因为路径重写、鉴权头注入这些操作用 Middleware 比堆 annotation 清爽太多。2. 部署 Traefik 与前置准备IngressRoute 与 CRD 安装踩坑环境假设你已经有一个能正常kubectl get nodes的集群我用的是 kubeadm 搭的三节点。Traefik 官方提供了 Helm Chart也提供了裸 YAML。为了看清每一步我这里用官方 YAML 走一遍再补 Helm 方式。先拉官方的 k8s 示例目录里面包含 RBAC、Deployment、Service 等文件cd /home/wanyang3/k8s/ git clone https://github.com/traefik/traefik.git ls traefik/docs/content/reference/dynamic-configuration/如果你用的是较新版本CRD 需要单独安装否则 IngressRoute 创建时会报no matches for kind IngressRoute。这一步是新手最容易漏的kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.11/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml装完 CRD再部署 Traefik 本体。RBAC 先上再上 Deploymentkubectl create -f traefik-rbac.yaml kubectl create -f traefik-deployment.yaml kubectl get pods --all-namespaces -o wide | grep traefik正常会看到traefik-ingress-controller-xxx 1/1 Running。它同时开了 80业务入口和 8080Dashboard。查看 Service 暴露的 NodePortkubectl get service --all-namespaces | grep traefik输出类似traefik-ingress-service 10.96.8.191 nodes 80:30016/TCP,8080:30960/TCP。浏览器访问http://node_ip:30960/dashboard/#/能看到 Dashboard。初次打开 Providers 下 Kubernetes 是空的因为还没建任何路由规则这是正常的。这里有个细节值得说Traefik 的 Dashboard 本身也是通过 IngressRoute 暴露的官方示例里叫traefik-dashboard。如果你想让 Dashboard 走域名而不是 NodePort可以自己写一条 IngressRoute把 Host 设成traefik-ui.k8s后端指向apiinternal。这样访问http://traefik-ui.k8s/dashboard/就能进比记端口号舒服。前置准备里还有一件事确认你的 Traefik 版本。kubectl get deploy traefik -n kube-system -o yaml | grep image看一下v2 和 v3 的 CRD apiVersion 不一样v2 是traefik.containo.us/v1alpha1v3 改成了traefik.io/v1alpha1。写 YAML 时 apiVersion 写错报错信息是no matches for kind很多人会误以为是 CRD 没装其实是版本对不上。我踩过的坑就是拿 v2 的示例往 v3 集群上套折腾了半小时才发现是 apiVersion 的问题。3. 可复制配置IngressRoute、Middleware 与 TaoToken 通道片段这一节是全文的核心所有 YAML 和配置片段都可以直接改改就用。先看基于 Host 的 IngressRoute把dashboard.k8s.traefik和ela.k8s.traefik分别路由到 dashboard 和 elasticsearchapiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: dashboard-ela-route namespace: kube-system spec: entryPoints: - web routes: - match: Host(dashboard.k8s.traefik) kind: Rule services: - name: kubernetes-dashboard port: 80 - match: Host(ela.k8s.traefik) kind: Rule services: - name: elasticsearch-logging port: 9200再看基于 Path 的路由这里必须配合 Middleware 做路径重写否则后端服务收到的路径会带上前缀直接 404。Middleware 的stripPrefix就是干这个的apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: strip-dashboard namespace: kube-system spec: stripPrefix: prefixes: - /dashboard --- apiVersion: traefik.io/v1alpha1 kind: IngressRoute metadata: name: my-k8s-route namespace: kube-system spec: entryPoints: - web routes: - match: Host(my.k8s.traefik) PathPrefix(/dashboard) kind: Rule middlewares: - name: strip-dashboard services: - name: kubernetes-dashboard port: 80 - match: Host(my.k8s.traefik) PathPrefix(/kibana) kind: Rule middlewares: - name: strip-kibana services: - name: kibana-logging port: 5601strip-kibana的 Middleware 和上面结构一样把 prefixes 换成/kibana即可。注意match里用的是反引号不是单引号这是 Traefik 的规则语法写错会报invalid rule。接下来是 TaoToken 统一 API 通道的配置。TaoToken 提供 OpenAI 兼容的接口Base URL 是https://taotoken.net/api模型对话、Coding Plan、API Keys 都在控制台管理。你可以在本地工具里这样配{ base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥, model: claude-sonnet-4-5 }如果你用的是 Claude Code 这类工具配置通常放在~/.claude/settings.json或项目级 settings 里把 Base URL 指向 TaoTokenKey 填控制台生成的即可。Codex 用户则改~/.codex/auth.json结构类似{ base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥 }三件套记牢Base URL、Key、Model ID缺一个都调不通。Model ID 以控制台模型列表为准别照抄网上的旧名字。如果你在集群里跑 Agent可以把这些值放进 Secret再挂进 Pod 环境变量避免硬编码。4. 验证请求curl 测路由与鉴权是否真的通了配置写完不验证等于没写。先确认 IngressRoute 被 Traefik 识别kubectl get ingressroute --all-namespaces kubectl get middleware --all-namespaces然后从集群外 curl验证 Host 路由。假设你的节点 IP 是 10.222.76.93Traefik 的 web 入口 NodePort 是 30016curl -H Host: dashboard.k8s.traefik http://10.222.76.93:30016/ -I返回HTTP/1.1 200 OK或 302 跳转说明 Host 路由生效。再测 Path 路由和 stripPrefixcurl -H Host: my.k8s.traefik http://10.222.76.93:30016/dashboard/ -I如果后端 dashboard 返回 200说明/dashboard前缀被正确剥离。如果返回 404八成是 Middleware 没挂上或者stripPrefix的 prefixes 写错了。再验证 TaoToken 通道。用 curl 直接打模型对话接口curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的TaoToken密钥 \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-5, messages: [{role: user, content: ping}] }返回里带choices数组和内容就说明 Key 和 Base URL 都对。如果返回 401是 Key 无效或没带Bearer前缀返回 404多半是路径写成了/v1/chat/completions之外的形式检查 Base URL 是不是https://taotoken.net/api别多加或少加/v1。最后看 Traefik DashboardProviders 下应该能看到你新建的 IngressRoute 和 MiddlewareServices 里能看到后端服务列表。点进去还能看到负载均衡策略默认是 wrr加权轮询。如果你把某个服务扩到两个 PodDashboard 里会实时多出一个 endpoint不用刷新这就是 Traefik 热重载的直观体现。5. 本篇常见错排查401、local proxy failed 与 reading choices排错这块我按真实报错来对都是我自己或群里同学遇到过的。第一个401 Unauthorized。分两种场景。如果是 curl Traefik 路由返回 401说明后端服务自己有鉴权比如 dashboard 需要 token这跟 Traefik 无关去后端解决。如果是 curl TaoToken 返回 401检查三件事Key 是否复制完整别带空格、请求头是否是Authorization: Bearer sk-xxx、Key 是否在控制台被禁用或额度耗尽。第二个local proxy failed。这个报错通常出现在本地工具通过代理访问 API 时代理进程没起来或端口不对。排查顺序先确认本地代理进程在跑再确认工具的 Base URL 指向的是https://taotoken.net/api而不是某个本地端口。如果你在 K8s 里跑 Agent检查 Pod 的 env 里 Base URL 有没有被旧值覆盖kubectl exec进去env | grep -i base看一眼最直接。第三个reading choices相关报错比如cannot read property choices of undefined。这几乎都是响应体不是预期的 JSON 结构导致的。常见原因Base URL 配错请求打到了某个返回 HTML 的地址或者 Model ID 写错服务端返回了错误对象而不是正常响应。解决办法是先 curl 一次看原始返回别只看工具封装后的报错。原始返回里如果有error字段按里面的 message 定位。第四个IngressRoute 创建成功但访问 404。检查entryPoints是不是web80还是websecure443你 curl 的端口要和 entryPoint 对上。再检查match规则里的 Host 和你 curl 的-H Host: ...是否完全一致大小写、点号都不能差。第五个Middleware 不生效。kubectl get middleware -n kube-system确认存在然后看 IngressRoute 的middlewares字段引用的 name 和 namespace 是否对得上。跨 namespace 引用要写全同 namespace 直接写 name。改完 Middleware 不用重启 Traefik几秒内自动生效。6. 把 AI 调用统一到 TaoToken 通道的长期用法路由跑通之后真正省事的是把 AI 工具的调用入口统一。以前每个工具一套 Key、一个 Base URL换模型要改一堆地方。现在全部指向 TaoTokenKey 在控制台统一管理模型切换只改 Model ID。如果你要长期跑编码类 Agent建议用 Coding Plan额度更划算适合高频调用。日常验证模型效果用模型对话页面直接试不用写代码。需要生成和管理 Key去 API Keys 页面。接入细节和参数说明看接入文档最准。这几个入口分别是模型对话https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel_chatCoding Planhttps://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding_plan控制台https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentconsoleAPI Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi_keys接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc在 K8s 里我习惯把 TaoToken 的 Key 放进 SecretAgent 的 Deployment 通过envFrom引用这样换 Key 只改 Secret不用动镜像。配合 Traefik 的 IngressRoute外部流量进集群走 Traefik集群内 Agent 出网走 TaoToken两条链路各管各的排查起来边界清晰。最后留一个实用技巧Traefik 的 Dashboard 里能看到每个路由的请求量和响应码分布调 AI 接口时如果偶发 5xx先看 Dashboard 是 Traefik 层的问题还是后端的问题能省不少时间。路由规则改完kubectl apply一下Dashboard 秒级更新不用重启任何 Pod这就是当初换 Traefik 想要的效果。