4. OPA 与 Rego 语言基础:OPA 架构、Rego 语法入门、基本规则编写、数据查询与决策输出

4.1 OPA 架构与核心组件

Open Policy Agent (OPA) 是一种开源的、通用策略引擎,它将策略决策与业务逻辑解耦。在云原生和 CI/CD 场景中,OPA 作为独立的服务或库运行,接收结构化的查询(输入 + 数据),输出策略决策结果。

核心设计理念: OPA 不负责执行策略(如拒绝 Pod 创建),只负责做出决策(如“是否允许该 Pod 创建”)。执行动作由调用方(如 Kubernetes API Server、CI/CD 工具)完成。

4.1.1 OPA 架构分层

OPA 架构分层与数据流 调用层(Caller) Kubernetes API Server / CI/CD 工具 / 微服务网关 查询层(Query Layer) 输入(input)+ 数据(data)→ 查询请求 策略引擎层(Policy Engine) Rego 规则编译、数据索引、查询评估 数据层(Data Layer) 基础文档(base documents) + 虚拟文档(virtual documents)

4.1.2 关键组件说明

组件 角色 CI/CD 场景示例
输入(input) 每次查询时传入的临时数据 流水线构建请求的 JSON:{"kind":"Deployment","metadata":{"name":"web-app"}}
数据(data) 全局持久化数据,可热加载 资源配额表、团队白名单、环境标签
Rego 策略 声明式规则集合 deny[msg] { ... } 规则
决策输出 查询结果,通常为布尔值或结构化 JSON {"allow":false,"reason":"CPU 配额超限"}
架构要点: OPA 将策略从代码中剥离,通过统一的 input + data → decision 模型,使 CI/CD 流水线中的资源配额校验、安全合规检查、环境准入控制等策略实现集中管理和热更新。

4.2 Rego 语法入门

Rego 是 OPA 专用的声明式查询语言,灵感来源于 Datalog。Rego 的核心是规则(Rule)和查询(Query),所有逻辑都围绕“数据是什么”而非“如何计算”展开。

4.2.1 基本语法元素

语法元素 说明 示例
标量 字符串、数字、布尔值 "prod"、42、true
变量 以 _ 或小写字母开头 name、cpu_limit、_
引用 访问嵌套数据 input.metadata.name、data.quotas
数组/对象 复合数据结构 ["a","b"]、{"key":"val"}
集合推导 从集合中筛选 { x | x := data.items[x.cpu > 1] }

4.2.2 规则定义

Rego 规则分为完整规则和部分规则。完整规则返回单个值,部分规则返回集合或对象。

# 完整规则:返回布尔值
allow := true {
    input.role == "admin"
}

# 部分规则:返回集合(所有违规消息)
deny[msg] {
    input.cpu > data.quotas.max_cpu
    msg := sprintf("CPU 配额超限: %v > %v", [input.cpu, data.quotas.max_cpu])
}

# 部分规则:返回对象
team_quotas[team] = quota {
    data.teams[team]
    quota := data.quotas[team]
}
常见陷阱: Rego 中变量名区分大小写,且变量一旦绑定即不可变。不要尝试在规则内对同一变量多次赋值,这会导致评估失败。

4.3 基本规则编写与数据查询

4.3.1 规则编写模式

在资源配额场景中,规则通常遵循“默认允许 + 显式拒绝”模式。OPA 的决策输出通过 allow、deny、warn 等规则名约定来组织。

# 默认允许
default allow := false

# 显式允许条件
allow {
    input.namespace == "default"
    input.cpu <= data.quotas.default.cpu
}

# 拒绝规则
deny[msg] {
    input.cpu > data.quotas.default.cpu
    msg := "CPU 请求超过默认配额"
}

deny[msg] {
    input.memory > data.quotas.default.memory
    msg := "内存请求超过默认配额"
}

4.3.2 数据查询与决策输出

OPA 通过 REST API 或 Go 库接收查询。查询时需提供 input 和可选的 data 覆盖。决策输出是查询路径对应的规则结果。

查询方式 请求示例 响应示例
完整规则查询 POST /v1/data/example/allow {"result":true}
部分规则查询 POST /v1/data/example/deny {"result":["CPU 请求超过默认配额"]}
自定义输出 POST /v1/data/example/decision {"result":{"allowed":false,"reasons":[...]}}
# 自定义决策输出规则
decision := {"allowed": allow, "reasons": deny} {
    true  # 始终执行
}

# 查询 /v1/data/example/decision 时返回:
# {"result":{"allowed":false,"reasons":["CPU 请求超过默认配额"]}}
CI/CD 集成要点: 在流水线中,通常将 input 设为构建请求的 JSON 描述,data 加载全局配额表。OPA 返回的 deny 集合若不为空,则流水线中断并输出错误消息。

4.4 资源配额策略的 Rego 实现示例

以下是一个完整的资源配额校验策略,适用于 CI/CD 流水线中的部署请求审核。

package deployment.quota

# 默认拒绝
default allow := false

# 允许条件:命名空间在配额表中且资源未超限
allow {
    data.quotas[input.namespace]
    input.cpu <= data.quotas[input.namespace].cpu_limit
    input.memory <= data.quotas[input.namespace].memory_limit
}

# 拒绝原因:命名空间不存在
deny[msg] {
    not data.quotas[input.namespace]
    msg := sprintf("命名空间 %v 未定义配额", [input.namespace])
}

# 拒绝原因:CPU 超限
deny[msg] {
    data.quotas[input.namespace]
    input.cpu > data.quotas[input.namespace].cpu_limit
    msg := sprintf("CPU 配额超限: %v > %v", [input.cpu, data.quotas[input.namespace].cpu_limit])
}

# 拒绝原因:内存超限
deny[msg] {
    data.quotas[input.namespace]
    input.memory > data.quotas[input.namespace].memory_limit
    msg := sprintf("内存配额超限: %v > %v", [input.memory, data.quotas[input.namespace].memory_limit])
}

# 结构化决策输出
decision := {"allowed": allow, "reasons": deny}

4.4.1 数据与输入示例

# data.quotas 数据
{
  "default": {"cpu_limit": 4, "memory_limit": 8192},
  "production": {"cpu_limit": 16, "memory_limit": 32768},
  "staging": {"cpu_limit": 8, "memory_limit": 16384}
}

# input 输入
{
  "namespace": "production",
  "cpu": 12,
  "memory": 24576
}

# 决策输出
{
  "allowed": true,
  "reasons": []
}
最佳实践: 将配额数据存储在 OPA 的 data 层(如通过 ConfigMap 或 Bundle 加载),避免硬编码在规则中。这样更新配额时无需修改策略代码,只需更新数据源即可。

4.5 本章小结

  • OPA 架构 采用分层设计:调用层 → 查询层 → 策略引擎层 → 数据层,实现策略与执行分离。
  • Rego 语法 以声明式规则为核心,支持完整规则、部分规则、集合推导和自定义输出。
  • 规则编写 遵循“默认拒绝 + 显式允许 + 拒绝原因”模式,确保安全合规。
  • 数据查询 通过 REST API 传入 input 和 data,OPA 返回结构化决策结果。
  • 资源配额策略 示例展示了如何在 CI/CD 流水线中校验命名空间、CPU 和内存配额。