1. Traefik 2.X 在 k8s 里当 ingress-controller 到底解决了什么问题
Traefik 2.X 是一个云原生反向代理和负载均衡器,在 Kubernetes 集群里通常以 ingress-controller 的身份运行。它能做什么?简单说,就是把集群外部的流量按域名、路径、Header 等规则转发到集群内部的 Service 上,同时支持自动发现 Ingress、IngressRoute、Middleware 等 CRD 资源。适合谁?适合已经在用 k8s、想找一个配置轻量、Dashboard 可视化、支持动态路由的入口网关的开发和运维同学。
我这次聚焦的场景很具体:Traefik 2.X 作为 k8s ingress-controller 时,Dashboard 怎么安全暴露、EntryPoint 怎么和路由规则配合、以及如何把入口统一到 TaoToken 的调用链路上做端到端验证。很多人第一次装 Traefik 2.X 会卡在两个地方:一是 Dashboard 默认只监听 8080 且没有认证,直接暴露到 NodePort 上等于把管理面板送人;二是 EntryPoint 的 web/websecure 和 IngressRoute 的 entryPoints 字段对不上,导致 curl 一直 404。
Traefik 2.X 和 1.X 最大的区别是引入了 CRD(Custom Resource Definition),路由不再只靠 Ingress 注解,而是用 IngressRoute、Middleware、TLSOption 这些自定义资源来描述。这意味着你可以把「路由」和「中间件」解耦,比如给 Dashboard 单独加一个 BasicAuth 中间件,而不影响业务路由。这个设计在实操里非常香,因为 Dashboard 暴露和业务入口往往是两套安全策略。
下面我会从零开始,给出可复制的 RBAC、Deployment、Service、IngressRoute、Middleware YAML 片段,然后演示用 curl 验证路由命中、401 响应,最后把整条链路和 TaoToken 的统一入口配置对齐。你可以在本地 kind、minikube 或者任意测试集群里跟着做。
2. 前置准备:TaoToken 统一入口与集群环境对齐
在动手写 YAML 之前,先把「统一入口」这件事想清楚。Traefik 的 EntryPoint 是它监听流量的端口,比如 web 对应 80,websecure 对应 443,traefik 对应 8080(Dashboard)。而 TaoToken 在这里扮演的是统一 API 入口的角色——你的模型调用、coding-plan、console 管理都走同一个 Base URL,这样在 Traefik 里做路由和鉴权时,只需要维护一套上游地址。
TaoToken 的官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。注意 API 地址不带 UTM 参数,配置里要写干净。如果你后面要在 Traefik 后面接模型对话或者 coding-plan,建议先把这几个 deep link 记下来:模型对话、coding-plan、console、api-keys、doc、ClaudeCodeAnthropic。这些页面在配置鉴权和验证请求时会反复用到。
集群侧的准备:一个可用的 k8s 集群(1.20+),kubectl 能正常连上,最好有 2 个以上节点或者单节点但资源够。Traefik 2.X 我用的是 2.5.5 之后的版本,CRD 已经稳定。先确认你的集群里没有别的 ingress-controller 抢 80/443,否则 EntryPoint 会绑定失败。
kubectl get nodes kubectl get svc -A | grep -E "LoadBalancer|NodePort"如果看到已经有 nginx-ingress 在跑,要么先停掉,要么给 Traefik 换端口。我实测下来,本地测试集群用 NodePort 暴露 30974 给 Dashboard 是最省事的,生产环境则应该走 websecure + BasicAuth。
还有一个容易忽略的点:Traefik 2.X 的 CRD 需要先安装,否则你 apply IngressRoute 会报no matches for kind "IngressRoute"。CRD 文件在官方仓库的docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml,或者直接用 helm chart 装。我下面给的是手动 apply 的方式,方便你理解每一步。
3. 可复制配置:RBAC、Deployment、Service 与 IngressRoute YAML
这一章是核心,所有片段都可以直接复制。先装 CRD,再装 RBAC,然后是 Deployment 和 Service,最后是 Dashboard 的 IngressRoute 和 BasicAuth Middleware。
先创建 CRD:
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.9/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.ymlRBAC 部分,注意新版文件比较长,别复制少了:
apiVersion: v1 kind: ServiceAccount metadata: name: traefik-ingress-controller namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: traefik-ingress-controller rules: - apiGroups: [""] resources: ["services", "endpoints", "secrets"] verbs: ["get", "list", "watch"] - apiGroups: ["extensions", "networking.k8s.io"] resources: ["ingresses", "ingressclasses"] verbs: ["get", "list", "watch"] - apiGroups: ["traefik.containo.us"] resources: ["ingressroutes", "middlewares", "tlsoptions"] verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: traefik-ingress-controller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: traefik-ingress-controller subjects: - kind: ServiceAccount name: traefik-ingress-controller namespace: kube-systemDeployment 里关键是 EntryPoint 的启动参数,web 监听 80,websecure 监听 443,traefik 监听 8080 给 Dashboard:
apiVersion: apps/v1 kind: Deployment metadata: name: traefik namespace: kube-system spec: replicas: 1 selector: matchLabels: app: traefik template: metadata: labels: app: traefik spec: serviceAccountName: traefik-ingress-controller containers: - name: traefik image: traefik:v2.9 args: - --api.insecure=true - --api.dashboard=true - --providers.kubernetescrd=true - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --entrypoints.traefik.address=:8080 ports: - name: web containerPort: 80 - name: websecure containerPort: 443 - name: traefik containerPort: 8080Service 用 NodePort 暴露,Dashboard 走 30974:
apiVersion: v1 kind: Service metadata: name: traefik namespace: kube-system spec: type: NodePort selector: app: traefik ports: - name: web port: 80 targetPort: 80 nodePort: 30080 - name: websecure port: 443 targetPort: 443 nodePort: 30443 - name: traefik port: 8080 targetPort: 8080 nodePort: 30974Dashboard 的 IngressRoute 和 BasicAuth Middleware,这里就是「把 Dashboard 配置改到统一入口」的关键。Middleware 用 htpasswd 生成的密文,你可以用htpasswd -nb admin yourpassword生成:
apiVersion: traefik.containo.us/v1alpha1 kind: Middleware metadata: name: dashboard-auth namespace: kube-system spec: basicAuth: secret: dashboard-auth-secret --- apiVersion: v1 kind: Secret metadata: name: dashboard-auth-secret namespace: kube-system type: Opaque stringData: users: | admin:$apr1$xyz$abcdefghijklmnopqrstuv --- apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: traefik-dashboard namespace: kube-system spec: entryPoints: - traefik routes: - match: Host(`traefik.local`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`)) kind: Rule services: - name: api@internal kind: TraefikService middlewares: - name: dashboard-auth注意entryPoints写的是traefik,对应 Deployment 里的--entrypoints.traefik.address=:8080。如果你写成web,curl 会 404,这是最常见的坑。另外api@internal是 Traefik 内置服务,不需要你手动创建 Service。
4. 验证请求:curl 命中路由与 401 响应实测
配置 apply 完之后,先确认 Pod 和 CRD 都就绪:
kubectl get pods -n kube-system | grep traefik kubectl get ingressroute -n kube-system kubectl get middleware -n kube-system等 Pod 变成 Running,然后拿节点 IP:
kubectl get nodes -o wide假设节点 IP 是 192.168.1.30,Dashboard 的 NodePort 是 30974。先测不带认证的请求,应该返回 401:
curl -i http://192.168.1.30:30974/dashboard/预期输出里会有:
HTTP/1.1 401 Unauthorized Www-Authenticate: Basic realm="traefik"这说明 BasicAuth Middleware 生效了,路由也命中了。如果返回 404,说明 IngressRoute 的 match 规则或者 entryPoints 写错了。如果返回 502,说明api@internal服务没找到,检查 CRD 是否装全。
再测带认证的请求:
curl -i -u admin:yourpassword http://192.168.1.30:30974/dashboard/这次应该返回 200,并且能看到 Dashboard 的 HTML。如果你在浏览器里访问,会弹出登录框,输入账号密码后进入 Traefik Dashboard,能看到 Routers、Services、Middlewares 的实时状态。
再验证一下 web EntryPoint 上的业务路由。假设你有一个 tomcat 服务,创建一个 IngressRoute:
apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: tomcat-route namespace: default spec: entryPoints: - web routes: - match: Host(`my.tomcat.com`) kind: Rule services: - name: tomcat-svc port: 8080然后在物理机 hosts 里加一条192.168.1.30 my.tomcat.com,用 curl 验证:
curl -i -H "Host: my.tomcat.com" http://192.168.1.30:30080/如果返回 tomcat 的欢迎页,说明 web EntryPoint 的路由也通了。这一步和 Dashboard 的区别在于 entryPoints 从traefik换成了web,端口从 30974 换成了 30080。
如果你要把这条链路和 TaoToken 的模型调用对齐,可以在业务服务里把上游 Base URL 配成 https://taotoken.net/api ,然后用同样的 curl 方式验证模型对话接口是否可达。TaoToken 的 API Key 在 console 的 api-keys 页面生成,配置时注意 Base URL、Key、Model ID 三件套要写全。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
实操里最容易撞的几个报错,我按真实日志对照给你排。
第一个是 401 Unauthorized。如果你 curl Dashboard 不带-u返回 401,这是正常的,说明 Middleware 生效。但如果你带了正确的账号密码还是 401,检查 Secret 里的users字段格式,必须是用户名:密文,密文用htpasswd -nb生成,不能用明文。另外 Secret 的 namespace 要和 Middleware 一致,否则 Traefik 读不到。
第二个是local proxy failed或者dial tcp: connection refused。这通常出现在你把上游配成 localhost 或者 127.0.0.1 的时候。Traefik 在 Pod 里跑,localhost 指向的是 Pod 自己,不是你的物理机。正确做法是写 Service 名或者集群内 DNS,比如tomcat-svc.default.svc.cluster.local。如果你在配置 TaoToken 的 Base URL,也要确认写的是 https://taotoken.net/api 而不是本地地址。
第三个是reading choices相关的报错,一般出现在模型调用返回体解析失败时。如果你在 Traefik 后面接了一个模型代理服务,返回的 JSON 结构不对,客户端解析choices字段就会报错。排查方法是先用 curl 直接打上游,确认返回体是标准格式,再经过 Traefik 转发。Traefik 本身不会改返回体,所以问题多半在服务端。
第四个是 OAuth 相关报错,比如OAuth token exchange failed。如果你在 Middleware 里配了 forwardAuth 或者 OIDC,检查 issuer URL 和 client secret 是否正确。Traefik 2.X 的 forwardAuth 会把请求头转发给认证服务,认证服务返回 2xx 才放行。如果认证服务本身挂了,就会一直 401。建议先用 curl 单独测认证服务的健康检查接口。
还有一个隐蔽的坑:IngressRoute 的entryPoints名字必须和 Deployment 里的--entrypoints.xxx.address完全一致。我见过有人写websecure但 Deployment 里只配了web,结果路由一直不生效。用kubectl logs -n kube-system deploy/traefik看日志,会提示entrypoint not found。
最后,如果你同时用了 CC Switch、Cline MCP 或者 Codex 的 auth.json,记得三件套要写全:Base URL 用 https://taotoken.net/api ,Key 用 console 生成的,Model ID 按文档填。缺任何一个都会导致鉴权失败或者模型找不到。
6. 把入口统一到 TaoToken:长期编码与 Agent 场景的接入建议
Dashboard 和 EntryPoint 配通之后,下一步就是把业务入口统一到 TaoToken 的调用链路上。如果你只是临时验证模型对话,直接用模型对话页面测就行。但如果你要做长期编码或者 Agent 场景,建议走 Coding Plan,这样配额和路由策略更稳定。
具体做法:在 Traefik 的 IngressRoute 里,把上游 Service 指向你的模型代理服务,代理服务里配置 TaoToken 的 Base URL 和 Key。这样外部流量先到 Traefik,Traefik 做路由和鉴权,再转发到代理服务,代理服务调用 TaoToken API。整条链路的入口是统一的,鉴权也集中在 Traefik 的 Middleware 里。
如果你用的是 Claude Code 做润色或者代码生成,接入方式类似:在配置里填 Base URL https://taotoken.net/api ,Key 从 api-keys 页面拿,Model ID 按文档选。Traefik 这边只需要保证 websecure EntryPoint 的证书和路由规则正确,剩下的交给上游。
排障的时候,优先看 Traefik 的 Dashboard,Routers 页面会显示每条路由的命中状态和错误信息。如果某个 Router 显示红色,点进去看详细报错,通常是 match 规则写错或者 Service 不存在。接入文档里有完整的参数说明,遇到不确定的字段先去 doc 页面查。
最后提醒一句:Dashboard 的--api.insecure=true只适合本地测试,生产环境一定要关掉,改用 websecure + BasicAuth 或者 forwardAuth。我踩过的坑就是测试环境图省事开了 insecure,结果 Dashboard 被扫到,虽然没造成损失,但也是个教训。把 Dashboard 和 EntryPoint 都收敛到统一入口之后,整个 k8s 集群的流量治理会清晰很多。