3. 策略即代码(PaC)概念
3.1 PaC 的定义与核心价值
策略即代码(Policy as Code, PaC)是一种将组织中的安全、合规、资源治理等策略规则,以机器可读的代码形式进行声明、存储、执行和审计的实践方法。其核心思想是:把“什么是允许的”和“什么是禁止的”从人工审核或静态文档中解放出来,转化为可编程、可测试、可版本控制的自动化决策逻辑。
- 自动化执行:策略在系统运行时自动评估,无需人工干预。
- 版本控制与审计:策略变更通过 Git 等工具追踪,提供完整的变更历史。
- 一致性:消除不同环境或团队之间的策略执行差异。
- 可测试性:策略可以像软件代码一样编写单元测试和集成测试。
- 自服务:开发团队可以自助查看和理解策略,减少沟通成本。
3.2 PaC 与 IaC 的关系
基础设施即代码(Infrastructure as Code, IaC)定义了“系统应该是什么状态”,而策略即代码(PaC)定义了“系统允许是什么状态”。两者是互补关系,共同构建了云原生环境下的“声明式治理”闭环。
| 维度 | 基础设施即代码 (IaC) | 策略即代码 (PaC) |
|---|---|---|
| 关注点 | 部署什么资源(如 Pod、Service、Deployment) | 资源必须满足什么约束(如必须包含资源限制、禁止特权容器) |
| 执行时机 | 资源创建/更新时(Apply) | 资源创建/更新前(Admission Review) |
| 失败后果 | 资源无法部署或状态不一致 | 请求被拒绝,并返回明确的违规原因 |
| 典型工具 | Terraform, Pulumi, Helm | OPA, Gatekeeper, Kyverno |
| 类比 | 建筑蓝图(设计图) | 建筑规范(必须遵守的规则) |
3.3 主流 PaC 引擎简介
在 Kubernetes 生态中,策略即代码主要通过准入控制器(Admission Controller)实现。以下是三个最主流的引擎:
3.3.1 OPA (Open Policy Agent)
OPA 是一个通用的、开源的策略引擎,它不绑定于任何特定平台。OPA 使用一种名为 Rego 的高级声明式语言来编写策略。OPA 本身是一个独立的服务,通过 REST API 接收查询(输入),并返回策略决策(输出)。
- 核心特点:通用性强,可应用于微服务、CI/CD、Kubernetes 等多种场景。
- 语言:Rego(功能强大,但学习曲线相对陡峭)。
- 在 K8s 中的角色:作为独立的准入控制器服务运行。
3.3.2 Gatekeeper
Gatekeeper 是 OPA 在 Kubernetes 环境中的原生集成实现,由 Google 和微软等公司共同维护。它作为 Kubernetes 的准入 Webhook 运行,将 OPA 的策略引擎与 Kubernetes 的 API 深度绑定。
- 核心特点:完全基于 Kubernetes 自定义资源(CRD)管理策略,原生支持 Kubernetes 审计和约束模板。
- 语言:Rego(通过 ConstraintTemplate 封装)。
- 优势:与 K8s 生态集成最紧密,社区成熟度高。
3.3.3 Kyverno
Kyverno 是一个专为 Kubernetes 设计的策略引擎,由 Nirmata 公司开发。它的最大特点是策略编写简单,无需学习新的策略语言(如 Rego),直接使用 Kubernetes 资源清单(YAML)来定义策略规则。
- 核心特点:策略即 YAML,学习成本极低;支持 mutate(修改资源)、validate(验证资源)、generate(生成资源)等多种能力。
- 语言:YAML(基于 Kubernetes 资源模式)。
- 优势:对 Kubernetes 用户友好,策略编写效率高。
3.4 三种引擎对比
| 特性 | OPA | Gatekeeper | Kyverno |
|---|---|---|---|
| 策略语言 | Rego | Rego | YAML |
| 学习曲线 | 高 | 中(需理解 CRD + Rego) | 低 |
| K8s 原生性 | 低(通用引擎) | 高(CRD 驱动) | 极高(YAML 即策略) |
| 策略能力 | 验证、查询 | 验证、审计 | 验证、变更、生成 |
| 社区与生态 | 广泛(跨平台) | K8s 生态主流 | 快速增长 |
| 适用场景 | 需要跨平台统一策略 | K8s 原生策略治理 | 快速落地、团队 K8s 经验丰富 |
3.5 PaC 在 Kubernetes 中的工作流程
下图展示了 PaC 引擎在 Kubernetes 准入控制阶段的核心工作流程:
3.6 策略即代码示例
以下是一个使用 Kyverno 编写的简单策略示例,用于强制要求所有 Pod 必须包含 app.kubernetes.io/name 标签:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-app-label
spec:
validationFailureAction: Enforce
rules:
- name: check-app-label
match:
any:
- resources:
kinds:
- Pod
validate:
message: "标签 'app.kubernetes.io/name' 是必需的。"
pattern:
metadata:
labels:
app.kubernetes.io/name: "?*"
validationFailureAction: Enforce 表示违反策略时直接拒绝请求。如果设置为 Audit,则仅记录违规,不阻止资源创建,适用于策略的灰度测试阶段。