网络策略
学习目标
- 理解 NetworkPolicy 的作用和重要性
- 掌握 NetworkPolicy 的配置方法
- 了解网络策略的最佳实践
核心概念
一句话解释
NetworkPolicy 用于控制 Pod 之间以及 Pod 与外部网络之间的网络访问,默认情况下所有 Pod 都可以互相通信,NetworkPolicy 可以限制这种访问。
为什么需要 NetworkPolicy
默认情况:所有 Pod 可以互相通信
┌─────────────────────────────────────────┐
│ Kubernetes 集群 │
│ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │ Web │ │ API │ │ DB │ │
│ │ │←→│ │←→│ │ │
│ └───────┘ └───────┘ └───────┘ │
│ ↑ ↑ ↑ │
│ └──────────┴──────────┘ │
│ 所有 Pod 可以互相访问 │
└─────────────────────────────────────────┘
问题:
- 安全性差:任何 Pod 都可以访问数据库
- 无法限制:无法阻止恶意流量
- 不符合最小权限原则
解决方案:NetworkPolicy
┌─────────────────────────────────────────┐
│ Kubernetes 集群 │
│ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │ Web │ │ API │ │ DB │ │
│ │ │─→│ │─→│ │ │
│ └───────┘ └───────┘ └───────┘ │
│ │ │ ↑ │
│ │ └──────────┘ │
│ │ 只有 API 可以访问 DB │
│ │ │
│ └──────────────────────────────────┘
│ Web 可以访问 API,不能访问 DB │
└─────────────────────────────────────────┘
NetworkPolicy 基本概念
NetworkPolicy 包含三个部分:
1. Pod 选择器:策略应用到哪些 Pod
2. 入站规则(Ingress):允许哪些流量进入
3. 出站规则(Egress):允许哪些流量出去
┌─────────────────────────────────────────┐
│ NetworkPolicy │
│ │
│ Pod 选择器:app=db │
│ │
│ 入站规则(Ingress): │
│ - 来源:app=api │
│ - 端口:5432 │
│ │
│ 出站规则(Egress): │
│ - 目标:app=logging │
│ - 端口:514 │
└─────────────────────────────────────────┘
NetworkPolicy 示例
# 基本的 NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-policy
namespace: default
spec:
podSelector: # 策略应用到的 Pod
matchLabels:
app: db
policyTypes: # 策略类型
- Ingress # 入站规则
- Egress # 出站规则
ingress: # 入站规则
- from:
- podSelector: # 允许来自哪些 Pod
matchLabels:
app: api
ports: # 允许的端口
- protocol: TCP
port: 5432
egress: # 出站规则
- to:
- podSelector: # 允许访问哪些 Pod
matchLabels:
app: logging
ports:
- protocol: TCP
port: 514
入站规则(Ingress)
# 入站规则配置
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ingress-policy
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
# 规则 1:允许来自同一 namespace 的 Pod
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
# 规则 2:允许来自特定 namespace 的 Pod
- from:
- namespaceSelector:
matchLabels:
env: production
ports:
- protocol: TCP
port: 80
# 规则 3:允许来自特定 IP 范围
- from:
- ipBlock:
cidr: 10.0.0.0/8
except:
- 10.0.1.0/24
ports:
- protocol: TCP
port: 80
出站规则(Egress)
# 出站规则配置
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: egress-policy
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Egress
egress:
# 规则 1:允许访问 DNS
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# 规则 2:允许访问特定 Pod
- to:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 8080
# 规则 3:允许访问外部服务
- to:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- protocol: TCP
port: 443
策略组合
# 完整的网络策略示例
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: comprehensive-policy
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
# 允许 Web 访问
- from:
- podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 8080
# 允许 Health Check
- from: [] # 空 from 表示允许所有来源
ports:
- protocol: TCP
port: 8080
egress:
# 允许访问数据库
- to:
- podSelector:
matchLabels:
app: db
ports:
- protocol: TCP
port: 5432
# 允许访问 DNS
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
默认策略
# 默认拒绝所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {} # 应用到所有 Pod
policyTypes:
- Ingress
# 没有 ingress 规则 = 拒绝所有入站
# 默认拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
# 没有 egress 规则 = 拒绝所有出站
# 默认拒绝所有流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
策略优先级
NetworkPolicy 优先级规则:
1. 如果没有 NetworkPolicy 应用到 Pod → 允许所有流量
2. 如果有 NetworkPolicy 应用到 Pod → 只允许明确允许的流量
3. 多个 NetworkPolicy 取并集
示例:
┌─────────────────────────────────────────┐
│ Policy A:允许 Web 访问 API │
│ Policy B:允许 Health Check 访问 API │
│ │
│ 结果:Web 和 Health Check 都可以访问 │
└─────────────────────────────────────────┘
实践练习
练习 1:创建默认拒绝策略
# 默认拒绝所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
# 应用策略
kubectl apply -f default-deny-ingress.yaml
# 测试:应该无法访问
kubectl run test-pod --image=busybox --rm -it -- wget -qO- http://web-service
练习 2:允许特定 Pod 访问
# 允许 frontend 访问 backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
# 应用策略
kubectl apply -f allow-frontend-to-backend.yaml
# 测试:从 frontend 应该可以访问
kubectl exec frontend-pod -- wget -qO- http://backend-service:8080
# 测试:从其他 Pod 应该无法访问
kubectl run test-pod --image=busybox --rm -it -- wget -qO- http://backend-service:8080
练习 3:配置 DNS 访问
# 允许访问 DNS(重要!否则 Pod 无法解析域名)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# 应用策略
kubectl apply -f allow-dns.yaml
# 测试 DNS 解析
kubectl exec test-pod -- nslookup kubernetes.default
常见误解
1. NetworkPolicy 是默认启用的
错误理解:Kubernetes 默认启用 NetworkPolicy
正确理解:需要 CNI 插件支持
支持 NetworkPolicy 的 CNI:
- Calico
- Cilium
- Weave Net
不支持的 CNI:
- Flannel(默认)
- 基本的桥接网络
2. 没有 NetworkPolicy 就是不安全的
错误理解:没有 NetworkPolicy 一定不安全
正确理解:
NetworkPolicy 是 Pod 级别的网络隔离
还有其他安全措施:
- RBAC(权限控制)
- Pod Security Policy
- Service Mesh(如 Istio)
小结
| 要点 | 说明 |
|---|---|
| NetworkPolicy | 控制 Pod 网络访问 |
| 策略类型 | Ingress(入站)、Egress(出站) |
| 选择方式 | podSelector、namespaceSelector、ipBlock |
| 默认行为 | 没有策略 = 允许所有,有策略 = 只允许明确的 |
| 最佳实践 | 先默认拒绝,再按需允许 |
| 注意事项 | 需要 CNI 插件支持 |
练习编辑器
bash
Loading...