2. Policy Check 核心原理:策略即代码(Policy as Code)思想、OPA 与 Rego 语言简介

在进入多环境规则与 Runbook 联动部署之前,必须理解 Policy Check 的底层哲学:策略即代码(Policy as Code, PaC)。传统策略管理依赖人工审核、静态文档或硬编码在应用逻辑中,而 PaC 将策略声明为可版本控制、可测试、可自动执行的代码。本章深入剖析 PaC 思想,并介绍云原生领域最主流的策略引擎——OPA(Open Policy Agent)及其策略语言 Rego。

2.1 策略即代码(Policy as Code)思想

策略即代码的核心目标是将“允许什么、禁止什么、必须满足什么条件”这类治理规则,从人脑、Wiki 或审批流程中剥离,转化为机器可读、可执行的代码制品。它与基础设施即代码(IaC)一脉相承,但关注点从“资源定义”转向“合规判定”。

维度 传统策略管理 策略即代码(PaC)
载体 PDF 文档、邮件、审批表单 文本文件(.rego, .yaml, .json)
版本控制 无或依赖文件名 Git 仓库,支持 diff、PR、回滚
测试 人工抽查 单元测试、集成测试(如 OPA 测试框架)
执行时机 事后审计或人工拦截 准入控制、CI/CD 门禁、实时决策
变更影响 难以评估 通过 Git 历史与测试覆盖可追溯
实践要点:PaC 不是简单的“把规则写成代码”,而是要求策略具备幂等性(相同输入始终返回相同决策)、可组合性(小策略可叠加为大策略)和可观测性(决策日志与审计追踪)。在 Policy Check 课程中,所有 Runbook 联动规则都将以 PaC 形式交付。

2.2 OPA:云原生策略引擎

OPA(Open Policy Agent)是 CNCF 毕业项目,提供统一的策略决策层。它不负责执行策略(如阻断请求),而是回答“是否允许”的问题。OPA 将策略与业务逻辑解耦,使安全团队、平台团队可以独立编写和更新规则,无需修改微服务代码。

OPA 的核心工作流程:

  1. 输入(Input):外部系统(如 Kubernetes API Server、CI 工具)将请求数据以 JSON 格式发送给 OPA。
  2. 策略(Policy):OPA 加载用 Rego 语言编写的策略文件。
  3. 数据(Data):OPA 可加载外部数据(如白名单、角色映射)作为决策上下文。
  4. 决策(Decision):OPA 执行策略,返回 allow/deny 及详细原因。
OPA 核心决策流程 输入 (Input) JSON 请求 策略 (Policy) Rego 文件 数据 (Data) 外部上下文 OPA 引擎 策略评估 决策 allow/deny OPA 不执行阻断,只返回决策结果;由外部系统(如 K8s Admission Controller)执行 enforce

2.3 Rego 语言简介

Rego 是 OPA 的原生查询语言,受 Datalog 启发,专为嵌套文档结构(JSON/YAML)的策略评估设计。Rego 的核心思想是:策略是查询,查询是规则。开发者编写规则来定义“什么是允许的”,而非“如何拒绝”。

2.3.1 基础语法结构

一个 Rego 策略文件通常包含 package 声明、import 语句和若干规则(Rule)。规则可以是完整规则(Complete Rule)或增量规则(Incremental Rule)。

package policycheck.kubernetes

import future.keywords.if
import future.keywords.in

# 完整规则:返回布尔值
default allow := false

# 增量规则:当条件满足时 allow 为 true
allow if {
    input.request.operation == "CREATE"
    input.request.resource == "Pod"
    input.request.namespace == "production"
    not has_privileged_container
}

# 辅助规则:检查是否包含特权容器
has_privileged_container if {
    some container in input.request.object.spec.containers
    container.securityContext.privileged == true
}
关键概念:
  • 规则头(Rule Head):allow if { ... },定义规则名称和条件。
  • 迭代(some ... in):遍历数组或集合,类似编程语言的 for-each。
  • 默认值(default):为规则设置默认结果,避免未定义。
  • 否定(not):Rego 使用 not 表示逻辑非,但需注意安全否定(Negation as Failure)。

2.3.2 数据查询与组合

Rego 支持从外部数据源(如 JSON 文件、LDAP、HTTP API)加载数据,并在策略中引用。数据通过 data 关键字访问。

package policycheck.iam

# 加载外部角色映射数据(假设 data.roles 包含 {"admin": ["create", "delete"], "viewer": ["read"]})
allow if {
    input.user.role == "admin"
    input.action in data.roles[input.user.role]
}
Rego 特性 说明 典型场景
完全匹配(==) 精确比较值 检查 namespace 是否为 production
模式匹配(=) 统一赋值与匹配 解构嵌套对象
集合操作 交集、并集、差集 检查标签是否在白名单内
内置函数 如 count(), regex.match(), time.now_ns() 正则校验、时间窗口限制

2.4 OPA 与 Rego 在 Policy Check 中的角色

在《Policy Check 多环境规则与 Runbook 联动部署》课程中,OPA 作为策略决策引擎,Rego 作为策略编写语言,二者共同构成规则层的核心。Runbook 联动部署时,每个环境(dev/staging/prod)加载不同的 Rego 策略包,OPA 根据输入(如部署请求、资源清单)实时判定是否允许继续。

Policy Check 多环境策略分层 Dev 环境 Staging 环境 Prod 环境 dev-policy.rego 宽松规则:允许调试 staging-policy.rego 中等规则:限制资源 prod-policy.rego 严格规则:全面审计 OPA 策略引擎(统一决策层) 加载对应环境的 Rego 包 + 全局数据 决策输出:allow / deny + 原因 每个环境独立维护 Rego 策略包,OPA 引擎根据请求来源加载对应策略,实现多环境差异化管控
常见误区:不要将 OPA 当作“策略执行器”。OPA 只做决策,不负责拦截或修改请求。执行动作(如拒绝 Pod 创建、触发 Runbook 回滚)必须由调用方(如 Kubernetes Admission Webhook、CI 脚本)实现。在后续 Runbook 联动章节中,我们将展示如何将 OPA 的 deny 决策转化为自动化补救动作。

2.5 本章小结

  • 策略即代码将治理规则从文档转化为可版本控制、可测试的代码制品,是 Policy Check 的基石。
  • OPA 提供统一的策略决策层,通过输入、策略、数据、决策四步完成判定,与业务逻辑完全解耦。
  • Rego 是声明式策略语言,擅长处理嵌套 JSON 数据,支持迭代、模式匹配、外部数据引用等特性。
  • 在多环境场景中,每个环境拥有独立的 Rego 策略包,OPA 引擎根据环境标识加载对应规则,实现差异化管控。