第17章 NetworkPolicy与安全隔离
学习目标
- 理解NetworkPolicy的工作原理和配置方法
- 掌握网络策略的规则设计和最佳实践
- 了解不同CNI插件的NetworkPolicy实现
- 能够排查网络策略相关的安全问题
前置知识
17.1 NetworkPolicy概述
17.1.1 什么是NetworkPolicy
NetworkPolicy是Kubernetes中用于控制Pod间网络通信的安全策略,提供基于标签的网络隔离和流量控制。
核心功能:
- 网络隔离:控制Pod间的网络通信
- 流量控制:限制入站和出站流量
- 安全策略:基于标签的访问控制
- 微隔离:实现零信任网络架构
17.1.2 NetworkPolicy工作原理
┌─────────────────────────────────────────────────────────────┐
│ NetworkPolicy Architecture │
├─────────────────────────────────────────────────────────────┤
│ NetworkPolicy Resource │
├─────────────────────────────────────────────────────────────┤
│ CNI Plugin (Calico, Cilium, etc.) │
├─────────────────────────────────────────────────────────────┤
│ Network Rules (iptables, eBPF, etc.) │
├─────────────────────────────────────────────────────────────┤
│ Pod Network Traffic │
└─────────────────────────────────────────────────────────────┘
17.1.3 支持NetworkPolicy的CNI插件
- Calico:基于iptables和BGP
- Cilium:基于eBPF
- Weave Net:基于iptables
- Romana:基于iptables
- Flannel:不支持(需要额外组件)
17.2 NetworkPolicy配置
17.2.1 基本配置结构
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: example-network-policy
namespace: default
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
- namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 80
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 3306
17.2.2 选择器类型
1. Pod选择器
podSelector:
matchLabels:
app: nginx
matchExpressions:
- key: tier
operator: In
values: [frontend, backend]
2. 命名空间选择器
namespaceSelector:
matchLabels:
name: production
3. IP块选择器
ipBlock:
cidr: 10.0.0.0/8
except:
- 10.0.1.0/24
17.3 实验:NetworkPolicy实践
17.3.1 实验环境准备
创建测试应用:
# frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
labels:
app: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
---
# backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
labels:
app: backend
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
部署应用:
# 创建Deployment
kubectl apply -f frontend-deployment.yaml
kubectl apply -f backend-deployment.yaml
# 验证部署
kubectl get pods -l app=frontend
kubectl get pods -l app=backend
17.3.2 实验1:默认拒绝策略
步骤1:创建默认拒绝策略
# default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
步骤2:应用策略并测试
# 应用策略
kubectl apply -f default-deny.yaml
# 测试Pod间通信
kubectl exec -it frontend-pod -- wget -qO- http://backend-service
# 应该失败,因为默认拒绝所有流量
17.3.3 实验2:允许特定流量
步骤1:创建允许策略
# allow-frontend-to-backend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
步骤2:测试通信
# 应用策略
kubectl apply -f allow-frontend-to-backend.yaml
# 测试frontend到backend的通信
kubectl exec -it frontend-pod -- wget -qO- http://backend-service
# 应该成功
# 测试backend到frontend的通信
kubectl exec -it backend-pod -- wget -qO- http://frontend-service
# 应该失败,因为没有允许backend到frontend的流量
17.3.4 实验3:命名空间隔离
步骤1:创建命名空间
# 创建命名空间
kubectl create namespace production
kubectl create namespace development
# 为命名空间添加标签
kubectl label namespace production name=production
kubectl label namespace development name=development
步骤2:创建跨命名空间策略
# cross-namespace-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-production-to-backend
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 80
17.4 高级NetworkPolicy功能
17.4.1 端口范围
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: port-range-policy
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
- protocol: TCP
port: 8080-8090
17.4.2 出站策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-policy
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 3306
- to: []
ports:
- protocol: TCP
port: 53
- protocol: UDP
port: 53
17.4.3 组合选择器
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: complex-policy
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 80
17.5 不同CNI插件的实现
17.5.1 Calico实现
查看Calico策略:
# 查看Calico网络策略
calicoctl get networkpolicy
# 查看Calico全局网络策略
calicoctl get globalnetworkpolicy
# 查看Calico策略详情
calicoctl get networkpolicy default.allow-frontend-to-backend -o yaml
Calico策略转换:
# 将Kubernetes NetworkPolicy转换为Calico格式
calicoctl convert policy -f network-policy.yaml
17.5.2 Cilium实现
查看Cilium策略:
# 查看Cilium网络策略
kubectl get cnp
# 查看Cilium端点策略
kubectl get cep
# 查看Cilium策略详情
kubectl get cnp allow-frontend-to-backend -o yaml
Cilium策略验证:
# 使用Cilium CLI验证策略
cilium policy get
# 查看策略统计
cilium policy trace --src-identity 1 --dst-identity 2
17.6 故障排查
17.6.1 常见问题诊断
问题1:策略不生效
# 检查CNI插件是否支持NetworkPolicy
kubectl get pods -n kube-system | grep -E "(calico|cilium|weave)"
# 检查NetworkPolicy状态
kubectl get networkpolicy
# 检查Pod标签
kubectl get pods --show-labels
问题2:流量被意外阻止
# 检查所有NetworkPolicy
kubectl get networkpolicy -o yaml
# 检查Pod选择器匹配
kubectl get pods -l app=frontend
# 测试网络连通性
kubectl exec -it pod-name -- ping target-pod-ip
问题3:策略冲突
# 查看所有策略
kubectl get networkpolicy
# 检查策略优先级
kubectl describe networkpolicy policy-name
# 查看CNI插件日志
kubectl logs -n kube-system -l k8s-app=calico-node
17.6.2 调试工具
# 使用netshoot调试网络
kubectl run netshoot --image=nicolaka/netshoot -it --rm
# 使用tcpdump抓包
kubectl exec -it pod-name -- tcpdump -i eth0
# 使用netstat查看连接
kubectl exec -it pod-name -- netstat -tulpn
17.7 排错清单
17.7.1 NetworkPolicy配置检查
- [ ] CNI插件是否支持NetworkPolicy
- [ ] 策略语法是否正确
- [ ] Pod选择器是否匹配
- [ ] 端口配置是否正确
- [ ] 策略是否应用到正确的命名空间
17.7.2 网络连通性检查
- [ ] Pod标签是否正确
- [ ] 策略规则是否合理
- [ ] 是否有策略冲突
- [ ] 网络插件是否正常
- [ ] 防火墙规则是否正确
17.7.3 安全策略检查
- [ ] 默认拒绝策略是否生效
- [ ] 允许规则是否最小化
- [ ] 跨命名空间访问是否受限
- [ ] 出站流量是否受控
- [ ] 策略变更是否及时生效
17.8 延伸阅读
下一章:第18章 Calico深度解析
返回目录:README