1. 从 Ingress 到 Gateway API:为什么你的集群需要换一套入口模型
如果你已经在 Kubernetes 里用 Ingress 暴露过服务,大概率写过类似nginx.ingress.kubernetes.io/rewrite-target这样的 annotation。它能用,但用久了会发现一个问题:这些能力是绑定在具体 Ingress Controller 上的,换一个网关实现,YAML 就得重写一遍。Kubernetes Gateway API 就是官方为了解决这类问题推出的下一代入口与路由 API 规范,它把「网关类型」「入口监听」「路由规则」拆成 GatewayClass、Gateway、HTTPRoute 三层资源,让平台团队和业务团队各管各的。这篇内容面向已经会写 Ingress、想动手跑通第一条 HTTPRoute 的读者,我会给出可直接复制的 YAML 骨架、kubectl 验证动作,以及用 TaoToken 统一 Key 为集群内 AI 工具提供配置参考的实操路径。整套流程不需要你提前理解全部 CRD,跟着敲一遍就能看到请求真正落到 Pod 上。
Ingress 的模型是「一个资源装下所有东西」:域名、路径、TLS、后端 Service、控制器私有配置全塞在一起。基础场景够用,但一旦涉及多命名空间、Header 匹配、流量权重、跨团队权限隔离,表达能力就开始吃紧。Gateway API 的思路是把职责拆开——GatewayClass 回答「用哪种网关实现」,Gateway 回答「入口开在哪个端口、收哪些 Host」,HTTPRoute 回答「请求怎么匹配、转发到哪个 Service」。三者通过引用关系串起来,权限边界自然清晰:平台团队管 GatewayClass 和 Gateway,业务团队只管自己命名空间里的 HTTPRoute。
2. 前置准备:装好 Gateway API CRD 与 TaoToken 统一 Key
动手之前需要确认两件事:集群里已经安装了 Gateway API 的 CRD,以及有一个支持 Gateway API 的控制器在跑。CRD 是标准资源定义,控制器才是真正下发配置、转发流量的组件。常见的实现有 Envoy Gateway、Cilium、Istio、Traefik、Kong、NGINX Gateway Fabric 等,选一个你熟悉的即可。下面以 Envoy Gateway 为例,其他实现的 GatewayClass 名称不同,但 Gateway 和 HTTPRoute 的写法基本一致。
安装 CRD 可以用官方发布的标准版本:
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml装完后确认 CRD 已经就位:
kubectl get crd | grep gateway.networking.k8s.io正常会看到gatewayclasses、gateways、httproutes等资源。接着安装控制器,以 Envoy Gateway 为例:
helm install eg oci://docker.io/envoyproxy/gateway-helm \ --version v1.1.0 \ -n envoy-gateway-system \ --create-namespace等 Pod 起来后,集群里会自动出现一个名为eg的 GatewayClass:
kubectl get gatewayclass看到eg的ACCEPTED为True,说明控制器已经接管了这类网关。
接下来是 TaoToken 的部分。集群里如果跑着 AI 工具(比如代码补全、对话机器人、Agent 服务),它们通常需要调用模型接口。与其在每个 Pod 里散落不同的 Key,不如用 TaoToken 统一 Key 和 API 通道,把配置集中管理。先到控制台创建一个 API Key:
# 控制台地址(创建 Key 后复制保存) https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite创建完成后,把 Key 写进一个 Kubernetes Secret,供集群内工具引用:
kubectl create secret generic taotoken-secret \ --from-literal=api-key='sk-你的TaoTokenKey' \ -n app-demo这样后续无论是 HTTPRoute 后面的 AI 服务,还是集群里的其他工具,都能通过同一个 Secret 拿到统一 Key,避免 Key 到处复制。API 通道的基础地址是https://taotoken.net/api,接入文档在:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite3. 可复制配置:GatewayClass、Gateway、HTTPRoute 三层 YAML 骨架
先建一个命名空间,把示例应用和路由都放进去:
kubectl create namespace app-demo准备一个后端应用,这里用一个简单的 echo 服务模拟:
apiVersion: apps/v1 kind: Deployment metadata: name: app-service namespace: app-demo spec: replicas: 2 selector: matchLabels: app: app-service template: metadata: labels: app: app-service spec: containers: - name: app image: hashicorp/http-echo:0.2.3 args: - "-text=hello from gateway api" ports: - containerPort: 5678 --- apiVersion: v1 kind: Service metadata: name: app-service namespace: app-demo spec: selector: app: app-service ports: - port: 8080 targetPort: 5678注意 Service 的port是 8080,targetPort是容器实际监听的 5678,后面 HTTPRoute 的backendRefs.port要写 8080。
GatewayClass 通常由控制器安装时自动创建,一般不需要手写。如果你用的实现没有自动创建,可以手动声明一个:
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: eg spec: controllerName: gateway.envoyproxy.io/gatewayclass-controllercontrollerName是关键字段,它告诉 Kubernetes 这个 GatewayClass 由哪个控制器管理。写错这个值,Gateway 会一直处于Accepted=False。
接着写 Gateway,它代表一个具体的入口实例:
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: app-gateway namespace: app-demo spec: gatewayClassName: eg listeners: - name: http port: 80 protocol: HTTP hostname: "app.example.com" allowedRoutes: namespaces: from: Same逐字段看:gatewayClassName: eg表示这个 Gateway 交给eg这个 GatewayClass 对应的控制器处理;listeners定义了一个名为http的监听入口,监听 80 端口、处理 HTTP 流量、只接收 Host 为app.example.com的请求;allowedRoutes.namespaces.from: Same表示只允许和 Gateway 同命名空间的 HTTPRoute 绑定到这个 listener。
最后是 HTTPRoute,它定义请求怎么匹配、怎么转发:
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: app-route namespace: app-demo spec: parentRefs: - name: app-gateway sectionName: http hostnames: - "app.example.com" rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: app-service port: 8080parentRefs表示这条 HTTPRoute 绑定到app-gateway的httplistener;hostnames是路由级别的匹配条件;rules.matches.path用PathPrefix匹配所有以/开头的路径;backendRefs指向app-service:8080。
把三个资源依次应用:
kubectl apply -f app-deployment.yaml kubectl apply -f gateway.yaml kubectl apply -f httproute.yaml4. 验证请求:kubectl 检查状态与 curl 打通链路
资源创建后,先看 Gateway 是否被控制器接受:
kubectl get gateway app-gateway -n app-demo -o wide关注PROGRAMMED列,为True说明控制器已经为它分配了地址并下发配置。如果为False,用kubectl describe gateway app-gateway -n app-demo看 Events。
再看 HTTPRoute 的绑定状态:
kubectl get httproute app-route -n app-demo -o widePARENTS列会显示它绑定了哪个 Gateway,STATUS为Accepted表示路由规则已被接受。
获取 Gateway 的实际访问地址:
kubectl get gateway app-gateway -n app-demo \ -o jsonpath='{.status.addresses[0].value}'拿到地址后,用 curl 带上 Host 头验证:
curl -H "Host: app.example.com" http://<Gateway地址>/正常会返回hello from gateway api。这一步打通,说明从 Gateway 入口到 HTTPRoute 匹配再到 Service 转发到 Pod 的整条链路都通了。
如果你在集群内跑 AI 工具,想验证 TaoToken 的 API 通道是否可用,可以在同一个命名空间起一个临时 Pod:
kubectl run curl-test --rm -it --image=curlimages/curl -n app-demo -- sh进入容器后,用 Secret 里的 Key 请求模型对话接口:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"ping"}]}'返回正常 JSON 就说明统一 Key 和 API 通道都通了。模型对话的入口在:
https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite5. 本篇常见错排查:Gateway 不 Ready、HTTPRoute 不绑定、404 怎么查
Gateway 一直PROGRAMMED=False:最常见的原因是gatewayClassName写错,或者对应的 GatewayClass 没有被控制器接受。先kubectl get gatewayclass确认ACCEPTED为True,再检查 Gateway 的spec.gatewayClassName是否和它一致。如果控制器 Pod 没起来,Gateway 也不会被处理。
HTTPRoute 的PARENTS为空:说明它没绑定上任何 Gateway。检查parentRefs.name是否和 Gateway 名字一致,sectionName是否对应 Gateway 里真实存在的 listener 名。如果 Gateway 和 HTTPRoute 不在同一命名空间,parentRefs里要写namespace,同时 Gateway 的allowedRoutes.namespaces.from要允许对应命名空间。
curl 返回 404:请求进了 Gateway 但没匹配上 HTTPRoute。先确认 Host 头是否和hostnames一致,再检查matches.path的type和value。PathPrefix: /能匹配所有路径,但如果写成Exact: /api,访问/就不会命中。另外注意 Gateway listener 的hostname和 HTTPRoute 的hostnames需要有交集,否则入口层就把请求挡掉了。
返回 503:路由匹配上了但后端不可达。检查backendRefs.name和port是否对应真实的 Service 和端口。Service 的port和targetPort别写反,targetPort要指向容器实际监听的端口。
跨命名空间绑定失败:Gateway 的allowedRoutes.namespaces.from默认是Same,只允许同命名空间。要允许其他命名空间,改成All或用Selector指定标签。生产环境建议用Selector,避免任意命名空间都能挂上来。
6. 把统一 Key 接进集群:TaoToken 在 Gateway API 场景下的配置参考
Gateway API 解决的是流量入口和路由,TaoToken 解决的是集群内 AI 工具的 Key 和 API 通道统一。两者结合的场景很自然:你的 AI 服务通过 HTTPRoute 暴露出去,而它调用模型接口时用的是同一个 TaoToken Key。这样 Key 只需要在一个 Secret 里维护,轮换时改一处即可。
如果集群里跑的是长期编码任务或 Agent 服务,建议用 Coding Plan 统一管理调用配额和通道:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite需要新建或轮换 Key 时,到 API Keys 页面操作:
https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite接入细节和参数说明看文档:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite如果你用的是 Claude Code 这类工具,Anthropic 兼容通道的配置参考在:
https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude_code&utm_campaign=rewrite把 Secret 挂进 Pod 的方式很直接,在 Deployment 里加一段环境变量引用:
env: - name: TAOTOKEN_API_KEY valueFrom: secretKeyRef: name: taotoken-secret key: api-key这样容器里的 AI 工具读TAOTOKEN_API_KEY就能拿到统一 Key,不需要在镜像或代码里硬编码。Gateway API 负责把外部请求路由到你的 AI 服务,TaoToken 负责让服务内部调用模型时 Key 和通道统一,两层各司其职。整套跑下来,你手里应该有一条能返回hello from gateway api的 HTTPRoute,以及一个能在集群内验证通过的 TaoToken API 通道。