2. OPA 与 Rego 基础回顾:OPA 架构、Rego 策略语言核心概念、数据文档与规则文档
在深入缓存与延迟故障排查之前,必须重新校准对 OPA 与 Rego 的基础认知。本章从架构、语言核心、数据与规则三个维度建立统一的术语体系,确保后续章节的案例分析与调试手段有共同的知识底座。
2.1 OPA 整体架构
OPA(Open Policy Agent)是一个轻量级的、与平台无关的策略引擎。其核心职责是将策略决策与策略执行解耦。OPA 本身不执行任何业务逻辑,只回答一个问题:“这个请求是否被允许?”
架构要点:OPA 通过 REST API 接收查询(Query),结合加载的策略(Policy)与外部数据(Data),输出决策结果(Decision)。所有输入数据均视为不可信的 JSON 文档,策略规则通过 Rego 语言编写。
2.2 Rego 策略语言核心概念
Rego 是一种声明式查询语言,灵感来源于 Datalog。它不描述“如何做”,而是描述“数据应该是什么样子”。理解以下核心概念是编写高效策略的基础。
| 概念 | 说明 | 示例 |
|---|---|---|
| 规则(Rule) | 策略的基本单元,定义一组条件与结果 | allow { input.role == "admin" } |
| 查询(Query) | 向 OPA 发起的决策请求,包含 input 数据 | POST /v1/data/example/allow |
| 迭代(Iteration) | 通过集合推导式遍历数组或对象 | some user in input.users |
| 默认规则(Default) | 为规则提供兜底值,避免未定义 | default allow = false |
| 内置函数(Built-in) | 预置的字符串、时间、加密等函数 | http.send(...) |
常见误区:Rego 中的变量一旦绑定即不可变。不要尝试在规则体内对同一变量多次赋值,这会导致编译错误或非预期结果。
2.3 数据文档(Data Document)与规则文档(Rule Document)
OPA 将一切视为文档。理解数据文档与规则文档的区别,是诊断策略行为异常的关键。
2.3.1 数据文档
数据文档是外部注入的静态 JSON 数据,通过 data 命名空间访问。典型来源包括:
- Bundle 加载:通过 OPA 的 Bundle API 推送的 JSON 文件。
- REST API 推送:通过
PUT /v1/data接口写入。 - 外部数据源:通过
http.send在运行时拉取。
// 数据文档示例:data.roles
{
"roles": {
"admin": ["read", "write", "delete"],
"viewer": ["read"]
}
}
2.3.2 规则文档
规则文档是由 Rego 规则计算得出的虚拟文档。规则一旦被定义,其名称就成为 data 下的一个路径。规则文档是动态的,每次查询时重新计算。
// 规则文档示例:data.example.allow
package example
default allow = false
allow {
input.user == "alice"
}
allow {
data.roles[input.role][_] == "write"
}
性能陷阱:规则文档的递归引用可能导致无限循环。例如规则 A 引用规则 B,规则 B 又引用规则 A,且没有终止条件。OPA 在检测到循环时会返回错误,但复杂的间接循环可能难以定位。
2.4 关键对比:数据文档 vs 规则文档
| 维度 | 数据文档 | 规则文档 |
|---|---|---|
| 来源 | 外部注入(Bundle / API) | Rego 规则定义 |
| 生命周期 | 持久化存储,直到被覆盖 | 每次查询时重新计算 |
| 缓存行为 | 可被 OPA 缓存层缓存 | 通常不缓存(除非显式优化) |
| 变更方式 | 通过 API 或 Bundle 更新 | 通过重新加载策略模块 |
| 典型用途 | 角色列表、黑名单、配置参数 | 访问控制、校验逻辑、聚合计算 |
故障排查启示:当策略行为与预期不符时,首先确认目标路径是数据文档还是规则文档。如果是数据文档,检查数据是否已正确加载;如果是规则文档,检查规则依赖链中是否存在未定义或循环引用。