16.7.3 NetworkPolicy网络隔离
NetworkPolicy 用于在 Kubernetes 中实现命名空间内/跨命名空间的网络访问控制,通过基于标签的策略定义限制 Pod 的入站与出站流量。其核心对象是 NetworkPolicy 资源,依赖 CNI 插件实现(如 Calico、Cilium、Weave)。在没有策略时默认允许所有流量;一旦对某 Pod 选择器匹配并应用策略,默认变为“拒绝”,仅放行策略允许的流量。
原理与数据流(示意):
关键概念与字段要点:
- podSelector:选择受策略保护的目标 Pod 集合
- policyTypes:Ingress / Egress
- ingress / egress:允许的流量规则(from/to)
- namespaceSelector、podSelector、ipBlock:流量源/目标匹配方式
- ports:协议与端口范围控制
- 规则为白名单并集:多条策略叠加后,允许集合取并集
CNI 安装与校验(示例:Calico):
# 1) 安装 Calico(Kubernetes 1.26+)
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
# 2) 确认 CNI 正常
kubectl -n kube-system get pods -l k8s-app=calico-node -o wide
# 3) 检查节点 CNI 配置(每个节点)
ls -l /etc/cni/net.d/
cat /etc/cni/net.d/10-calico.conflist
基础环境示例(创建命名空间与测试 Pod):
# 创建命名空间
kubectl create ns netpol-demo
# 创建前端与后端 Pod
kubectl -n netpol-demo run frontend --image=nginx --labels=app=frontend --port=80
kubectl -n netpol-demo run backend --image=nginx --labels=app=backend --port=80
# 暴露后端为 Service(便于测试)
kubectl -n netpol-demo expose pod backend --name=backend-svc --port=80
# 验证连通性(默认允许)
kubectl -n netpol-demo exec frontend -- curl -sS http://backend-svc
示例一:默认拒绝所有入站流量(零信任基线)
# /tmp/np-deny-all-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: netpol-demo
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
kubectl apply -f /tmp/np-deny-all-ingress.yaml
# 预期:前端访问后端失败
kubectl -n netpol-demo exec frontend -- curl -m 3 -sS http://backend-svc || echo "blocked"
命令解释:
- policyTypes: Ingress:仅控制入站
- ingress 为空:拒绝所有入站流量
示例二:仅允许同命名空间内标签访问(前端访问后端)
# /tmp/np-allow-frontend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: netpol-demo
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
kubectl apply -f /tmp/np-allow-frontend.yaml
# 预期:允许前端访问后端
kubectl -n netpol-demo exec frontend -- curl -sS http://backend-svc
# 其他 Pod 访问应被阻断
kubectl -n netpol-demo run test --image=busybox --restart=Never --labels=app=test -- sh -c "sleep 3600"
kubectl -n netpol-demo exec test -- wget -qO- --timeout=3 http://backend-svc || echo "blocked"
示例三:允许运维网段访问管理端口(ipBlock)
# /tmp/np-allow-ops-cidr.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ops-cidr
namespace: netpol-demo
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 10.0.0.0/24
except:
- 10.0.0.128/25
ports:
- protocol: TCP
port: 8443
说明:
- cidr 允许运维网段访问
- except 排除子网
- 常用于管理端口(如 8443)
示例四:限制出站访问仅允许数据库(Egress)
# /tmp/np-egress-only-db.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-only-db
namespace: netpol-demo
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: mysql
ports:
- protocol: TCP
port: 3306
# 假设已有 mysql Pod
kubectl -n netpol-demo run mysql --image=mysql:8 --labels=app=mysql \
--env MYSQL_ROOT_PASSWORD=pass --port=3306
kubectl apply -f /tmp/np-egress-only-db.yaml
# 后端访问数据库允许
kubectl -n netpol-demo exec backend -- sh -c "nc -zvw2 mysql 3306"
# 后端访问公网会被阻断(若有 egress 默认拒绝)
kubectl -n netpol-demo exec backend -- sh -c "wget -qO- --timeout=3 http://example.com || echo blocked"
核心命令与说明(排错与核验):
# 查看策略
kubectl -n netpol-demo get networkpolicy
kubectl -n netpol-demo describe networkpolicy allow-frontend-to-backend
# 验证标签选择是否匹配
kubectl -n netpol-demo get pod --show-labels
# 检查 Service 与 Endpoints
kubectl -n netpol-demo get svc,ep
# 观察 CNI 日志(Calico)
kubectl -n kube-system logs -l k8s-app=calico-node --tail=200
常见故障排查:
- 策略无效:CNI 不支持 NetworkPolicy 或未正确安装
- 误阻断 DNS:需放行 kube-dns
# /tmp/np-allow-dns.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: netpol-demo
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
kubectl apply -f /tmp/np-allow-dns.yaml
实践建议与规范:
- 先建立命名空间默认隔离策略,再逐步细化应用级放行
- 采用标签规范化(app、role、tier)提升可维护性
- 变更策略前在测试环境验证,避免误阻断核心链路
- 与 RBAC、Pod 安全策略、ServiceAccount 联合实施形成完整安全体系
练习题(动手):
1. 为 netpol-demo 命名空间创建“默认拒绝入站 + 允许前端访问后端”的两条策略,并验证连通性变化。
2. 增加 Egress 策略,只允许后端访问 kube-dns 与 mysql:3306,并验证访问公网被阻断。
3. 使用 namespaceSelector 允许来自 monitoring 命名空间的探针访问后端 9113 端口。