Kubernetes默认网络模型下,所有Pod之间网络互通,这在多租户或生产环境中存在安全风险。NetworkPolicy是K8s原生的网络流量控制机制,配合CNI插件可以实现Pod级别的入站和出站规则。
NetworkPolicy工作机制
NetworkPolicy是命名空间级别的资源,通过标签选择器定义目标Pod,通过ingress和egress规则定义允许的流量方向和来源。默认拒绝(Default Deny)模式下,未匹配任何策略的Pod所有流量被阻断。
NetworkPolicy的执行依赖CNI插件支持。主流CNI插件的NetworkPolicy支持情况:
- Calico:原生支持全部NetworkPolicy功能,还扩展了GlobalNetworkPolicy
- Cilium:基于eBPF实现,支持Layer 3-7策略,性能优于iptables模式
- Flannel:不原生支持,需要叠加Calico(Canal模式)
- Antrea:基于Open vSwitch,支持完整NetworkPolicy
默认拒绝策略配置
实现命名空间级别的默认拒绝,需要分别创建ingress和egress的默认拒绝策略:
# default-deny-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
---
# default-deny-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
kubectl apply -f default-deny-ingress.yaml
kubectl apply -f default-deny-egress.yaml
应用后,production命名空间内所有Pod无法接收和发起任何网络连接。后续通过白名单策略逐步放开必要流量。
分层服务访问策略
典型的三层架构(前端到后端到数据库)中,需要严格限制每层只能访问相邻层。以production命名空间为例:
# frontend-policy.yaml - 前端只能被Ingress Controller访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-policy
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
tier: web
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- protocol: TCP
port: 8080
---
# backend-policy.yaml - 后端只接收前端流量,只访问数据库
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: production
spec:
podSelector:
matchLabels:
app: backend
tier: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
tier: web
ports:
- protocol: TCP
port: 3000
egress:
- to:
- podSelector:
matchLabels:
app: postgres
tier: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
---
# database-policy.yaml - 数据库只接收后端流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: database-policy
namespace: production
spec:
podSelector:
matchLabels:
app: postgres
tier: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
tier: api
ports:
- protocol: TCP
port: 5432
Cilium策略与L7过滤
Cilium的CiliumNetworkPolicy扩展了标准NetworkPolicy,支持HTTP方法、路径等L7层过滤。适用于API级别的细粒度控制:
# cilium-api-policy.yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: api-l7-policy
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
tier: api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
tier: web
toPorts:
- ports:
- port: "3000"
protocol: TCP
rules:
http:
- method: GET
path: "/api/v1/.*"
- method: POST
path: "/api/v1/orders"
# 其他HTTP路径全部拒绝
这条策略只允许前端Pod对后端发起GET /api/v1/*和POST /api/v1/orders请求,其他HTTP路径的流量在L7层被丢弃。
策略审计与排障
NetworkPolicy排障的核心问题:流量被策略阻断但不确定是哪条策略导致的。
# 查看命名空间下所有NetworkPolicy
kubectl get networkpolicy -n production
# 查看Pod被哪些策略选中
kubectl get pod -n production -l app=backend -o wide
kubectl get networkpolicy -n production -o yaml | grep -A5 podSelector
# Calico环境使用calicoctl验证
calicoctl policy --namespace production --selector "app=='backend'" \
--detail
# Cilium环境查看策略命中情况
cilium policy get
cilium monitor --type drop # 实时查看被丢弃的流量
# 命名空间间流量验证
kubectl exec -n test nettool -- curl -s -o /dev/null \
-w "%{http_code}" http://backend.production:3000/api/v1/health
生产环境策略管理建议
策略膨胀是真问题。一个中等规模的集群可能积累上百条NetworkPolicy,互相覆盖和冲突。建议的策略管理实践:
- 使用策略生成器(如kyverno)从模板自动生成策略,减少手工编写
- 定期审计策略,移除不再使用的Pod选择器和端口规则
- 在CI流水线中加入策略dry-run,验证部署变更不违反网络策略
- 监控策略命中率,Cilium的Hubble可以提供策略执行的可视化
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-wang-luo-ce-lyue-shi-zhan-networkpolicy-liu/