加了条 NetworkPolicy,消息队列直接断了——K8s 默认拒绝挨的第一刀

场景:给支付服务加了一条 NetworkPolicy——只允许订单服务访问 8080。支付接口正常了,但订单突然收不到支付回调——不是代码改了,是订单到支付的异步消息走的是 RabbitMQ(5672 端口),被 NetworkPolicy 一视同仁拦了 路径:坐标(现象:HTTP 正常、MQ 超时)→ 分层(Pod → Service → NetworkPolicy → 理解默认拒绝行为)→ 路径(3 条命令排查)→ 定位(查 MQ 配了两小时,根因在 NetPol)→ 标点(修复 + Check-list) K8s 版本:v1.28,Calico CNI

上篇讲跨 Namespace 调用时提到了一个关键认识——K8s 不是只拦跨 Namespace 的流量,同 Namespace 内,一条 NetworkPolicy 也能把自己人拦在门外。

给支付服务加了一条 NetworkPolicy——只允许订单服务访问 8080。支付接口正常了,但订单突然不发货了。不是代码改了,是订单到支付的异步消息走的是 RabbitMQ(5672 端口),被 NetworkPolicy 一视同仁拦了。

你不是多配了一个端口——是你忘了 NetworkPolicy 的默认原则:只允许显式声明的,拒绝其他所有。

【坐标】现象:HTTP 正常、MQ 超时

结论前置:服务在跑、端口不同、一个通一个不通

order-service 调用 payment-service——HTTP(8080)一切正常,但异步消息(RabbitMQ,5672)一直超时。

订单服务异步消息超时

2026-07-10 14:32:18.123 ERROR [order-service] o.s.a.r.c.CachingConnectionFactory : Channel shutdown: connection error
2026-07-10 14:32:18.124 ERROR [order-service] c.o.order.service.PaymentGateway    : Failed to send message to payment.queue: timeout after 30000ms
2026-07-10 14:32:18.125  WARN [order-service] c.o.order.service.PaymentGateway    : Retrying... attempt 2/3

证据展开:看 Pod 状态、看 Service、看 Endpoints

Pod 确认 Running:

kubectl get pod -n production -l app=payment-service -o wide
# NAME                                READY   STATUS    RESTARTS   AGE   IP              NODE
# payment-service-5d8f9c6b4-j2k9s   2/2     Running   0          12h   10.244.2.15     node-2

Service 正常、Endpoint 有 IP:

kubectl get svc -n production rabbitmq
# NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
# rabbitmq   ClusterIP   10.96.123.45    <none>        5672/TCP   30d

kubectl get endpoints -n production rabbitmq
# NAME       ENDPOINTS           AGE
# rabbitmq   10.244.1.15:5672    30d

开发的第一反应:"RabbitMQ 连不上了——连接字符串写错了?认证配错了?Vhost 不对?"

衔接:Service 有 IP,Pod 也正常——那问题在哪一层?

IP 能解析、Service 有 Endpoint、Pod 在 Running——问题不在应用层,在中间的流量控制层。


【分层】逐层排查:从 Pod 日志到 NetworkPolicy

NetworkPolicy 流量路径示意

排查顺序

层级 命令 关键输出
① Pod 层 kubectl logs kubectl describe pod MQ 超时、无异常 Event
② Service 层 kubectl get svc / endpoints RabbitMQ 正常,Endpoint 有 IP
③ 网络层 kubectl get networkpolicy --all-namespaces 一条 NetPol 只配了 8080
④ 深入 kubectl describe networkpolicy PolicyTypes: Ingress,ports: [8080]

第一层:Pod——日志明确说"连接被关"

kubectl logs payment-service-5d8f9c6b4-j2k9s -n production -c payment

Payment 服务连 RabbitMQ 超时

2026-07-10 14:32:20.001 INFO  [payment-service] o.s.a.r.l.SimpleMessageListenerContainer : Broke connection to rabbitmq.production.svc:5672
2026-07-10 14:32:20.002 ERROR [payment-service] o.s.a.r.l.SimpleMessageListenerContainer : Could not connect to RabbitMQ: connection timed out

Payment 连 RabbitMQ 也超时。这不是"order 发不出去"——是 order 发、payment 收,两边都连不上。

kubectl describe pod 看 Events:没有 OOM、没有 FailedScheduling、没有 CrashLoopBackOff。Events 干干净净。

第二层:Service——DNS 和 Endpoint 没问题

kubectl get svc -n production -o wide
# NAME              TYPE        CLUSTER-IP     PORT(S)     SELECTOR
# rabbitmq          ClusterIP   10.96.123.45   5672/TCP    app=rabbitmq
# order-service     ClusterIP   10.96.100.1    8080/TCP    app=order-service
# payment-service   ClusterIP   10.96.100.2    8080/TCP    app=payment-service
kubectl get endpoints -n production rabbitmq -o wide
# NAME       ENDPOINTS           AGE
# rabbitmq   10.244.1.15:5672    30d

DNS 能解析、Endpoint 有 Pod IP。Service 层没问题。

