Administrator
Administrator
发布于 2026-10-28 / 0 阅读
0
0

Kubernetes 故障排查(11):连接超时却不是 DNS:NetworkPolicy 如何定位到来源和方向

面向初级运维,使用 Linux 节点和稳定 Kubernetes API。命令按 Bash 编写。本文为教学故障场景,日志及结果为示意,不冒充生产实测;执行前确认 context、命名空间和权限。

一、遭遇情况:能解析 Service,HTTP 却一直超时

应用名称可以解析,后端也 Ready,但客户端发起 HTTP 请求没有响应。一次网络策略变更后才开始出现,其他命名空间的某些客户端却仍能访问。

本篇案例是目标 Web Pod 被一份 ingress 隔离策略选中,但没有允许当前客户端访问。需要核对来源、目标、方向和端口,而不只是搜索策略里有没有“80”。

二、原因分析:策略对象存在,不代表当前网络实现会执行

NetworkPolicy 的执行依赖支持它的网络插件。API 允许创建该对象,不自动证明集群 CNI 已实施隔离。实验前应确认网络实现支持相应策略。

NetworkPolicy 从流量坐标到规则的判断

标准策略是允许规则叠加:多份选中相同 Pod 的策略,其允许流量会合并,不是后写的规则覆盖前一份。某方向未被选入隔离时,与被隔离后需要许可是不同状态。

客户端 egress 与服务端 ingress 都进入隔离时,流量通常需要双方各自允许。只在服务端放行,并不自动替客户端增加出口许可。

三、排查思路:看标签与实际方向

kubectl get networkpolicy -n 目标命名空间
kubectl get networkpolicy -n 目标命名空间 -o yaml
kubectl get pods -n 目标命名空间 --show-labels
kubectl get namespaces --show-labels

结合客户端和服务端两侧的命名空间检查,不要只读目标服务那一侧。podSelector 写在 policy 顶层时选择被保护的 Pod,写在 peer 中时选择相应来源或目标,语义位置不同。

同一个 peer 内的 namespaceSelector 与 podSelector 组合,和分成两个 peer 的允许范围也不同。缩进合法不代表逻辑正确,要把它翻译成“哪些命名空间里的哪些 Pod”。

四、实践:只隔离实验 Web 的入口

保存 kt11-networkpolicy.yaml。前提是集群支持并启用了 NetworkPolicy,且没有其他集群级规则干扰本实验。

apiVersion: v1
kind: Namespace
metadata:
  name: kt11
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: kt11
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:stable-alpine
          readinessProbe:
            httpGet:
              path: /
              port: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: kt11
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: isolate-web-ingress
  namespace: kt11
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes: [Ingress]
  ingress: []
kubectl apply -f kt11-networkpolicy.yaml
kubectl rollout status deployment/web -n kt11 --timeout=120s
kubectl run client -n kt11 --image=busybox:1.37 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/client -n kt11 --timeout=120s
kubectl exec client -n kt11 -- nslookup web
kubectl exec client -n kt11 -- wget -T 3 -qO- http://web:80/

预期 DNS 正常、HTTP 被入口隔离阻止。若 HTTP 仍成功,先确认 CNI 执行能力、现有允许策略和测试流量路径,不应把成功解释为“NetworkPolicy 没用”。

五、修复实践:只允许带特定标签的本命名空间客户端

保存 kt11-allow.yaml:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-approved-clients
  namespace: kt11
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes: [Ingress]
  ingress:
    - from:
        - podSelector:
            matchLabels:
              access: approved
      ports:
        - protocol: TCP
          port: 80
kubectl apply -f kt11-allow.yaml
kubectl label pod client -n kt11 access=approved
kubectl exec client -n kt11 -- wget -T 3 -qO- http://web:80/

预期允许该客户端访问。这里 peer 的 podSelector 没有 namespaceSelector,因此选择同一命名空间内匹配标签的 Pod,不是全群所有带该标签的 Pod。

六、验证:允许目标成功,不该放开的仍失败

再创建一个不带 access 标签的独立客户端,执行同样请求,应仍被阻止。然后核对 DNS 和其他必要依赖是否受影响。不要通过删除所有 NetworkPolicy 来证明应用能通,删规则会同时改变太多变量。

NetworkPolicy 通常不负责 HTTP 路径、用户身份和 TLS 内容授权;来源地址还可能受 NAT、控制器和网络实现影响。真实流量穿过 Ingress 控制器时,要按实际来源条件设计,而不是照搬终端客户端标签。

七、总结

排查顺序是:DNS 与端点是否正常 → 源和目标是谁 → 哪个方向被隔离 → 哪些允许规则适用 → 做最小放行 → 正反验证。最小修复不是“开放所有方向”,而是把必要业务路径表达准确。

官方参考


上一篇 · 系列目录 · 下一篇


评论