4. Rego 语言基础(一):语法结构、规则定义与数据类型
Rego 是 Open Policy Agent (OPA) 的策略语言,专为在云原生环境中表达策略逻辑而设计。理解 Rego 的语法结构、规则定义方式以及数据类型,是编写可测试、可维护策略代码的基石。本章将系统性地拆解 Rego 的核心语言要素,为后续的流水线回滚护栏编写打下坚实基础。
4.1 Rego 语法结构概览
Rego 的语法受 Prolog 和 Datalog 启发,采用声明式(Declarative)范式。与命令式语言不同,Rego 不描述“如何做”,而是描述“应该是什么”。其核心结构由 模块(Module)、包(Package)、导入(Import) 和 规则(Rule) 组成。
| 语法元素 | 说明 | 示例 |
|---|---|---|
| Package | 定义策略的命名空间,避免规则冲突。每个文件通常以 package 开头。 |
package deployment.rollback |
| Import | 引入外部数据或另一个包中的规则,简化引用路径。 | import data.kubernetes.pods |
| Rule | 策略的核心逻辑单元,定义一组条件与结论。 | deny[msg] { ... } |
| Comment | 单行注释,以 # 开头。 |
# 这是注释 |
关键点: Rego 中的
data 是全局根命名空间,所有输入(input)和外部数据都挂载在此之下。理解 data 与 input 的区别是编写正确策略的第一步。
4.2 规则定义:完整规则与部分规则
规则是 Rego 策略的基本构建块。根据返回值的不同,规则分为 完整规则(Complete Rules) 和 部分规则(Partial Rules)。
4.2.1 完整规则
完整规则产生一个单一的布尔值或标量值。它类似于编程语言中的函数,只返回一个结果。如果规则体中的所有表达式都为真,则规则为真;否则为假。
# 完整规则:判断部署是否允许回滚
package deployment.rollback
default allow_rollback := false
allow_rollback {
input.metadata.annotations["rollback-enabled"] == "true"
input.spec.replicas > 0
}
4.2.2 部分规则
部分规则用于生成一组值(集合)或键值对(对象)。它们常用于收集所有违反策略的条目。在回滚护栏中,部分规则通常用于收集所有“拒绝”原因。
# 部分规则:收集所有拒绝回滚的原因(集合)
package deployment.rollback
deny[reason] {
input.metadata.annotations["rollback-enabled"] != "true"
reason := "回滚功能未在注解中启用"
}
deny[reason] {
input.spec.replicas == 0
reason := "副本数为0,无法执行回滚"
}
实践建议: 在流水线护栏中,优先使用部分规则(如
deny 集合)来聚合所有失败条件。这比使用多个完整规则更易于测试和调试,因为你可以一次性看到所有违反的策略点。
4.3 标量值与复合值
Rego 支持多种数据类型,分为标量值和复合值。掌握这些类型是进行数据查询和模式匹配的前提。
4.3.1 标量值
标量值是单一的值,不可再分。Rego 支持以下标量类型:
| 类型 | 描述 | 示例 |
|---|---|---|
| 字符串 | 双引号包裹的文本 | "production" |
| 数字 | 整数或浮点数 | 42, 3.14 |
| 布尔值 | 真或假 | true, false |
| 空值 | 表示缺失或未定义 | null |
4.3.2 复合值
复合值用于构建复杂的数据结构,是处理 Kubernetes 资源清单的核心工具。
- 对象(Object): 无序的键值对集合,类似于 JSON 对象。键通常是字符串,值可以是任意类型。
- 数组(Array): 有序的元素列表,索引从 0 开始。
- 集合(Set): 无序的唯一值集合,没有重复元素。集合是 Rego 中非常强大的特性,常用于去重和成员关系检查。
# 复合值示例
package examples
# 对象
deployment_info := {
"name": "nginx",
"namespace": "default",
"labels": {"app": "web", "env": "prod"}
}
# 数组
container_ports := [80, 443, 8080]
# 集合
allowed_namespaces := {"default", "kube-system", "production"}
常见陷阱: 在 Rego 中,集合 和 数组 的语法不同。集合使用空集符号
{} 但内部元素不能有重复;数组使用方括号 []。混淆两者会导致策略逻辑错误,尤其是在使用 == 进行精确匹配时。
4.4 Rego 规则与数据流关系图
下图展示了 Rego 规则如何与输入数据(input)和外部数据(data)交互,最终生成策略决策(deny/allow)。
4.5 标量与复合值在回滚场景中的应用
在回滚护栏策略中,标量值和复合值各有其典型用途。下表总结了常见的使用模式:
| 数据类型 | 回滚场景示例 | Rego 表达式 |
|---|---|---|
| 字符串 | 检查回滚目标版本标签 | input.spec.template.metadata.labels.version == "v1.2.3" |
| 数字 | 验证回滚后的副本数阈值 | input.spec.replicas >= 3 |
| 布尔值 | 判断是否强制回滚 | input.metadata.annotations["force-rollback"] == true |
| 对象 | 提取并比对容器资源限制 | input.spec.template.spec.containers[0].resources.limits.cpu |
| 数组 | 遍历所有容器检查镜像来源 | input.spec.template.spec.containers[_].image |
| 集合 | 检查回滚目标命名空间是否在白名单内 | allowed_ns := {"prod", "staging"}; input.metadata.namespace in allowed_ns |
核心原则: 在编写回滚护栏时,优先使用 集合 来定义允许列表或拒绝列表。集合的成员关系检查(
in 操作符)比数组的遍历更高效、更简洁,且天然去重,能有效减少策略中的冗余逻辑。
4.6 本章小结
本章建立了 Rego 语言的基础认知框架。你已掌握:
- Rego 的模块化结构:
package、import和rule的协作方式。 - 完整规则与部分规则的区别,以及部分规则在聚合拒绝原因中的优势。
- 标量值(字符串、数字、布尔、null)与复合值(对象、数组、集合)的定义与操作。
- 这些数据类型在回滚护栏场景中的具体映射关系。