4. 网络策略基础:CiliumNetworkPolicy 与 CiliumClusterwideNetworkPolicy 的 CRD 定义与生效机制
Cilium 的网络策略模型基于 Kubernetes 的 NetworkPolicy 语义进行了深度扩展,通过两个核心 CRD(Custom Resource Definition)实现:CiliumNetworkPolicy(命名空间级别)与 CiliumClusterwideNetworkPolicy(集群级别)。理解这两个 CRD 的定义结构、字段语义以及生效机制,是掌握 Cilium 网络隔离与安全策略的基础。
4.1 两个 CRD 的定位与差异
| 特性 | CiliumNetworkPolicy (CNP) | CiliumClusterwideNetworkPolicy (CCNP) |
|---|---|---|
| 作用域 | 仅作用于特定命名空间 | 作用于整个集群,跨所有命名空间 |
| 资源名称 | ciliumnetworkpolicies.cilium.io |
ciliumclusterwidenetworkpolicies.cilium.io |
| Endpoint 选择器 | 默认限定在策略所在命名空间 | 可跨命名空间选择 Pod/Service |
| 典型场景 | 微服务间细粒度隔离、租户内策略 | 全局基线策略、DNS 规则、监控/日志组件白名单 |
| 优先级 | 与 CCNP 共同生效,无显式优先级 | 与 CNP 共同生效,无显式优先级 |
关键理解:CNP 是命名空间隔离的“租户内策略”,CCNP 是集群管理员定义的“全局护栏”。两者在 Cilium Agent 内部被统一处理为 Endpoint 策略,不存在覆盖关系,而是叠加生效。
4.2 CRD 定义结构解析
两个 CRD 共享相同的核心 Spec 结构,仅顶层元数据不同。以下以 CiliumNetworkPolicy 为例展示其 YAML 定义骨架:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-http-allow
namespace: production
spec:
description: "Allow HTTP GET to /api/v1 from frontend"
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1"
egress:
- toEndpoints:
- matchLabels:
app: database
toPorts:
- ports:
- port: "5432"
protocol: TCP
4.2.1 核心字段说明
- endpointSelector:必填字段,通过 LabelSelector 选择策略作用的 Pod 集合。CNP 中仅匹配当前命名空间的 Pod;CCNP 中可跨命名空间匹配。
- ingress / egress:分别定义入站和出站规则。每个规则块内可包含:
fromEndpoints / toEndpoints:基于 Label 的端点选择器fromCIDR / toCIDR:基于 IP 段的规则(适用于外部流量)toPorts:端口与协议定义,支持 L3/L4 以及 L7 规则toFQDNs:基于 DNS 名称的出站规则(需开启 DNS 代理)
- enableDefaultDeny:隐式行为。一旦为某个方向(ingress/egress)定义了规则,Cilium 会自动为该方向添加默认拒绝规则,未匹配的流量将被丢弃。
4.3 生效机制:从 CRD 到 BPF 映射
Cilium 网络策略的生效并非简单的 YAML 解析,而是经过多层转换最终生成 BPF 映射中的键值对。下图展示了完整的策略生效链路:
4.4 策略生效的原子操作:Identity 与 Selector 解析
Cilium 不直接使用 Pod IP 或命名空间作为策略匹配依据,而是引入 Security Identity 概念。每个 Pod 根据其标签组合被分配一个 24 位整数 Identity。策略中的 endpointSelector 和 fromEndpoints 最终被解析为 Identity 集合,写入 BPF Policy Map。
Identity 分配示例:
Pod 标签
Pod 标签
策略规则
Pod 标签
app=frontend, version=v2 → Identity 1678Pod 标签
app=backend → Identity 2345策略规则
fromEndpoints: {matchLabels: {app: frontend}} → 允许 Identity 1678 的流量
4.4.1 策略合并与冲突处理
当多个 CNP/CCNP 作用于同一个 Endpoint 时,Cilium 采用以下合并规则:
- 同一方向(ingress/egress)的规则取并集:只要任意一个策略允许某流量,该流量即被允许。
- 默认拒绝是隐式的:一旦有规则定义,未显式允许的流量被拒绝。若完全没有规则,则默认允许所有流量(与 Kubernetes 原生 NetworkPolicy 行为一致)。
- L7 规则与 L3/L4 规则共存:L7 规则是 L3/L4 规则的超集,必须先通过 L3/L4 检查,再进入 L7 代理进行 HTTP/gRPC 方法匹配。
4.5 实战:编写一个典型的 CNP 与 CCNP 组合
以下示例展示如何通过 CNP 实现微服务隔离,同时通过 CCNP 设置全局 DNS 白名单:
# CNP:只允许 frontend 访问 backend 的 8080 端口
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: backend-ingress
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
---
# CCNP:所有命名空间的 Pod 只能解析内部 DNS
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: global-dns-egress
spec:
endpointSelector: {} # 匹配所有 Pod
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- toFQDNs:
- matchName: "*.internal.example.com"
注意:CCNP 中使用
endpointSelector: {} 表示匹配集群中所有 Pod。这种全局策略应谨慎使用,避免意外阻断关键系统组件通信。建议先使用 matchLabels 限定范围,验证后再放宽。
4.6 策略生效验证与调试
部署策略后,可通过以下命令验证其是否按预期生效:
# 查看特定 Pod 的详细策略状态
kubectl exec -n kube-system cilium-xxxxx -- cilium endpoint list
# 查看某个 Endpoint 的 Identity 和关联策略
kubectl exec -n kube-system cilium-xxxxx -- cilium endpoint get 1234
# 实时跟踪策略匹配情况(需开启 monitor)
kubectl exec -n kube-system cilium-xxxxx -- cilium monitor --type policy-verdict
通过 cilium monitor 输出的策略判决日志,可以快速定位流量被允许或拒绝的原因,结合 Identity 编号反查标签,是调优网络策略的核心手段。