3. Policy as Code 概述:主流引擎对比

在 Kubernetes 生态中,Policy as Code(策略即代码)将安全、合规与治理规则从人工审核或静态配置中解放出来,转化为可版本化、可测试、可自动执行的代码。本章聚焦于三种主流引擎:OPA/Gatekeeper、Kyverno 与 Kubewarden,从架构、策略语言、性能与适用场景进行系统性对比。

3.1 核心概念与定位

Policy as Code 引擎通常以 准入控制器(Admission Controller) 的形式运行在 Kubernetes API Server 的请求链中。当资源创建、更新或删除时,引擎拦截请求,评估策略规则,决定允许或拒绝。

引擎 策略语言 运行时模型 策略分发方式 社区成熟度
OPA/Gatekeeper Rego(声明式查询语言) OPA 作为通用策略引擎,Gatekeeper 作为 Kubernetes 原生 CRD 封装 ConstraintTemplate + Constraint CRD CNCF 毕业项目,生态最广
Kyverno YAML 原生(无新语言) 专用准入控制器,直接解析 Kubernetes 资源 ClusterPolicy / Policy CRD CNCF 孵化项目,增长迅速
Kubewarden 多种语言(Rust、Go、Swift 等)编译为 WebAssembly Wasm 沙箱执行策略,轻量隔离 PolicyServer + AdmissionPolicy CRD CNCF 沙箱项目,新兴方案
选型提示: 如果团队已有 Rego 经验或需要跨平台策略复用,OPA/Gatekeeper 是稳妥选择;如果追求低学习成本与 Kubernetes 原生体验,Kyverno 更友好;如果对安全隔离与多语言策略有强需求,Kubewarden 的 Wasm 沙箱值得关注。

3.2 架构对比与策略执行流程

三种引擎在架构设计上存在显著差异,直接影响策略执行效率与扩展性。下图展示了各自的组件关系与请求处理路径。

三种 Policy as Code 引擎架构对比 OPA / Gatekeeper API Server 请求 Gatekeeper 准入 Webhook Constraint 匹配 OPA 引擎执行 Rego 允许 / 拒绝 ConstraintTemplate CRD Constraint CRD 实例 Kyverno API Server 请求 Kyverno 准入 Webhook ClusterPolicy 匹配 YAML 规则引擎 允许 / 拒绝 ClusterPolicy CRD Policy CRD 实例 Kubewarden API Server 请求 PolicyServer 准入 Webhook AdmissionPolicy 匹配 Wasm 沙箱执行 允许 / 拒绝 AdmissionPolicy CRD PolicyServer 部署

3.3 策略语言与表达能力

策略语言是引擎的核心差异点,直接影响编写效率、可读性与可维护性。

  • OPA/Gatekeeper — Rego:声明式查询语言,擅长处理嵌套 JSON 数据,支持复杂逻辑与数据聚合。学习曲线较陡,但表达能力极强。
  • Kyverno — YAML 原生:无需学习新语言,直接使用 Kubernetes 资源字段匹配与条件表达式。适合快速上手与简单策略。
  • Kubewarden — 多语言编译为 Wasm:开发者可使用 Rust、Go、Swift 等语言编写策略,编译为 WebAssembly 模块。性能高、隔离性好,但需要编译工具链。
策略示例对比: 以下展示同一策略(禁止特权容器)在三种引擎中的写法差异。
# OPA/Gatekeeper (Rego)
package k8s.privileged
violation[{"msg": msg}] {
  container := input.request.object.spec.containers[_]
  container.securityContext.privileged == true
  msg := sprintf("Container %v is privileged", [container.name])
}

# Kyverno (YAML)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-privileged
spec:
  rules:
  - name: check-privileged
    match:
      resources:
        kinds:
        - Pod
    validate:
      message: "Privileged containers are not allowed."
      pattern:
        spec:
          containers:
          - securityContext:
              privileged: "false"

# Kubewarden (Rust 编译为 Wasm)
// 使用 policy-sdk 编写,编译后部署
fn validate(payload: &ValidationRequest) -> ValidationResponse {
    let pod: Pod = serde_json::from_value(payload.object).unwrap();
    for container in &pod.spec.containers {
        if let Some(sc) = &container.security_context {
            if sc.privileged == Some(true) {
                return ValidationResponse::reject("Privileged container found".to_string());
            }
        }
    }
    ValidationResponse::accept()
}

3.4 性能与扩展性对比

在节点滚动升级场景中,策略引擎的性能直接影响升级速度。以下从延迟、资源消耗与扩展维度进行对比。

维度 OPA/Gatekeeper Kyverno Kubewarden
平均延迟 中等(Rego 解析 + 数据缓存) 低(YAML 直接匹配) 低(Wasm 沙箱执行,接近原生)
内存占用 较高(OPA 缓存数据与规则) 中等(每个策略独立 CRD) 低(Wasm 模块轻量)
策略扩展 通过 ConstraintTemplate 扩展 通过 ClusterPolicy 扩展 通过 Wasm 模块扩展
多集群支持 需额外配置 OPA 联邦 原生支持多集群策略同步 需 PolicyServer 跨集群部署
热更新 支持(OPA 热加载) 支持(CRD 更新即生效) 支持(Wasm 模块替换)

3.5 差异化准入能力

在节点滚动升级中,差异化准入要求策略引擎能够根据节点状态、升级阶段或资源标签动态调整规则。三种引擎的支持程度如下:

  • OPA/Gatekeeper:通过 Rego 的 data 注入外部数据(如节点标签、升级状态),可实现复杂条件判断。但需要额外维护数据同步。
  • Kyverno:支持 preconditions 与 context 引用集群资源,可直接查询节点状态,实现基于上下文的差异化准入。
  • Kubewarden:Wasm 策略可接收上下文参数,通过 PolicyServer 配置动态注入,适合需要高性能隔离的差异化场景。
注意: 在滚动升级过程中,差异化准入策略必须与节点排水、Pod 迁移节奏协调。策略引擎的缓存机制可能导致状态延迟,建议在升级前预热策略缓存或使用最终一致性模型。

3.6 选型建议与适用场景

根据团队技术栈与业务需求,以下提供选型参考:

场景 推荐引擎 理由
已有 Rego 经验或跨平台策略复用 OPA/Gatekeeper 生态成熟,策略可移植到非 K8s 环境
快速落地、团队 K8s 原生经验为主 Kyverno YAML 原生,学习成本低,社区策略库丰富
高性能、多语言策略、安全隔离要求高 Kubewarden Wasm 沙箱,性能接近原生,语言选择灵活
节点滚动升级中的动态差异化准入 Kyverno 或 Kubewarden 上下文感知能力强,延迟低,适合实时调整