3. CiliumNetworkPolicy 核心概念:策略作用域、标签选择器与默认拒绝

在 Cilium 的零信任安全模型中,理解策略的作用域、标签选择器机制以及默认拒绝原则是编写可排查策略的基础。本章将拆解这三个核心概念,并展示它们如何共同构成 Cilium 网络策略的骨架。

3.1 策略作用域:Ingress 与 Egress

CiliumNetworkPolicy 通过 spec.ingress 和 spec.egress 两个独立字段定义流量方向。每个方向都是一个规则列表,规则之间是 OR 关系(满足任意一条即放行)。

作用域 方向 控制对象 典型场景
Ingress 入站 谁可以访问当前 Pod 只允许 frontend 访问 backend
Egress 出站 当前 Pod 可以访问谁 只允许 backend 访问数据库
排查要点: 当流量被拒绝时,首先确认策略是作用于 Ingress 还是 Egress。使用 cilium monitor -t drop 查看丢弃事件中的方向标识。

3.2 标签选择器机制:身份识别的核心

Cilium 不使用传统 IP 或 CIDR 作为策略主体,而是使用 Kubernetes 标签选择器。每个 Pod 的标签集合决定了它的安全身份。策略通过 matchLabels 和 matchExpressions 选择目标端点。

  • fromEndpoints / toEndpoints:基于标签选择源或目标 Pod。
  • fromRequires / toRequires:强制要求所有匹配的端点必须同时满足额外标签(用于多租户隔离)。
  • fromNodes / toNodes:基于节点标签选择(适用于节点级控制)。
  • fromCIDR / toCIDR:用于与集群外部通信(非 Kubernetes 端点)。
故障排查黄金法则: 如果策略未生效,90% 的原因是标签选择器写错了。使用 kubectl get pods --show-labels 验证目标 Pod 的标签是否与策略中的 matchLabels 完全匹配。

3.3 默认拒绝原则

Cilium 的默认行为是 白名单模式:一旦任何 CiliumNetworkPolicy 应用到某个 Pod,该 Pod 的所有流量(Ingress 和 Egress)都会被默认拒绝,除非显式放行。这是实现零信任网络的基础。

  • 隐式拒绝:未匹配任何规则的流量被丢弃。
  • 显式放行:必须编写规则明确允许特定流量。
  • 策略优先级:Cilium 不支持传统防火墙的优先级数字。所有规则是 累加且非冲突 的——只要有一条规则允许,流量即通过;只要没有规则允许,流量即拒绝。
常见陷阱: 很多工程师误以为“没有策略就是允许”。在 Cilium 中,没有策略 = 默认拒绝(仅针对被策略选中的 Pod)。未被任何策略选中的 Pod 仍然可以自由通信,直到第一个策略应用。

3.4 核心概念关系图

下图展示了策略作用域、标签选择器与默认拒绝之间的逻辑关系:

CiliumNetworkPolicy 核心概念关系图 CiliumNetworkPolicy 核心概念关系 CiliumNetworkPolicy Ingress(入站) Egress(出站) 标签选择器 标签选择器 默认拒绝(隐式) 默认拒绝(隐式) 显式放行规则 → 允许通过

3.5 策略优先级与规则合并

Cilium 的策略模型是 非抢占式 的。多个策略可以同时作用于同一个 Pod,所有规则被合并处理。合并规则如下:

场景 合并结果 示例
策略 A 允许 Ingress 允许 策略 A 允许来自 app=frontend 的流量
策略 B 拒绝 Ingress 允许(Cilium 无拒绝规则) 策略 B 无法覆盖策略 A 的允许
策略 A 允许,策略 C 允许不同源 两个源都允许 来自 app=frontend 和 app=monitor 的流量均放行
无策略匹配 默认拒绝 流量被丢弃
排查技巧: 使用 kubectl describe cnp <policy-name> 查看策略的 Status 字段。如果 Enforcing: true,说明策略已生效。使用 cilium endpoint list 查看每个端点的策略摘要。

3.6 标签选择器匹配流程

下图展示了当流量到达 Pod 时,Cilium 如何通过标签选择器决定是否放行:

标签选择器匹配流程 标签选择器匹配流程 流量到达 Pod 检查是否有策略选中该 Pod? 有策略 → 匹配标签选择器 无策略 → 默认允许(未锁定) 匹配成功 → 放行 匹配失败 → 默认拒绝

3.7 实战排查清单

  1. 确认策略是否应用:kubectl get cnp -n <namespace> 查看策略列表。
  2. 确认标签是否匹配:kubectl get pods -n <namespace> --show-labels 对比策略中的 matchLabels。
  3. 确认作用域方向:检查被拒绝的流量是 Ingress 还是 Egress,对应查看策略中的 fromEndpoints 或 toEndpoints。
  4. 确认默认拒绝是否生效:如果 Pod 有策略但流量被拒,检查是否有显式放行规则。
  5. 使用 Hubble 可视化:hubble observe -n <namespace> --verdict DROPPED 查看丢弃流量的具体原因。
关键提醒: 标签选择器是大小写敏感的。Kubernetes 标签值中的空格、特殊字符都会导致匹配失败。建议在编写策略前,先使用 kubectl label --dry-run=client 验证标签语法。