十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Envoy 15001 收不到流量?让 Codex 走 TaoToken 对着 iptables 规则查

Envoy 15001 收不到流量?让 Codex 走 TaoToken 对着 iptables 规则查 Envoy 15001 一个包都没进Sidecar 和业务容器却都 Running这种 Service Mesh 排障最折磨人你以为数据平面已经接管流量实际 istio-init 写入的 iptables -t nat 规则和 Envoy 的 virtualOutbound listener 根本没对上。我处理这类问题时会先让 Codex 走 TaoToken 的统一通道打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content 创建 API Key再把 Codex 的 Base URL 填成 https://taotoken.net/api。TaoToken 只提供 Key 和统一 Base URL不碰你的 k8s 资源真正的 kubectl、iptables 导出和结果判断仍然由你在自己节点上执行把输出贴回对话逐段对照。1. 15001 零包先别改 YAML按 iptables 链和 listener 对齐1.1 istio-init 没把规则写进 Pod netns后面全白搭Sidecar 注入成功后Pod 里通常会多出两个关键角色istio-init和istio-proxy。istio-init是 Init Container它的任务不是跑 Envoy而是在 Pod 的 network namespace 里调用类似istio-iptables的工具把 outbound 流量重定向到 15001把 inbound 流量重定向到 15006。很多同学只看业务容器和istio-proxy都是 Running就默认数据平面已经接管流量但istio-init可能因为权限、Annotation、命名空间注入开关、镜像版本等原因没有真正写入规则。如果istio-init没有执行或者执行失败后退出nat 表里就不会有完整的ISTIO_OUTPUT、ISTIO_REDIRECT、ISTIO_INBOUND、ISTIO_IN_REDIRECT链。此时应用照常发请求包直接走默认路由出去15001 自然一个包都收不到。排查时先看 Pod 的注解和 init container 列表不要一上来就改VirtualService或DestinationRule那些属于控制面下发配置不负责把应用发出的包塞进 15001。kubectl get pod pod -n ns -o jsonpath{.metadata.annotations.sidecar\.istio\.io/status}{\n} kubectl get pod pod -n ns -o jsonpath{.spec.initContainers[*].name}{\n} kubectl logs pod -n ns -c istio-initistio-init成功时日志可能很少甚至没有明显输出所以不能只凭“日志为空”判断失败。更可靠的是看 Pod 状态、init container 退出码以及后续从 Pod netns 导出的 iptables 规则。1.2 outbound 链的 REDIRECT 目标必须是 15001Istio 默认的流量劫持链路可以粗略理解成两条一条管 outbound一条管 inbound。outbound 通常从 nat 表的OUTPUT链进入ISTIO_OUTPUT再按条件跳到ISTIO_REDIRECT最终REDIRECT到 15001。inbound 则从PREROUTING进入ISTIO_INBOUND再跳到ISTIO_IN_REDIRECT最终REDIRECT到 15006。15001 对应 Envoy 的 virtualOutbound listener15006 对应 virtualInbound listener。15001 收不到流量最常见的是ISTIO_OUTPUT里在前面命中了RETURN。比如默认会排除istio-proxy自己的 UID 1337也会排除 15020、15090 等管理端口还可能排除某些网段和接口。如果业务容器恰好以 1337 运行或者应用的出站端口被写进了排除列表包就不会进入ISTIO_REDIRECTpkts计数器会一直是 0。这个时候你盯 YAML 没用必须看 nat 表里的链顺序和计数器。kubectl exec -it pod -n ns -c istio-proxy -- iptables -t nat -L ISTIO_OUTPUT -n -v kubectl exec -it pod -n ns -c istio-proxy -- iptables -t nat -L ISTIO_REDIRECT -n -v如果容器里没有iptables不要直接去宿主机随便查因为宿主机的 nat 表和 Pod netns 不是一回事。可以用kubectl debug进入同一个 network namespace或者用节点上的nsenter指定 Pod netns但前提是你清楚自己查的是哪个命名空间。1.3 Envoy 在 15001 监听不等于流量会进来istioctl proxy-config listener pod -n ns --port 15001能看到 virtualOutbound只说明 Envoy 准备好了入口。它不证明 iptables 已经把包重定向过来。反过来如果ISTIO_REDIRECT的计数器在涨但连接被拒绝那才更可能是 listener 没就绪、Envoy 启动慢、端口没监听或者 Sidecar 就绪顺序有问题。把“规则没生效”和“规则生效但 Envoy 处理失败”分开排查范围会小很多。可以同时看 15001 和 15006istioctl proxy-config listener pod -n ns --port 15001 istioctl proxy-config listener pod -n ns --port 15006如果 15001 listener 存在、ISTIO_REDIRECT计数为 0就别再怀疑 Envoy 路由先回到ISTIO_OUTPUT看谁把流量提前放走了。这个判断顺序比反复改 YAML 有效得多。2. 让 Codex 走 TaoToken~/.codex/config.toml 和 YOUR_API_KEY2.1 先在 TaoToken 创建 Key别把 Key 写进仓库打开 TaoToken 注册并创建 API KeyKey 用占位符YOUR_API_KEY表示实际值只放在你自己的环境变量或本地配置里不要提交到 Git。模型 ID 不要凭记忆写直接以 TaoToken 模型广场当时的列表为准。TaoToken 在这里提供的是统一 API 通道官网用于注册、创建 Key、看模型广场和用量填进 Codex 的 Base URL 是https://taotoken.net/api末尾不要加/v1。这一步和 Envoy 排障没有直接耦合。Codex 不需要访问你的 k8s 集群也不需要拿 kubeconfig。它只负责在对话里解释 iptables 链、对照 listener 输出、生成下一步排查命令。真正执行kubectl、iptables-save、istioctl的人仍然是你。2.2 Codex 的 config.toml 怎么写Codex 的配置文件在~/.codex/config.toml。不要把 Claude Code 的ANTHROPIC_*环境变量套到 Codex 上那是两套工具。按下面这段改重点是model_provider指向自定义供应商base_url填 TaoToken 的统一入口model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat其中YOUR_MODEL_ID要替换成模型广场里真实存在的 ID不要自己拼日期后缀。env_key写的是环境变量名不是 Key 本身。设置环境变量时用export TAOTOKEN_API_KEYYOUR_API_KEY codexWindows PowerShell 可以这样$env:TAOTOKEN_API_KEYYOUR_API_KEY codex如果之前配过其他 provider注意不要同时留下冲突的model_provider。Codex 启动后如果报 401先查环境变量有没有传到当前终端如果报 404先查base_url是不是误加了/v1以及模型 ID 是否和模型广场一致。2.3 先做一次最小对话验证配置改完先问 Codex 一个和本篇相关但不接触集群的问题例如“解释ISTIO_OUTPUT和ISTIO_REDIRECT在 nat 表里的关系”。能正常回答说明 Codex 已经走通 TaoToken 通道。然后回到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content 控制台看这次调用有没有记上账顺便核对模型 ID 和 Key 是否选对。验证通过后再把 Codex 当成“排障副驾驶”用。提示词里要明确你不能访问我的集群只能根据我贴出的命令输出做对照并告诉我下一步在本机执行什么命令。这样既能利用模型对 iptables、Envoy listener 的归纳能力又不会把生产环境的执行权交出去。3. 用 kubectl 抓三份证据istio-init 日志、iptables-save、15001 listener3.1 确认注入状态和 init container排障最怕只拿一份 YAML 反复看。先把 Pod 的注入状态、init container 名称、Sidecar 容器状态拉出来。确认istio-init是否存在Pod 注解里sidecar.istio.io/status是否正常命名空间是否开启了自动注入。若发现没有istio-init后面的 nat 表基本不用查了先解决注入问题。kubectl get pod pod -n ns -o jsonpath{.metadata.annotations.sidecar\.istio\.io/status}{\n} kubectl get pod pod -n ns -o jsonpath{.spec.initContainers[*].name}{\n} kubectl describe pod pod -n nsdescribe里重点看 Init Containers 的状态、重启次数、退出码。istio-init通常是一次性任务成功后退出不会长期 Running。如果它根本没出现检查 Deployment 模板有没有被注入或者 Pod 是否显式关闭了注入。3.2 导出 nat 表不要只看 -L只看iptables -L很容易漏掉链顺序和计数器。更推荐iptables-save -t nat因为它能完整展示规则顺序、目标端口、匹配条件和跳转链。把输出保存下来后面贴给 Codex 对照。kubectl exec -it pod -n ns -c istio-proxy -- iptables-save -t nat如果istio-proxy容器里没有iptables可以尝试用kubectl debug启动一个带网络工具的临时容器并让它加入目标 Pod 的 network namespace。无论用哪种方式都要确认你查的是目标 Pod 的 netns而不是节点默认命名空间。重点核对四条链ISTIO_OUTPUT、ISTIO_REDIRECT、ISTIO_INBOUND、ISTIO_IN_REDIRECT。15001 的问题优先看前两条。3.3 导出 Envoy 的 15001 和 15006 listenerlistener 这一侧用istioctl最省事istioctl proxy-config listener pod -n ns --port 15001 istioctl proxy-config listener pod -n ns --port 15006也可以从 Envoy 管理端口拿 JSONkubectl exec pod -n ns -c istio-proxy -- curl -s localhost:15000/listeners?formatjson你要找的是 virtualOutbound 和 virtualInbound以及它们监听的地址、端口、filter chain。如果 15001 listener 不存在先解决 Sidecar 启动和配置下发如果 listener 存在但 iptables 计数为 0问题在 nat 规则命中不在 Envoy 路由。把这三份输出整理在一起Codex 才能按“规则 - 跳转 - listener”的顺序帮你定位。4. 把三份输出贴回 Codex按 outbound 15001 / inbound 15006 逐段对照4.1 给 Codex 的提示词要限制它只做对照贴输出之前先给 Codex 一个边界清晰的提示词。不要让它“帮你连集群看看”而是让它做静态对照。可以这样写下面是一个 Istio Pod 的 iptables-save nat 表、istio-init 日志和 Envoy listener 摘要。请按 outbound 15001、inbound 15006 两条链路逐段检查规则是否存在、跳转链是否被 RETURN 提前截断、REDIRECT 端口是否和 listener 一致、UID/端口/接口排除是否误伤业务流量。只输出对照表和需要我在本机执行的下一步命令不要假设你能访问集群。然后把iptables-save -t nat、kubectl logs pod -c istio-init、istioctl proxy-config listener的输出按顺序贴进去。Codex 走的是 TaoToken 的统一通道它能看到的是你贴过去的文本不是你的 k8s API。4.2 REDIRECT 计数为 0 时先看 ISTIO_OUTPUT 提前 RETURNISTIO_REDIRECT的pkts为 0通常说明包没有走到这条链。回到ISTIO_OUTPUT看前面的规则尤其是-j RETURN。常见排除项包括--uid-owner 1337、--dport 15020、--dport 15090、特定目的网段、特定出口网卡。如果业务容器的 UID 或端口被误伤它发出的请求就会提前返回永远不会 REDIRECT 到 15001。可以对照下面这个判断表现象iptables 证据listener 证据优先判断15001 零包ISTIO_REDIRECT的 pkts 为 0virtualOutbound 存在重定向没命中连接被拒ISTIO_REDIRECT的 pkts 增加15001 未 readylistener 或就绪顺序inbound 失败ISTIO_IN_REDIRECT的 pkts 为 015006 存在PREROUTING 或端口排除只有部分服务异常规则存在但接口/网段不匹配listener 正常出口网卡或排除列表这张表不是让你背而是让你在贴给 Codex 时能明确告诉它“现在计数器是哪种状态”。模型拿到明确状态给出的下一步命令才不会发散。4.3 端口错位、UID 排除、接口匹配三种典型现象端口错位很好认REDIRECT目标写成了 15000、15002或者 inbound 写成了 15001。listener 那边却仍然在 15001/15006 监听两边对不上。UID 排除则更隐蔽规则看起来完整但业务进程恰好是 1337包在ISTIO_OUTPUT里直接 RETURN。接口匹配问题通常和-i、-o、-x参数有关比如只匹配了某个网卡名而实际出站走的是另一个接口。这三种现象的共同点是光看 Deployment YAML 和 Service YAML 都看不出来。必须把 nat 表、init container 参数、listener 摘要放在一起。Codex 可以帮你把istio-iptables参数和实际链规则做映射比如-p 15001对应 outbound 端口-z 15006对应 inbound 端口-u 1337对应 proxy 自身排除。但最终是不是你的应用被排除仍然要看你本地导出的计数器。5. 改完规则后的验证从 pod 内发起请求看 15001 计数器5.1 重新注入或重启后先确认规则版本如果你调整了注入 Annotation、命名空间标签、istio-init参数最稳妥的方式是重建 Pod而不是在运行中的 Pod 里手工改 iptables。手工改只能做临时验证下一次重建就丢了还可能和生产期望不一致。重建后先确认istio-init退出码为 0再重新导出一次 nat 表确认ISTIO_OUTPUT、ISTIO_REDIRECT的规则和你预期一致。kubectl get pod pod -n ns -o wide kubectl describe pod pod -n ns | sed -n /Init Containers/,/Containers/pREADY 显示2/2只代表容器就绪不代表流量劫持链路完全正确。还是要看规则和计数器。5.2 验证 outbound 和 inbound 两条链路从业务容器里发一个出站请求然后在另一个终端观察ISTIO_REDIRECT的计数器。注意不要用istio-proxy容器里的curl去测 outbound因为 proxy 自己的 UID 1337 通常被排除测出来的结果会误导你。业务容器没有 curl/wget 时可以用临时 debug 容器加入同一 netns但同样要确认发起请求的 UID 和端口没有被排除。kubectl exec -it pod -n ns -c app-container -- sh -c wget -qO- http://service.ns.svc.cluster.local:port/ kubectl exec -it pod -n ns -c istio-proxy -- iptables -t nat -L ISTIO_REDIRECT -n -v kubectl exec -it pod -n ns -c istio-proxy -- iptables -t nat -L ISTIO_IN_REDIRECT -n -v如果 outbound 计数器增加说明包已经进了 15001如果 inbound 计数器增加说明 15006 链路也起来了。接下来再看 Envoy 的 route、cluster、endpoint判断请求为什么 503 或 404。5.3 回控制台看这次 Codex 调用是否记上账排障过程中如果让 Codex 反复解释和对照建议回到 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content 控制台确认这次 Key 的调用记录顺便核对当前用的模型 ID 和 Base URL。这个动作和查 iptables 一样都是“用证据说话”一边确认数据平面计数器一边确认模型通道调用正常。若 Codex 侧出现 401先查环境变量若出现 404先查模型 ID 和base_url是否写成https://taotoken.net/api不要在后面补/v1。6. 还不出流量时Sidecar 就绪顺序与 VirtualService、DestinationRule 对照6.1 就绪顺序导致的 connection refused 和零包区别15001 零包和 15001 连接失败是两回事。零包说明重定向没发生优先查ISTIO_OUTPUT和ISTIO_REDIRECT。连接失败说明重定向发生了但 Envoy 没有及时监听或处理。Sidecar 就绪顺序就可能造成后一种情况应用容器启动很快istio-proxy还在初始化15001 还没 ready应用发请求就会 connection refused。等 Sidecar ready 后重试可能恢复但日志里会留下启动阶段的报错。所以看问题时先把现象分开ISTIO_REDIRECT计数为 0就查规则计数增加但应用报 connection refused就查 15001 listener 和 proxy readiness。不要用一种药治两种病。6.2 控制面下发的 VirtualService 与 listener 是否匹配控制面下发的VirtualService、DestinationRule不会直接改 iptables。它们影响的是 Envoy 的 route、cluster、endpoint 配置。也就是说15001 收到流量之后Envoy 才会根据这些配置决定转发到哪里。如果 iptables 和 listener 都对但请求还是失败就要看 route 有没有匹配上、cluster 有没有 endpoint、DestinationRule 有没有把流量引到不存在的 subset。istioctl proxy-config route pod -n ns istioctl proxy-config cluster pod -n ns istioctl proxy-config endpoint pod -n ns把这三份输出也贴给 Codex让它帮你对照服务名、端口、subset 和 listener 的匹配关系。仍然要强调Codex 只做解释和生成命令执行和结果采集在你本地完成。6.3 同一把 Key 继续追问但结论仍由你本地验证这套排查方法的价值在于前面配好的 Codex 通道可以继续用。你可以在同一个对话里继续问“这个 cluster 为什么没有 endpoint”“这个 route 的 match 条件是不是和 header 对不上”“15006 的 filter chain 为什么走了 passthrough”但每一次都要求 Codex 给出可复制命令由你在本机执行再把输出贴回来。不要让它直接连生产集群也不要把 kubeconfig 交给任何外部服务。如果这套流程你准备长期用建议先在 TaoToken 模型对话 里用同一把 Key 发一条测试消息确认模型 ID 和通道都正常需要长期跑代码对照可以看 Coding Plan 是否够用新的 Key 继续在 控制台 API Keys 创建。
返回列表