一、什么是 NetworkPolicy?
NetworkPolicy 是 Kubernetes 中的一种资源对象,用于定义 Pod 之间的网络通信规则。简单来说,它就像集群内部的 "防火墙",可以精确控制:
- 哪些 Pod 可以访问目标 Pod(入站流量,Ingress)
- 目标 Pod 可以访问哪些 Pod 或外部网络(出站流量,Egress)
- 允许通信的协议和端口范围
通过这种细粒度的控制,我们可以有效防止未经授权的访问,减少网络攻击面,提高集群的整体安全性。
二、NetworkPolicy 的核心原理
要理解 NetworkPolicy 的工作机制,需要掌握以下几个核心概念:
-
Pod 选择器(PodSelector) 通过标签(Label)选择特定的 Pod 群体,作为网络策略的 "作用对象"。例如,
matchLabels: {app: backend}表示策略仅作用于带有app=backend标签的 Pod。 -
命名空间选择器(namespaceSelector) 通过命名空间的标签选择特定命名空间,用于控制跨命名空间的通信。例如,
namespaceSelector: {matchLabels: {project: myproject}}表示仅允许来自带有project=myproject标签的命名空间的流量。 -
Ingress 规则定义允许进入 "作用对象 Pod" 的流量规则,包括来源(如其他 Pod、IP 网段)、协议和端口。
-
Egress 规则定义允许 "作用对象 Pod" 发出的流量规则,包括目标(如其他 Pod、IP 网段)、协议和端口。
-
**Peer Pod(对等 Pod)**规则中定义的通信对方 Pod,通过 PodSelector 或 namespaceSelector 指定,是 NetworkPolicy 规则的核心匹配目标。
三、NetworkPolicy 资源清单详解
一个完整的 NetworkPolicy 资源清单结构如下,我们通过示例解析关键字段:
yaml
apiVersion: networking.k8s.io/v1 # 固定API版本
kind: NetworkPolicy # 资源类型
metadata:
name: test-network-policy # 策略名称
namespace: default # 策略作用的命名空间(仅对该命名空间有效)
spec:
podSelector: # 选择作用对象Pod
matchLabels:
app: backend # 仅作用于带有app=backend标签的Pod
ingress: # 入站规则
- from: # 允许的来源
- podSelector: # 来源为带有app=frontend标签的Pod
matchLabels:
app: frontend
- ipBlock: # 来源为192.168.1.0/24网段
cidr: 192.168.1.0/24
ports: # 允许的端口和协议
- protocol: TCP
port: 8080 # 仅允许访问8080端口
egress: # 出站规则
- to: # 允许访问的目标
- podSelector: # 目标为带有app=database标签的Pod
matchLabels:
app: database
ports: # 允许的端口和协议
- protocol: TCP
port: 3306 # 仅允许通过3306端口访问
spec.policyTypes:可选字段,指定策略是否包含 Ingress、Egress 规则(默认根据是否定义 Ingress/Egress 自动推断)。ipBlock:用于指定 IP 网段(支持cidr和except排除网段),适合控制与集群外部的通信。
四、实用场景示例
以下是几个常见的 NetworkPolicy 配置场景,帮助理解如何在实际环境中应用。
场景 1:允许同一命名空间内的 Pod 通信
当需要限制 Pod 仅与同命名空间内的其他 Pod 通信时,可通过namespaceSelector匹配当前命名空间的标签:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
spec:
podSelector:
matchLabels:
app: myapp # 作用于带有app=myapp标签的Pod
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector: # 允许来自带有project=myproject标签的命名空间
matchLabels:
project: myproject
egress:
- to:
- namespaceSelector: # 允许访问带有project=myproject标签的命名空间
matchLabels:
project: myproject
注意 :需提前为命名空间添加project=myproject标签(如kubectl label ns default project=myproject)。
场景 2:限制敏感 Pod 的外部访问
对于敏感应用(如数据库),可能需要禁止其与集群外部通信,仅允许 Pod 间内部访问:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-external-traffic
spec:
podSelector:
matchLabels:
app: sensitive-app # 作用于敏感应用Pod
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector: {} # 允许所有内部Pod访问(空选择器匹配所有Pod)
egress:
- to:
- podSelector: {} # 允许访问所有内部Pod
podSelector: {}表示匹配当前命名空间内的所有 Pod,因此该策略会禁止敏感 Pod 访问集群外部网络。
场景 3:限制特定端口的访问
对于前端服务,可能仅需要开放 80(HTTP)和 53(DNS)端口:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-specific-ports
spec:
podSelector:
matchLabels:
app: frontend # 作用于前端Pod
ingress:
- ports: # 仅允许指定端口的入站流量
- protocol: TCP
port: 80 # 允许TCP 80端口
- protocol: UDP
port: 53 # 允许UDP 53端口(DNS解析)
场景 4:允许访问外部网络但禁止跨命名空间通信
需让myns1命名空间中app=alpine的 Pod 既能与同命名空间 Pod 通信,又能访问外部网络,但禁止与其他命名空间通信:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: alpine-communication-policy
namespace: myns1 # 仅作用于myns1命名空间
spec:
podSelector:
matchLabels:
app: alpine # 作用对象:app=alpine的Pod
policyTypes:
- Ingress
- Egress
# 入站:仅允许myns1内的Pod访问
ingress:
- from:
- podSelector: {} # 匹配myns1内所有Pod
# 出站:允许同命名空间Pod和外部网络,排除其他命名空间
egress:
# 允许访问myns1内所有Pod
- to:
- podSelector: {}
# 允许访问外部网络(排除集群内部CIDR)
- to:
- ipBlock:
cidr: 0.0.0.0/0 # 允许所有IPv4地址
except: # 排除集群内部网段(需根据实际集群调整)
- 10.244.0.0/16 # Pod CIDR示例
- 10.96.0.0/12 # Service CIDR示例
# 允许DNS解析(否则无法访问外部域名)
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system # kube-dns所在命名空间
podSelector:
matchLabels:
k8s-app: kube-dns # kube-dns的Pod标签
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
五、高级用法
NetworkPolicy 还支持更复杂的配置,满足多样化的网络控制需求:
1. 策略的 "叠加" 效果
Kubernetes 中多个 NetworkPolicy 可以同时作用于同一 Pod,最终规则为所有策略的 "并集"。例如:
- 一个策略允许来自
role=frontend的 Pod 访问 - 另一个策略允许来自
role=middleware的 Pod 访问最终目标 Pod 会允许来自frontend和middleware的所有访问。
2. 复杂的 Peer 选择器
通过matchExpressions定义更灵活的标签匹配规则,例如允许role为frontend或middleware的 Pod 访问:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: advanced-selector-matching
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchExpressions:
- key: role
operator: In
values: [frontend, middleware] # 匹配role为frontend或middleware的Pod
六、总结
NetworkPolicy 是 Kubernetes 集群网络安全的核心工具,通过定义精细的 Pod 通信规则,能够有效隔离不同应用、限制访问范围,降低网络攻击风险。在实际使用中,需注意:
- 策略仅对匹配标签的 Pod 生效,未匹配的 Pod 不受限制(除非有默认拒绝策略)
- 入站 / 出站规则默认 "拒绝所有",仅允许明确配置的流量
- 需结合集群实际的 Pod/Service CIDR 配置外部访问规则,避免误阻断内部通信