4. OPA 与 Rego 语言入门:OPA 架构、Rego 语法基础、策略查询与数据模型

本章是 OPA 策略引擎的入门实战章节。你将理解 OPA 的组件架构、掌握 Rego 语言的核心语法,并学会如何通过数据模型与查询机制将策略集成到 Kubernetes 多集群发布流程中。学完本章,你将能够独立编写并测试基础的 OPA 策略。

4.1 OPA 整体架构

OPA(Open Policy Agent)是一个开源的、通用的策略引擎,它将策略决策与业务逻辑解耦。在云原生环境中,OPA 作为独立的服务运行,接收来自任何系统(如 API 网关、Kubernetes API Server、CI/CD 流水线)的查询请求,并基于预定义的策略和输入数据做出决策。

OPA 核心架构组件 外部请求 (K8s / HTTP / CLI) OPA 服务 REST API Rego 引擎 策略存储 数据缓存 决策输出 (allow / deny) 外部数据源 (K8s RBAC / 集群清单) 策略文件 (Rego .rego 文件)
架构要点:OPA 将策略(Rego 代码)与数据(JSON 输入)分离。每次决策请求都包含一个 input 对象,OPA 引擎根据策略规则对 input 和内置的 data 进行求值,最终返回决策结果。

4.2 Rego 语言基础

Rego 是 OPA 专用的声明式查询语言,灵感来源于 Datalog。Rego 的核心思想是:你描述策略应该是什么样子,而不是如何执行它。Rego 中的每条规则都是一个逻辑断言。

4.2.1 基本语法元素

语法元素 说明 示例
包(Package) 用于组织策略的命名空间 package kubernetes.admission
规则(Rule) 策略的核心单元,返回布尔值或集合 allow { input.namespace == "prod" }
字面量 字符串、数字、布尔值、对象、数组 "nginx", 8080, true
变量 以 _ 或小写字母开头,不可变 image_name := input.containers[0].image
引用(Ref) 访问嵌套数据,使用点号或方括号 data.roles["admin"]
数组/对象推导 类似 Python 的列表推导式 [x | x = input.ports[_]; x > 1024]

4.2.2 规则类型与模式

Rego 规则主要分为两类:完整规则(Complete Rule)和部分规则(Partial Rule)。完整规则返回一个单一值;部分规则返回一个集合或对象,通常用于定义允许列表或黑名单。

# 完整规则:返回布尔值
package example

default allow = false

allow {
    input.role == "admin"
    input.action == "delete"
}

# 部分规则:返回一个集合
allowed_images := {"nginx:1.21", "redis:6.2", "alpine:3.15"}

valid_image {
    input.image in allowed_images
}
关键概念:Rego 中的 := 用于赋值(声明新变量),== 用于比较,= 用于统一(同时进行赋值和比较)。在规则体中,所有条件必须同时满足(逻辑与),多个规则体之间是逻辑或的关系。

4.3 策略查询与数据模型

OPA 通过 HTTP API 对外提供策略查询能力。理解数据模型是编写正确策略的前提。OPA 的数据模型分为三个层次:全局数据(data)、输入数据(input)和内置数据(built-in)。

4.3.1 数据模型层次

数据源 访问方式 内容说明 生命周期
全局数据(data) data.<package>.<rule> 所有加载的策略规则和外部数据 持久化,随策略加载更新
输入数据(input) input.<field> 每次查询请求携带的上下文 每次请求独立
内置数据 builtin.<function> OPA 内置函数,如 regex.match 固定,随 OPA 版本变化

4.3.2 查询方式

OPA 支持两种查询模式:决策查询(Decision Query)和数据查询(Data Query)。在多集群 Operator 发布场景中,最常用的是决策查询。

  • 决策查询:通过 POST /v1/data/<package> 发送,返回策略决策结果。适用于准入控制、权限校验等场景。
  • 数据查询:通过 GET /v1/data/<path> 获取 OPA 中存储的完整数据。适用于调试和审计。
  • 部分求值:通过 POST /v1/compile 对策略进行部分求值,生成可重用的决策条件。适用于大规模策略分发。
OPA 查询流程与数据模型交互 请求方 (K8s / 流水线) OPA 查询处理 input data Rego 规则求值 决策结果 (JSON 响应) 外部数据加载

4.3.3 实战:编写一个简单的准入控制策略

以下示例展示了一个用于 Kubernetes 准入控制的 OPA 策略,它检查 Deployment 的镜像是否来自受信任的仓库。

# 文件: check-registry.rego
package kubernetes.admission

# 默认拒绝
default deny = false

# 定义受信任的镜像仓库前缀
trusted_registries := {
    "docker.io/company/",
    "registry.internal.company.com/"
}

# 拒绝规则:如果镜像不在受信任列表中,则拒绝
deny {
    input.request.kind.kind == "Deployment"
    some container in input.request.object.spec.template.spec.containers
    not trusted_image(container.image)
}

# 辅助规则:检查镜像是否以受信任前缀开头
trusted_image(image) {
    some prefix in trusted_registries
    startswith(image, prefix)
}

# 允许规则:如果通过了所有拒绝检查,则允许
allow {
    not deny
}
常见陷阱:Rego 中 some 关键字用于声明局部变量,在遍历数组或集合时必须使用。忘记使用 some 会导致变量作用域错误,使规则意外求值为 true 或 false。另外,注意 not 运算符的优先级,建议使用括号明确分组。

4.4 本章小结

  • OPA 采用 策略与数据分离 的架构,通过 REST API 接收查询并返回决策。
  • Rego 是 声明式 策略语言,规则由包、规则头和规则体组成,支持完整规则和部分规则。
  • 数据模型分为 data、input 和内置函数三层,理解数据来源是编写正确策略的基础。
  • 查询方式包括决策查询、数据查询和部分求值,在多集群场景中决策查询最常用。
  • 通过 辅助规则 和 集合推导 可以编写可读性强、易于维护的策略代码。