第三层:网络——发现 NetworkPolicy 只显式允许了 8080

kubectl get networkpolicy --all-namespaces
NAMESPACE    NAME                      POD-SELECTOR     AGE
production   allow-order-to-payment    app=payment      2h

NetworkPolicy 详情

看到问题了吗——Ports 只列了 8080/TCP没有 5672。但 Service 的 HTTP(8080)能通,说明"不是全不通,是部分不通"。关键区别就在这里。

第四层:理解 NetworkPolicy 的默认拒绝

Pod 匹配了 NetworkPolicy 的 podSelector 之后,只允许 Policy 中显式声明的入站流量,其他所有入站流量都被拒绝。

NetworkPolicy — K8s 的网络访问控制资源。当一个 Pod 被 NetworkPolicy 选中(匹配 podSelector),该 Pod 的入站/出站流量就受 Policy 约束——只允许规则中显式声明的流量,其他全拒绝。

payment-service 的 Pod 被 allow-order-to-payment 选中了(app=payment-service),所以它的入站流量只允许: - 来自 app=order-service 的 Pod - 目标端口 8080

5672 不在允许列表中 → 被 K8s 网络插件(这里是 Calico)默默丢弃。

这解释了为什么: - HTTP 8080 能通 ✅ — 在规则中 - MQ 5672 不通 ❌ — 不在规则中


【路径】🔍 排查 NetworkPolicy 的 3 条命令

结论前置:三板斧测到底

NetworkPolicy 排查命令三板斧

衔接:命令链即排查思路

<< 排查口诀 >> HTTP 通 + MQ 不通 + 同一 Service → 中间层在过滤端口

以上三条命令按顺序执行:先发现有哪些 NetPol → 再看具体规则 → 最后验证标签匹配。任何 NetworkPolicy 问题都能在 2 分钟内定位到原因。


【定位】最常误判:查 MQ 配了两小时,根因在 NetPol

❌ 错误排查方向:RabbitMQ 配置错了

小张是订单服务的 Owner,看到 MQ 超时的第一时间就去翻代码——"连接字符串没配错啊"。然后查 RabbitMQ 管理界面——"认证通过了啊"。然后查 Vhost——"也对啊"。然后看日志——"channel shutdown——

看代码 → 连接字符串配对了?
看配置 → Vhost 配对了?
看认证 → 用户名密码对了?
看日志 → "channel shutdown"(连接关闭)
→ 再查一遍连接字符串 → 再看一遍认证

循环了 2 个小时,什么都没改。

✅ 正确排查方向:流量被 NetworkPolicy 拦了

关键问题是:HTTP 能通,MQ 不通——同一个 Pod、不同的端口

把问题反过来想:如果 MQ 配置真的错了,应该 HTTP 也不通(或至少不是这个现象)。HTTP 通 + MQ 不通 + 同一条 Service 链路 = 中间层在过滤端口

敲这个命令直接验证:

kubectl describe networkpolicy -n production allow-order-to-payment

看到 Ports: [8080] 的那一刻,根因就清楚了——不是 MQ 连不上,是流量到不了 MQ


【标点】修复 + Check-list

修复:在 NetworkPolicy 中添加 MQ 端口

NetworkPolicy YAML 修复前后对比

记住:一个 YAML 字段没配,不是 K8s 会帮你兜底——是它会按默认值运行,而默认值往往不适合你的场景。

NetworkPolicy 排查 Check-list

□ kubectl get networkpolicy --all-namespaces
  → 列出所有 NetPol,确认目标 Pod 是否被任何 Policy 选中

□ kubectl describe networkpolicy <name> -n <ns>
  → 查看 Policy 的 ports 列表、podSelector、namespaceSelector
  → 检查是否覆盖了所有需要的端口

□ kubectl get pod -n <ns> --show-labels
  → 确认 Pod 标签是否与 podSelector 匹配
  → 不匹配 = Pod 不受此 Policy 管理

□ 反向验证:kubectl exec -it <pod> -n <ns> -- curl -v <target-ip>:<port>
  → 直接到 Pod 网络命名空间里验证连通性
  → 通 = NetworkPolicy 以外的原因;不通 = 大概率 NetPol

附:完整命令清单

# NetworkPolicy 排查三板斧
kubectl get networkpolicy --all-namespaces
kubectl describe networkpolicy <name> -n <namespace>
kubectl get pod -n <namespace> --show-labels

# 容器内连通验证
kubectl exec -it <pod> -n <namespace> -- curl -v <target-ip>:<port> -m 5

# 目标 Pod 日志(看是否有入站连接)
kubectl logs -n <namespace> -l app=<target-app> --tail=50

# 查看 K8s 网络插件是否正常工作(Calico 示例)
kubectl get pods -n kube-system -l k8s-app=calico-node

下篇我们聊 NodePort 端口冲突——同一个端口被多个 Service 映射,谁也起不来。

🔗 个人博客:https://opencao.cn
📺 公众号:Ai拆代码的曹操
🌟 知识星球:Ai拆代码的曹操