3. Kubernetes 网络策略回顾:NetworkPolicy 资源定义、Pod 选择器、Ingress/Egress 规则

在深入 Cilium 网络策略之前,必须牢固掌握 Kubernetes 原生 NetworkPolicy 的设计哲学与核心机制。Kubernetes 网络策略是一种以应用为中心(Application-Centric)的声明式防火墙规则,它通过标签选择器(Label Selector)动态匹配 Pod,并基于四层(L3/L4)协议与端口控制流量。本节将系统回顾其资源定义结构、Pod 选择器的工作模式以及 Ingress/Egress 规则的配置逻辑。

3.1 NetworkPolicy 资源定义结构

一个标准的 NetworkPolicy 资源由 spec 中的三个核心字段构成:podSelector、policyTypes、以及 ingress/egress 规则数组。以下是一个同时定义了入站与出站规则的完整示例:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-allow-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend-api
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend-web
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432

下表总结了各字段的语义与约束:

字段 类型 说明
podSelector LabelSelector 必填。选择策略所作用的 Pod 集合。空选择器({})匹配命名空间下所有 Pod。
policyTypes []PolicyType 可选。显式声明策略生效方向。若省略,默认根据规则存在情况推断:有 ingress 规则则包含 Ingress,有 egress 规则则包含 Egress。
ingress []IngressRule 可选。入站白名单规则列表。每个规则包含 from(来源选择器)和 ports(目标端口)。
egress []EgressRule 可选。出站白名单规则列表。每个规则包含 to(目标选择器)和 ports(目标端口)。
关键原则:Kubernetes NetworkPolicy 采用“默认拒绝,显式允许”模型。一旦命名空间中存在任何一条 NetworkPolicy 匹配到某个 Pod,该 Pod 的未匹配流量将被隐式拒绝。空规则(ingress: [] 或 egress: [])意味着拒绝所有对应方向的流量。

3.2 Pod 选择器:标签驱动的动态匹配

Pod 选择器是 NetworkPolicy 的“寻址”核心。它使用 Kubernetes 标签选择器语法,支持两种匹配模式:

  • matchLabels:精确匹配。要求目标 Pod 必须包含所有指定的标签键值对。
  • matchExpressions:表达式匹配。支持 In、NotIn、Exists、DoesNotExist 四种操作符,用于更复杂的集合运算。

选择器可以出现在三个位置,分别控制不同的作用域:

  1. spec.podSelector:定义“谁”被策略保护(目标 Pod)。
  2. ingress[].from[].podSelector:定义“谁”可以访问目标 Pod(来源 Pod)。
  3. egress[].to[].podSelector:定义目标 Pod 可以访问“谁”(目的 Pod)。
命名空间隔离:默认情况下,podSelector 仅在当前 NetworkPolicy 所在的命名空间内生效。如果需要跨命名空间匹配,必须使用 namespaceSelector 或 ipBlock。

以下 SVG 图展示了 Pod 选择器在 Ingress 规则中的匹配流程:

Pod 选择器在 Ingress 规则中的匹配流程 Pod 选择器 Ingress 匹配流程 来源 Pod app: frontend-web (标签匹配) Ingress 规则 from.podSelector matchLabels 目标 Pod app: backend-api (spec.podSelector) 匹配逻辑 来源 Pod 标签必须完全匹配 from.podSelector; 目标 Pod 标签必须完全匹配 spec.podSelector。

3.3 Ingress 规则:入站流量控制

Ingress 规则定义允许哪些来源(from)访问目标 Pod 的哪些端口(ports)。from 字段是一个数组,支持四种来源选择器类型,它们之间是 OR 逻辑:

来源类型 字段 作用域 示例
Pod 选择器 podSelector 同命名空间 允许来自 app=frontend 的 Pod
命名空间选择器 namespaceSelector 跨命名空间 允许来自 env=staging 命名空间的所有 Pod
命名空间 + Pod 组合 namespaceSelector + podSelector 跨命名空间 + 精确 Pod 允许来自 env=prod 命名空间中 app=monitor 的 Pod
IP 段 ipBlock 集群外部或 CIDR 允许来自 10.0.0.0/16 的流量
注意:ipBlock 不经过 Kubernetes 标签系统,直接基于 IP 地址匹配。在动态容器环境中,Pod IP 会频繁变化,因此 ipBlock 通常用于控制集群外部流量或与裸金属设备通信,不推荐用于 Pod 间策略。

3.4 Egress 规则:出站流量控制

Egress 规则定义目标 Pod 允许访问哪些目的地(to)以及使用哪些端口。to 字段的语法与 from 完全对称,同样支持四种目标选择器类型,且多个条目之间为 OR 逻辑。

以下是一个典型的 Egress 规则示例,允许 app=backend-api 的 Pod 访问 app=database 的 Pod 的 5432 端口,同时允许访问集群外部 DNS 服务:

spec:
  podSelector:
    matchLabels:
      app: backend-api
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except:
        - 10.0.0.0/8
    ports:
    - protocol: UDP
      port: 53

以下 SVG 图对比了 Ingress 与 Egress 规则在 Pod 视角下的流量方向:

Ingress 与 Egress 规则流量方向对比 Ingress 与 Egress 规则流量方向 Ingress 规则 入站流量控制 来源 Pod 目标 Pod from + ports Egress 规则 出站流量控制 来源 Pod 目标 Pod to + ports 核心区别 Ingress:谁可以访问我? Egress:我可以访问谁?

3.5 策略生效规则与常见陷阱

理解以下生效规则对于编写正确的 NetworkPolicy 至关重要:

  • 默认拒绝:一旦命名空间中存在任何一条 NetworkPolicy 匹配到某个 Pod,该 Pod 的未显式允许的流量将被拒绝。如果命名空间中没有任何 NetworkPolicy,则所有 Pod 的流量默认全部允许。
  • 规则叠加(AND/OR):同一 NetworkPolicy 内的多个 from 或 to 条目是 OR 关系;多条 NetworkPolicy 作用于同一个 Pod 时,规则之间也是 OR 关系——只要有一条策略允许,流量即被放行。
  • 空选择器:podSelector: {} 匹配命名空间下所有 Pod。这在隔离整个命名空间时非常有用。
  • 端口必须显式声明:如果 ports 字段未指定,则规则匹配所有端口。一旦指定了端口,则只匹配指定端口。
控制面授权测试启示:在控制面授权测试中,NetworkPolicy 的“默认拒绝”特性是验证最小权限原则的基础。测试用例应覆盖:未匹配策略的 Pod 是否被正确拒绝、多条策略叠加时的预期行为、以及跨命名空间选择器是否按预期生效。