Kubernetes-NetworkPolicy
Kubernetes NetworkPolicy 是 Kubernetes 中用于控制 Pod 间网络通信的核心安全机制,它通过声明式规则实现精细的网络流量控制。
核心概念与工作原理
定义与功能
NetworkPolicy 是 Kubernetes 中定义网络流量规则的资源对象,它能够在 IP 地址或端口级别(OSI 第 3 层或第 4 层)精细控制 Pod 之间的网络通信。
- 流量控制:限制哪些 Pod 允许与其他 Pod 通信,或者限制外部访问 Pod
- 增强安全性:通过定义网络策略,减少潜在的攻击面
- 多租户支持:在多租户环境中隔离不同租户的流量
默认行为与隔离模型
Kubernetes 网络策略遵循特定的默认行为和隔离原则:
默认允许:未定义任何策略时,所有 Pod 可自由通信(取决于网络插件实现)
默认拒绝:一旦为 Pod 创建 NetworkPolicy:
- 若定义了
policyTypes: ["Ingress"]且无 ingress 规则,则所有入站流量被拒绝 - 若定义了
policyTypes: ["Egress"]且无 egress 规则,则所有出站流量被拒绝
- 若定义了
叠加原则:多个策略的效果是叠加的,不会互相覆盖
双向验证:连接必须同时满足源 Pod 的出口策略和目标 Pod 的入口策略
实现机制与前提条件
网络插件要求:集群必须使用支持 NetworkPolicy 的 CNI 插件(如 Calico、Cilium、Weave Net 等),Flannel 不支持此功能
策略执行流程:
标签匹配:根据 podSelector 确定策略作用的 Pod
流量分类:区分入站(进入目标 Pod)和出站(从目标 Pod 发出)流量
规则评估:按顺序匹配 ingress 或 egress 规则,首个匹配规则决定流量命运
资源清单结构
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: my-app-network-policy # 策略名称
namespace: production # 应用的目标命名空间
spec:
podSelector:
matchLabels:
app: my-app # 选择要应用策略的Pod标签
policyTypes:
- Ingress # 控制入站流量
- Egress # 控制出站流量(可选)
ingress:
- from: # 允许的入站流量来源
- podSelector: # 来自同一命名空间的特定Pod
matchLabels:
role: frontend
- namespaceSelector: # 来自特定命名空间
matchLabels:
env: staging
- ipBlock: # 来自特定IP段
cidr: 192.168.1.0/24
except: # 排除的IP
- 192.168.1.100/32
ports: # 允许的端口和协议
- protocol: TCP
port: 80
- protocol: UDP
port: 53
egress: # 出站规则(可选)
- to: # 允许的出站目标
- ipBlock:
cidr: 10.0.0.0/8
ports:
- protocol: TCP
port: 443NetworkPolicy 规则类型
策略方向类型
- 入口隔离(Ingress Isolation):控制哪些流量可以进入 Pod
- 默认情况下,Pod 允许所有入站连接
- 当有 NetworkPolicy 选择 Pod 并包含 "Ingress" policyType 时,Pod 被隔离为入口
- 出口隔离(Egress Isolation):控制 Pod 可以发出哪些流量
- 默认情况下,Pod 允许所有出站连接
- 当有 NetworkPolicy 选择 Pod 并包含 "Egress" policyType 时,Pod 被隔离为出口
选择器类型
Pod 选择器
匹配当前命名空间中的特定 Pod
podSelector:
matchLabels:
app: backend命名空间选择器
匹配特定命名空间中的所有 Pod
namespaceSelector:
matchLabels:
env: productionIP 块选择器
匹配特定的 CIDR 范围
ipBlock:
cidr: 192.168.1.0/24组合选择器
同时使用命名空间和 Pod 选择器
- namespaceSelector:
matchLabels:
user: alice
podSelector:
matchLabels:
role: client经典案例
NetworkPolicy 在 Kubernetes 集群中有多种应用场景,以下是生产环境中常见的用例和对应配置。
默认网络隔离策略
场景:实现集群级别的默认拒绝策略,然后逐步开放必要通信
# 拒绝所有入站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
# 拒绝所有出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
spec:
podSelector: {}
policyTypes:
- Egress
# 允许所有入站流量(恢复默认)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-ingress
spec:
podSelector: {}
ingress:
- {}
policyTypes:
- Ingress微服务间通信控制
场景:在微服务架构中限制服务间的访问权限
# 只允许前端访问后端服务
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80
# 允许后端访问数据库
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-db
spec:
podSelector:
matchLabels:
app: database
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 3306多租户环境隔离
场景:在共享集群中隔离不同团队或环境(如 dev/prod)
# 禁止开发环境访问生产环境
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-dev-to-prod
namespace: prod
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
environment: dev敏感服务保护
场景:对数据库、密钥管理等敏感服务进行严格隔离
# 只允许特定应用访问数据库
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: protect-db
spec:
podSelector:
matchLabels:
role: database
ingress:
- from:
- podSelector:
matchLabels:
app: payment
ports:
- protocol: TCP
port: 5432出站流量控制
场景:限制 Pod 只能访问特定的外部服务或网络
# 限制Pod只能访问特定CIDR
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-egress
spec:
podSelector:
matchLabels:
app: external-service
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 443跨命名空间通信
场景:控制不同命名空间间的 Pod 通信
# 允许monitoring命名空间访问app命名空间的应用
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-monitoring-to-app
namespace: app
spec:
podSelector:
matchLabels:
app: myapp
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring