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 关系。

下图展示了一个典型的多租户场景中,入站规则如何组合选择器来精确控制流量来源。

NetworkPolicy 入站规则选择器组合逻辑 目标 Pod (app: api-server) 规则 1 (OR) 来源: namespaceSelector (tenant: tenant-b) AND podSelector (app: frontend) 规则 2 (OR) 来源: ipBlock (203.0.113.0/24) except: 203.0.113.100/32 逻辑说明 规则 1 和规则 2 是 OR 关系:满足任一规则即允许流量。 规则 1 内部:namespaceSelector 与 podSelector 是 AND 关系。

3.6 多租户策略规则设计清单

在设计多租户 NetworkPolicy 规则时,请参考以下清单以避免常见错误:

检查项 说明 推荐做法
选择器粒度 避免使用过于宽泛的 namespaceSelector(无标签) 始终为命名空间打上租户标签,并使用标签选择器
端口范围 大量离散端口导致规则膨胀 使用 endPort 或拆分为多条规则
IPBlock 例外 忘记设置 except 导致意外放行 明确排除内部已知的敏感子网
规则顺序 NetworkPolicy 规则之间是 OR 关系,顺序无关 无需关注规则顺序,但建议按功能分组
默认拒绝 未匹配任何规则的流量默认被拒绝 先创建一条“允许所有”的基线策略,再逐步收紧