K8s 网络策略(NetworkPolicy)实战 + 调试
默认 K8s 任意 Pod 间互通,零安全。NetworkPolicy 是命名空间级别的 L3/L4 防火墙,本文给一套生产可用的策略集。
前提
NetworkPolicy 是声明式,但真正生效要 CNI 支持:
- Calico ✅
- Cilium ✅
- WeaveNet ✅
- Flannel ❌(默认不支持,要加 Canal)
kubectl get pods -n kube-system | grep -E "calico|cilium" # 确认 CNI
第一条:默认拒绝
每个 namespace 都先加一条 default deny:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
应用后整个 ns 所有 Pod 收发都断。然后按需放开。
放通同 namespace 内部
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: production
spec:
podSelector: {}
ingress:
- from:
- podSelector: {}
放通 DNS
90% 的应用都要 DNS,必须放:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
跨 namespace 调用(前端 → 后端)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
namespace: backend
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 8080
注意 ingress 是作用在被访问方——这条 policy 部署在 backend ns。
调试技巧
策略加错了 Pod 突然连不上,怎么定位?
# 1. 看哪些 policy 作用在这个 Pod
kubectl get networkpolicy -A -o jsonpath='{.items[*].spec.podSelector}' | grep <label>
# 2. 用 cilium hubble 看实际流量
hubble observe --from-pod production/api --to-pod production/db
# 3. 临时关掉所有 policy 看是否就通了
kubectl delete networkpolicy --all -n production # 危险
常见坑
- labels 改了 policy 失效:podSelector 是按 label 匹配,重命名了 label 要同步改
- namespaceSelector 需要 ns 有对应 label:默认 ns 没 label,K8s 1.22+ 自动加
kubernetes.io/metadata.name - Egress 拒绝把 healthcheck 也封了:kubelet 探测来自 host network,需要放通节点 IP
- CNI 不支持 Egress:老版本 Calico 默认只支持 Ingress
教训:NetworkPolicy 先在 staging 跑两周,盯监控有没有断流,再推生产。