4. Cilium 高级网络策略:基于 FQDN、HTTP 方法、ServiceAccount 与 CIDR 的策略
在 Kubernetes 生产环境中,仅依赖传统的 IP 与端口(L3/L4)网络策略往往无法满足微服务架构下的精细化访问控制需求。Cilium 基于 eBPF 的数据路径允许在 L7 层和应用身份层执行策略,实现“零信任”网络模型。本章将深入解析四种高级策略类型:基于 FQDN 的出站策略、基于 HTTP 方法的 API 策略、基于 Kubernetes ServiceAccount 的身份策略,以及传统的 CIDR 策略。
4.1 基于 FQDN 的策略(Fully Qualified Domain Name)
传统 Kubernetes NetworkPolicy 无法直接通过域名控制出站流量,因为 Pod IP 是动态的。Cilium 的 FQDN 策略允许你使用域名(如 api.example.com)定义出站规则,Cilium 代理会实时解析 DNS 并动态更新 eBPF 映射表。
4.1.1 FQDN 策略工作原理
- DNS 嗅探: Cilium 代理通过 eBPF 程序监控 Pod 发出的 DNS 查询(UDP/53)。
- 域名缓存: 将解析出的 IP 地址与域名关联,并写入 eBPF Map,设置 TTL 过期时间。
- 策略匹配: 当 Pod 发起 TCP 连接时,eBPF 程序检查目标 IP 是否匹配已缓存的 FQDN 条目。
- 动态更新: 当 DNS 记录变更或 TTL 过期,Cilium 自动更新 eBPF 映射,无需重启 Pod。
4.1.2 FQDN 策略 YAML 示例
以下策略允许 frontend 命名空间中的 Pod 仅能访问 api.stripe.com 和 s3.amazonaws.com,并拒绝所有其他外部流量。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "fqdn-egress-external"
namespace: frontend
spec:
endpointSelector:
matchLabels:
app: web-frontend
egress:
- toFQDNs:
- matchName: "api.stripe.com"
- matchPattern: "*.s3.amazonaws.com"
- toEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": kube-system
toPorts:
- ports:
- port: "53"
protocol: UDP
rules:
dns:
- matchPattern: "*"
toPorts 中的 UDP 53),否则 Cilium 无法解析域名,策略将失效。建议使用 matchPattern: "*" 允许所有 DNS 查询,或限制到特定 DNS 服务器。
4.1.3 FQDN 策略对比表
| 特性 | matchName | matchPattern |
|---|---|---|
| 匹配方式 | 精确域名匹配 | 通配符前缀匹配(Glob 模式) |
| 示例 | api.stripe.com |
*.s3.amazonaws.com |
| 性能 | 高(哈希查找) | 中(模式匹配) |
| 适用场景 | 固定域名,如内部 API | 多子域名,如 CDN、云存储 |
4.2 基于 HTTP 方法的策略(L7 协议感知)
Cilium 通过代理模式(Envoy)或原生 eBPF 解析 HTTP/1.x、HTTP/2 和 gRPC 流量,允许在 L7 层基于方法(GET、POST、PUT、DELETE)、路径、Header 等字段实施细粒度访问控制。
4.2.1 HTTP 方法策略结构
策略定义在 toPorts.rules.http 字段中,支持以下匹配条件:
- method: HTTP 方法(GET、POST、PUT、PATCH、DELETE、HEAD、OPTIONS)。
- path: URL 路径,支持精确匹配和前缀匹配(
/api/v1/)。 - headers: 自定义 Header 键值对匹配。
- host: HTTP Host Header 匹配。
4.2.2 策略示例:只允许 GET 请求
以下策略允许 frontend 命名空间中的 Pod 仅能对 backend 服务发起 GET 请求,拒绝 POST、PUT、DELETE 等写操作。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "l7-http-get-only"
namespace: frontend
spec:
endpointSelector:
matchLabels:
app: web-frontend
egress:
- toEndpoints:
- matchLabels:
app: backend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/products"
4.2.3 HTTP 策略与 ServiceMesh 对比
| 维度 | Cilium L7 HTTP 策略 | Istio/Envoy Sidecar |
|---|---|---|
| 数据路径 | eBPF + 可选 Envoy 代理 | Sidecar 代理(iptables 重定向) |
| 延迟开销 | 低(< 1ms,eBPF 快速路径) | 中(1-3ms,Sidecar 处理) |
| 资源消耗 | 低(无 Sidecar 容器) | 高(每个 Pod 额外 Sidecar) |
| 协议支持 | HTTP/1.x, HTTP/2, gRPC | HTTP/1.x, HTTP/2, gRPC, TCP |
| 策略复杂度 | 中等(YAML 定义) | 高(VirtualService, DestinationRule) |
4.3 基于 Kubernetes ServiceAccount 的策略
在零信任模型中,网络策略应基于“身份”而非“IP”。Cilium 原生支持通过 toServices 和 fromEndpoints 中的 matchLabels 引用 ServiceAccount,实现身份感知的访问控制。
4.3.1 ServiceAccount 策略原理
每个 Pod 都关联一个 ServiceAccount。Cilium 通过 Kubernetes API 监听 ServiceAccount 与 Pod 的绑定关系,并将身份信息注入 eBPF 程序。策略匹配时,直接检查 Pod 的 ServiceAccount 标签,而非 IP 地址。
4.3.2 策略示例:限制特定 ServiceAccount 的访问
以下策略只允许 service-account: payment-processor 的 Pod 访问 database 服务的 3306 端口。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "sa-to-database"
namespace: payment
spec:
endpointSelector:
matchLabels:
app: database
ingress:
- fromEndpoints:
- matchLabels:
"k8s:io.kubernetes.pod.namespace": payment
"k8s:app.kubernetes.io/name": payment-processor
toPorts:
- ports:
- port: "3306"
protocol: TCP
k8s: 前缀表示 Kubernetes 原生标签。Cilium 会自动将 ServiceAccount 名称转换为标签 k8s:io.kubernetes.pod.serviceaccount,但更推荐使用自定义 matchLabels 结合命名空间限制。
4.3.3 身份策略与 CIDR 策略对比
| 维度 | ServiceAccount 策略 | CIDR 策略 |
|---|---|---|
| 匹配依据 | Kubernetes 身份(ServiceAccount) | IP 地址范围 |
| 动态性 | 高(Pod 重建后自动适配) | 低(IP 变化需手动更新) |
| 适用场景 | 集群内部微服务间访问 | 集群外部系统、传统 VM 环境 |
| 安全性 | 高(身份不可伪造) | 中(IP 可被欺骗) |
4.4 CIDR 策略(Classless Inter-Domain Routing)
CIDR 策略是 Cilium 中最基础的 L3 层策略,用于控制 Pod 对特定 IP 地址段的访问。虽然不如 FQDN 或 ServiceAccount 策略灵活,但在与外部传统系统(如物理数据库、VPN 网关)通信时不可或缺。
4.4.1 CIDR 策略语法
使用 toCIDR 和 fromCIDR 字段,支持 IPv4 和 IPv6 地址段。
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "cidr-egress-external-db"
namespace: production
spec:
endpointSelector:
matchLabels:
app: api-server
egress:
- toCIDR:
- 10.100.20.0/24
- 192.168.1.100/32
toPorts:
- ports:
- port: "5432"
protocol: TCP
4.4.2 CIDR 策略与集群网络冲突
toCIDR 定义的 IP 段与 Kubernetes Pod CIDR 或 Service CIDR 重叠时,Cilium 会优先匹配集群内部端点策略(toEndpoints)。建议将 CIDR 策略仅用于外部 IP,内部通信使用 toEndpoints 或 toServices。
4.4.3 CIDR 策略最佳实践
- 最小化范围: 尽量使用
/32精确 IP 或/24小段,避免开放大段公网 IP。 - 结合 FQDN: 对于外部 API,优先使用 FQDN 策略;仅当外部服务无固定域名或 DNS 不可靠时,才使用 CIDR。
- 审计与监控: 使用
cilium monitor或 Hubble 观察 CIDR 策略命中情况,定期清理未使用的规则。
4.5 四种策略的协同架构
在实际生产环境中,这四种策略通常组合使用,形成分层防御体系。下图展示了典型微服务架构中的策略部署模型。
4.6 策略冲突与优先级
当多种策略类型同时作用于同一个 Pod 时,Cilium 遵循以下优先级规则:
- Deny 规则优先: 任何显式的
deny规则(CiliumNetworkPolicy 或 CiliumClusterwideNetworkPolicy 中的deny字段)优先级最高。 - L7 规则覆盖 L3/L4: 如果同时存在 L7 HTTP 规则和 L3/L4 端口规则,L7 规则会进一步限制允许的 HTTP 方法、路径等。
- 最具体规则生效: 对于同一流量,匹配条件最具体的策略生效。例如,
toFQDNs中的matchName比matchPattern更具体。 - 默认拒绝: 如果没有显式允许规则,所有流量默认被拒绝(白名单模式)。
cilium policy trace 命令模拟流量路径,查看哪些策略被命中。例如:cilium policy trace --src-k8s-pod default/frontend-pod --dst-k8s-pod default/backend-pod --dport 8080
4.7 本章小结
本章详细介绍了 Cilium 四种高级网络策略类型:
- FQDN 策略: 通过域名控制出站流量,适合访问外部 API 和 CDN。
- HTTP 方法策略: 在 L7 层限制 HTTP 方法、路径和 Header,实现 API 级安全。
- ServiceAccount 策略: 基于 Kubernetes 身份进行访问控制,适合集群内部微服务间通信。
- CIDR 策略: 基于 IP 地址段控制流量,用于与传统外部系统集成。