4. Rego 策略执行流程:输入解析、规则匹配、数据查询、结果聚合

理解 Rego 策略的完整执行流程,是优化缓存策略和降低 K8s API 延迟的前提。OPA 在每次策略评估时,都会经历四个核心阶段:输入解析、规则匹配、数据查询和结果聚合。每个阶段都可能成为性能瓶颈,尤其是在大规模集群中。

核心认知: Rego 并非逐行解释执行,而是先将策略编译为内部表示(IR),再基于输入和数据执行增量或全量评估。缓存策略主要作用于“数据查询”阶段,但其他阶段的优化同样关键。

4.1 执行流程全景图

下图展示了 Rego 策略从接收到返回结果的完整流水线。注意,数据查询阶段是 OPA 与 K8s API Server 交互的唯一入口,也是延迟的主要来源。

Rego 策略执行流程全景图 Rego 策略执行流程全景图 阶段1: 输入解析 input 对象构建与校验 阶段2: 规则匹配 规则选择与变量绑定 阶段3: 数据查询 data 文档 & K8s API 阶段4: 结果聚合 规则输出与决策生成 ⚠ 性能关键路径: 阶段3(数据查询)是唯一与外部系统(K8s API Server)交互的阶段,缓存策略主要作用于此处。 各阶段内部子流程 输入解析子流程 1. JSON/JSON Schema 校验 2. 类型转换与默认值填充 3. 构建 input 文档树 规则匹配子流程 1. 规则索引查找 2. 变量统一与绑定 3. 部分求值(PE) 数据查询子流程 1. 缓存命中检查 2. K8s API 调用(未命中) 3. 数据反序列化与合并 结果聚合子流程 1. 规则输出合并 2. 默认值/冲突处理 3. 决策文档生成

4.2 阶段一:输入解析(Input Parsing)

输入解析是策略执行的起点。OPA 将外部传入的 input 对象(通常是来自 K8s Admission Review 请求的 JSON)解析为内部可操作的文档树。

步骤 操作 性能影响
1 JSON 反序列化与 Schema 校验 大体积 input(如包含完整 Pod Spec)会增加解析耗时
2 类型转换与默认值填充 Rego 的 object.get() 等内置函数在此阶段预计算
3 构建 input 文档树 树深度影响后续规则匹配的遍历效率
优化建议: 在 K8s 准入控制场景中,尽量精简 Admission Review 请求体。只传递策略需要的字段,避免传递完整的 Pod/Deployment 清单。使用 object.filter() 在策略入口处裁剪 input。

4.3 阶段二:规则匹配(Rule Matching)

规则匹配阶段负责根据 input 内容,从策略包中选择需要评估的规则,并进行变量绑定。OPA 使用规则索引来加速匹配过程。

  • 规则索引: OPA 会为每个包中的规则建立哈希索引,基于规则头(head)中的变量快速定位候选规则。
  • 变量统一: 将 input 中的实际值与规则中的变量进行绑定,生成一组可能的赋值组合。
  • 部分求值(Partial Evaluation, PE): 在规则匹配阶段,OPA 会尝试将不依赖外部数据的子表达式提前求值,减少后续数据查询的负担。
# 示例:规则索引如何工作
# 假设有以下规则
allow {
    input.role == "admin"          # 索引键:role
    input.operation == "delete"    # 索引键:operation
    data.cluster.admins[_] == input.user  # 数据查询
}

# OPA 会为 role 和 operation 建立复合索引
# 当 input.role = "admin" 且 input.operation = "delete" 时
# 直接命中索引,跳过其他不相关规则

4.4 阶段三:数据查询(Data Query)—— 性能核心

数据查询阶段是 OPA 策略执行中最耗时的环节,也是缓存策略的主要作用对象。此阶段 OPA 需要访问 data 文档,其中包含从 K8s API Server 拉取的集群实时状态。

关键瓶颈: 每次数据查询都可能触发 K8s API 调用。在大型集群中,一次策略评估可能涉及数百次 API 调用(如遍历所有 Pod、Service、Namespace)。未经优化的数据查询是延迟的主要来源。

数据查询的三种模式:

模式 触发条件 延迟特征 缓存适用性
全量查询 data.cluster.pods[_] 无过滤条件 高(拉取所有资源) 适合全量缓存
带标签查询 data.cluster.pods[{"app": "nginx"}] 中(服务端过滤) 适合按标签缓存
单资源查询 data.cluster.pods["default"]["my-pod"] 低(直接索引) 适合短 TTL 缓存

4.5 阶段四:结果聚合(Result Aggregation)

结果聚合是策略执行的最后阶段。OPA 将所有匹配规则的输出合并,处理默认值和冲突,最终生成决策文档(Decision Document)。

  • 规则输出合并: 所有 allow、deny、violation 等规则的结果被收集。
  • 默认值处理: 使用 default allow = false 等声明填充未匹配规则的默认值。
  • 冲突解决: 当多条规则对同一变量赋值时,OPA 遵循“最后赋值胜出”或“完全集合”语义。
  • 决策文档生成: 最终输出一个 JSON 对象,包含 allowed、denied、warnings 等字段。
# 结果聚合示例
# 策略定义
package example

default allow = false

allow {
    input.role == "admin"
}

deny["用户没有管理员权限"] {
    not allow
}

# 当 input.role = "admin" 时,聚合结果为:
# {
#   "allow": true,
#   "deny": {}
# }
# 
# 当 input.role = "viewer" 时,聚合结果为:
# {
#   "allow": false,
#   "deny": {"用户没有管理员权限"}
# }

4.6 各阶段延迟分布与优化方向

以下表格展示了典型场景下各阶段的延迟占比,以及对应的优化策略:

阶段 典型延迟占比 主要优化方向
输入解析 5% - 10% 精简 input 结构、使用 Schema 预校验
规则匹配 10% - 20% 优化规则索引、减少冗余规则、使用部分求值
数据查询 60% - 80% 引入缓存、减少 API 调用、使用标签过滤
结果聚合 5% - 10% 减少规则数量、使用默认值避免空查询