1. 从一次 502 说起Kubernetes 南北向入口到底该选谁线上微服务刚拆完前端同学在群里甩来一张截图api.example.com/users返回 502但kubectl get pods里 user-service 明明是 Running。这种场景我遇到过不止一次问题往往不在业务代码而在集群的南北向入口——也就是外部流量进入 Kubernetes 的那道门。Kubernetes 网关要解决的核心问题就一句话把集群外的 HTTP/TCP 请求按域名和路径准确送到某个 Service 背后的 Pod同时把 TLS、限流、鉴权这些横切逻辑收拢到入口层。如果你正在给微服务配置统一入口会同时听到三个名字Ingress、Gateway API、Istio Gateway。它们不是互相替代的简单关系而是三代演进 不同职责层。Ingress 是 Kubernetes 第一代入口标准靠networking.k8s.io/v1的 Ingress 资源 注解驱动Nginx Ingress Controller 是事实上的默认实现Gateway API 是官方下一代标准用 GatewayClass / Gateway / HTTPRoute 三层 CRD 把「谁提供网关能力」「网关实例长什么样」「路由规则怎么走」拆开天然支持多租户和跨命名空间Istio Gateway 则是服务网格视角的入口和 VirtualService 配合做金丝雀、故障注入、mTLS。这篇不堆概念直接给你可复制的 Ingress 与 Gateway API 资源清单、kubectl 验证命令以及多集群访问凭据怎么用 TaoToken 统一管理。读完你能完成一次从外部请求到后端 Pod 的端到端连通验证并知道报错时先看哪一层。2. 前置准备集群、Controller 与 TaoToken 统一 Key 通道动手前先把地基铺好。你需要一个能跑 workload 的 Kubernetes 集群minikube、kind、k3s 都行生产用托管集群kubectl已配置好 context。下面所有命令默认你在能访问集群的机器上执行。第一步确认集群版本和节点状态kubectl version --short kubectl get nodes -o wide第二步部署一个用于验证的后端服务。这里用最经典的 echo 服务它会把你请求的路径、Header 原样返回方便确认路由是否命中kubectl create deployment echo --imagehashicorp/http-echo -- /http-echo -texthello from echo kubectl expose deployment echo --port5678 --target-port5678 kubectl get svc echo第三步安装 Ingress Controller。以 Nginx Ingress 为例用官方 manifest 最快kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml kubectl get pods -n ingress-nginx等ingress-nginx-controller变成 Running再拿到它的入口地址kubectl get svc -n ingress-nginx ingress-nginx-controller云环境这里通常是 LoadBalancer 类型会分配一个外部 IP本地 kind/minikube 可能是 NodePort 或 pending用kubectl port-forward临时打通即可。第四步也是多集群场景容易被忽略的一步访问凭据管理。当你同时维护 dev / staging / prod 三套集群每个集群的 kubeconfig、每个后端服务的 API Key、每个模型或工具链的 Token 散落在不同机器上轮换一次就是灾难。我的做法是用 TaoToken 把 Key/API 通道统一收口一个 Key 管多集群访问凭据避免把明文 Token 写进 CI 变量或本地.env。到官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后进控制台 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建 API Key再打开接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 对照你用的客户端配置。API 基址统一是 https://taotoken.net/api不加 UTM。这一步不涉及任何网络层特殊配置就是标准的 Key 申请与 Base URL 填写。如果你只是想让网关路由跑通TaoToken 不是必需项但一旦涉及多集群、多环境、多工具的凭据分发提前把通道统一后面排障会省很多事。3. 可复制配置Ingress 与 Gateway API 资源清单这一节给你两份能直接kubectl apply的清单先跑 Ingress再跑 Gateway API对照着看职责差异。3.1 Ingress 资源清单与注解Ingress 的核心是spec.rules里的 host path配合backend.service指向 Service。TLS 用spec.tls声明。下面这份清单把/users和/orders分别路由到两个服务并开启 rewriteapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: api-gateway annotations: nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/ssl-redirect: true spec: ingressClassName: nginx tls: - hosts: - api.example.com secretName: api-tls-secret rules: - host: api.example.com http: paths: - path: /users pathType: Prefix backend: service: name: user-service port: number: 80 - path: /orders pathType: Prefix backend: service: name: order-service port: number: 80注意ingressClassName: nginx这行Kubernetes 1.18 之后必须显式指定否则 Ingress 会被 Controller 忽略表现为「资源创建成功但访问 404」。pathType推荐用PrefixExact只匹配完全相等路径容易踩坑。应用并查看kubectl apply -f ingress.yaml kubectl get ingress api-gateway kubectl describe ingress api-gatewaydescribe里会显示 Rules 和实际绑定的 Controller 地址这是排查路由是否被接管的第一现场。3.2 Gateway API 三层资源Gateway API 把职责拆成三层GatewayClass 定义「用哪个 Controller 实现」Gateway 定义「监听什么端口、什么协议、TLS 怎么终止」HTTPRoute 定义「域名和路径怎么匹配、转发到哪个后端」。下面这份清单用 Istio 作为实现apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: istio spec: controllerName: istio.io/gateway-controller --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: public-api-gateway spec: gatewayClassName: istio listeners: - name: https port: 443 protocol: HTTPS tls: mode: Terminate certificateRefs: - name: wildcard-cert allowedRoutes: namespaces: from: Selector selector: matchLabels: expose: public --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: user-api-route labels: expose: public spec: parentRefs: - name: public-api-gateway hostnames: - api.example.com rules: - matches: - path: type: PathPrefix value: /v1/users filters: - type: RequestHeaderModifier requestHeaderModifier: set: - name: X-API-Version value: v1 backendRefs: - name: user-service-v1 port: 8080 weight: 90 - name: user-service-v2 port: 8080 weight: 10这份清单里有两个 Ingress 做不到的点一是allowedRoutes.namespaces.from: Selector实现了跨命名空间路由授权二是backendRefs直接支持weight做流量切分不需要额外注解。应用后验证kubectl apply -f gateway-api.yaml kubectl get gatewayclass kubectl get gateway -A kubectl get httproute -A如果kubectl get gatewayclass返回空说明集群没装 Gateway API CRD需要先安装对应版本的 CRD bundle再装 Istio 或其它实现。3.3 多集群凭据的 settings 片段多集群访问凭据统一管理可以在本地工具配置里集中声明。以常见的 settings 结构为例把 Base URL 和 Key 抽出来{ api_base_url: https://taotoken.net/api, api_key: ${TAOTOKEN_API_KEY}, clusters: { dev: { context: dev-cluster, namespace: default }, staging: { context: staging-cluster, namespace: default }, prod: { context: prod-cluster, namespace: default } } }Key 用环境变量注入不要硬编码。这样切换集群只改 context凭据通道不变。需要生成或轮换 Key 时去 API Keys 页面 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 操作。4. 验证请求从 curl 到后端 Pod 的端到端连通配置写完不算完必须验证请求真的到了后端。分三步走。第一步确认 Ingress/Gateway 拿到了地址。Ingress 场景kubectl get ingress api-gateway -o jsonpath{.status.loadBalancer.ingress[0].ip}如果输出为空说明 Controller 还没回填状态检查 Controller Pod 日志kubectl logs -n ingress-nginx -l app.kubernetes.io/componentcontroller --tail100第二步用 curl 带 Host 头请求。本地没有 DNS 时用--resolve把域名指到入口 IPcurl -v --resolve api.example.com:80:INGRESS_IP http://api.example.com/users预期返回 echo 服务的响应体里面能看到请求路径。如果返回 404先看 Ingress 的 path 是否匹配返回 502看后端 Service 的 Endpoints 是否为空kubectl get endpoints user-serviceEndpoints 为空通常意味着 Service 的 selector 和 Pod label 对不上或者 Pod 没 Ready。第三步Gateway API 场景验证。先拿到 Gateway 的地址kubectl get gateway public-api-gateway -o jsonpath{.status.addresses[0].value}再请求 HTTPRoute 匹配的路径curl -v --resolve api.example.com:443:GATEWAY_IP https://api.example.com/v1/users -k-k是因为自签证书生产环境换成正式证书后去掉。观察响应头里有没有X-API-Version: v1有就说明 filter 生效了。第四步确认流量真的到了 Pod。开一个新终端持续看 echo 日志kubectl logs -f deployment/echo再发一次请求日志里出现对应记录端到端链路就通了。这一步是很多人跳过的但它是区分「网关配置对了」和「请求真到了业务」的唯一标准。5. 常见报错排查401、local proxy failed 与 reading choices排障的核心思路是分层定位先确认请求有没有到 Controller再看 Controller 有没有转发到 Service最后看 Service 有没有到 Pod。下面几个报错是我踩过的坑。401 Unauthorized。如果网关层配了 JWT 或 API Key 校验请求头缺失或过期都会 401。先确认请求头curl -v -H Authorization: Bearer TOKEN https://api.example.com/v1/users如果 Token 是从 TaoToken 统一通道取的检查环境变量是否注入成功echo $TAOTOKEN_API_KEY。401 也可能是 Key 权限范围不对去控制台确认这个 Key 是否绑定了对应集群或服务。local proxy failed。这个报错常见于本地 port-forward 或客户端代理配置场景意思是本地转发通道没建立起来。先确认 port-forward 进程还在kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller 8080:80如果进程已退出重新起一个。如果客户端配置里写了代理地址但代理没监听也会报这个。检查配置里的 Base URL 是否写成了https://taotoken.net/api路径不要多加斜杠。reading choices 相关报错。这类报错通常出现在调用模型接口时响应体解析失败根因是返回的不是预期 JSON而是 HTML 错误页或空响应。先用 curl 看原始返回curl -i 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}]}如果返回 404检查路径返回 401检查 Key返回 200 但 body 为空检查请求体 JSON 是否合法。网关层如果做了请求体改写也可能把 JSON 改坏这时对比直连和过网关的请求体差异。OAuth 回调失败。如果网关后面挂了 OAuth2 Proxy回调地址必须和注册时一致。检查redirect_uri是否带了多余端口或路径以及 Gateway 的 listener 是否允许该 host。Ingress 创建成功但 404。九成是ingressClassName没写或写错。用kubectl get ingressclass看集群里有哪些 class再对照 Ingress 里的值。Gateway 一直 ProgrammedFalse。看kubectl describe gateway的 Conditions通常是 certificateRefs 指向的 Secret 不存在或者 allowedRoutes 的 namespace selector 没匹配到 HTTPRoute 所在命名空间。排查时记住一个顺序kubectl get看资源状态 →kubectl describe看事件 →kubectl logs看 Controller 日志 →curl -v看请求响应。四步走完大部分问题都能定位。6. 把入口层收口多集群访问与后续接入跑通单集群只是起点。真实环境里你会有多套集群、多个环境、多种客户端入口层的配置和凭据管理如果不收口维护成本会指数上升。我的建议是路由规则用 GitOps 管Ingress/Gateway 清单进 Git 仓库用 ArgoCD 或 Flux 同步凭据用统一通道管所有集群和工具的 Key 从 TaoToken 取本地只留环境变量引用。需要长期跑编码 Agent 或多集群自动化任务的可以看 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite把模型调用和集群访问的凭据统一到一条通道上。只是想先验证模型连通性的用模型对话 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 发一条请求确认 Base URL 和 Key 都对再往网关配置里接。最后留一个实用技巧给每个 Ingress/Gateway 资源打上owner和env标签排障时kubectl get ingress -l envprod一秒筛出生产入口比翻命名空间快得多。入口层是流量的咽喉配置越清晰出事时越不慌。