3. 策略规则详解:规则结构、from/to字段、端口与协议匹配、IPBlock使用
NetworkPolicy 的核心在于其规则(Rules)的定义。一个策略可以包含多个入站(Ingress)和出站(Egress)规则,每条规则精确描述了允许哪些流量通过。理解规则的结构、from/to 字段的语义、端口与协议的匹配方式以及 IPBlock 的使用场景,是编写高效、安全的多租户网络策略的基础。
3.1 规则结构总览
一个完整的 NetworkPolicy 规则由 podSelector(选择目标 Pod)、policyTypes(策略类型)以及 ingress/egress 规则数组组成。每条规则内部,通过 from(入站)或 to(出站)字段定义流量来源或目的地,通过 ports 字段定义目标端口和协议。
核心规则结构(YAML 示例):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: multi-tenant-api-policy
namespace: tenant-a
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
- Egress
ingress:
- from: # 入站规则:允许来自...
- namespaceSelector:
matchLabels:
tenant: tenant-b # 租户B命名空间
podSelector:
matchLabels:
app: frontend # 且标签为 app=frontend 的 Pod
ports:
- protocol: TCP
port: 8080
egress:
- to: # 出站规则:允许去往...
- ipBlock:
cidr: 10.0.0.0/16
except:
- 10.0.1.0/24
ports:
- protocol: TCP
port: 443
3.2 from / to 字段:流量方向与选择器
from(入站规则中)和 to(出站规则中)字段是规则的核心,它们定义了流量的“源”或“目标”。这两个字段支持四种选择器类型,可以组合使用(逻辑 OR 关系)。
| 选择器类型 | 字段名 | 作用范围 | 匹配逻辑 |
|---|---|---|---|
| podSelector | podSelector |
当前命名空间 | 匹配同一命名空间内具有指定标签的 Pod |
| namespaceSelector | namespaceSelector |
整个集群 | 匹配具有指定标签的命名空间内的所有 Pod |
| namespaceSelector + podSelector | 两者同时使用 | 跨命名空间 | 匹配指定命名空间内具有指定标签的 Pod(逻辑 AND) |
| ipBlock | ipBlock |
集群外部或 CIDR | 匹配指定的 IP 地址范围(CIDR),可设置例外 |
多租户最佳实践: 在跨租户访问控制中,优先使用
namespaceSelector 结合 podSelector 的组合。这比单独使用 ipBlock 更安全、更动态,因为 Pod IP 会变化,而命名空间标签是稳定的。
3.3 端口与协议匹配
ports 字段是一个数组,用于指定规则所允许的目标端口和传输层协议。如果不指定 ports,则规则会匹配所有端口。
- protocol:支持
TCP、UDP、SCTP。默认值为TCP。 - port:可以是整数端口号(如
8080),也可以是命名的端口名称(如http),该名称需与 Pod 的容器端口定义中的name字段一致。 - endPort(Kubernetes v1.21+):用于指定一个端口范围,与
port配合使用,表示从port到endPort的闭区间。
性能陷阱: 避免在一条规则中定义大量离散的端口。如果端口范围连续,请使用
endPort 字段;如果端口不连续,应拆分为多条规则。过多的端口条目会导致内核 iptables/nftables 规则膨胀,增加延迟。
# 端口匹配示例
ports:
- protocol: TCP
port: 80
- protocol: UDP
port: 53
- protocol: TCP
port: 30000
endPort: 32767 # 匹配 NodePort 范围
3.4 IPBlock 使用与注意事项
IPBlock 用于匹配集群外部的 IP 地址,或者集群内部无法通过标签选择器精确匹配的 IP 范围。它通过 CIDR 表示法定义,并支持 except 字段排除特定子网。
IPBlock 典型使用场景:
- 允许来自公司 VPN 出口 IP(如
203.0.113.0/24)的访问。 - 允许访问外部数据库服务(如云 RDS 的 IP 段)。
- 禁止访问已知的恶意 IP 段。
# 允许访问外部监控服务,但排除内部测试网段
egress:
- to:
- ipBlock:
cidr: 10.100.0.0/16
except:
- 10.100.1.0/24
- 10.100.2.0/24
ports:
- protocol: TCP
port: 9090
关键限制: 在
from 或 to 字段中,ipBlock 不能与 podSelector 或 namespaceSelector 混合使用于同一个选择器条目内。它们必须位于不同的数组元素中。例如,不能写 from: [{ ipBlock: ..., podSelector: ... }],而应写为 from: [{ ipBlock: ... }, { podSelector: ... }],这表示逻辑 OR。
3.5 规则组合逻辑与可视化
理解规则之间的逻辑关系至关重要:
- 规则内选择器之间:
from/to数组中的多个元素是 OR 关系。 - 规则内选择器内部:
namespaceSelector和podSelector同时出现时是 AND 关系。 - 多条规则之间:
ingress/egress数组中的多条规则是 OR 关系。
下图展示了一个典型的多租户场景中,入站规则如何组合选择器来精确控制流量来源。
3.6 多租户策略规则设计清单
在设计多租户 NetworkPolicy 规则时,请参考以下清单以避免常见错误:
| 检查项 | 说明 | 推荐做法 |
|---|---|---|
| 选择器粒度 | 避免使用过于宽泛的 namespaceSelector(无标签) |
始终为命名空间打上租户标签,并使用标签选择器 |
| 端口范围 | 大量离散端口导致规则膨胀 | 使用 endPort 或拆分为多条规则 |
| IPBlock 例外 | 忘记设置 except 导致意外放行 |
明确排除内部已知的敏感子网 |
| 规则顺序 | NetworkPolicy 规则之间是 OR 关系,顺序无关 | 无需关注规则顺序,但建议按功能分组 |
| 默认拒绝 | 未匹配任何规则的流量默认被拒绝 | 先创建一条“允许所有”的基线策略,再逐步收紧 |