4. OPA Gatekeeper 入门:Rego 策略语言基础、ConstraintTemplate 与 Constraint 概念
OPA Gatekeeper 是 Kubernetes 生态中最成熟的通用准入控制器之一。它将开放策略代理(OPA)的策略引擎与 Kubernetes 的 Admission Webhook 深度集成,允许集群管理员使用声明式 Rego 语言编写策略,并通过 CRD(Custom Resource Definition)进行管理。理解 Rego 语言基础、ConstraintTemplate 与 Constraint 的概念,是掌握 Gatekeeper 的核心前提。
4.1 Rego 策略语言基础
Rego 是一种为 OPA 量身定制的声明式查询语言。它并非传统的命令式编程语言,而是基于逻辑推理的规则引擎。在 Gatekeeper 中,Rego 用于定义“允许”或“拒绝”资源变更的条件。
4.1.1 Rego 核心概念
- 规则(Rules):Rego 的基本单元,形式为
rule_name = value { condition }。当条件满足时,规则被赋值为true或具体值。 - 文档(Documents):OPA 将输入数据(如 Kubernetes 资源对象)视为嵌套的 JSON 文档。Rego 通过点号(
.)访问文档中的字段,例如input.request.object.spec.replicas。 - 迭代(Iteration):使用
some关键字遍历数组或集合,例如some container in input.request.object.spec.containers。 - 内置函数(Built-in Functions):Rego 提供丰富的内置函数,如
count()、regex.match()、sprintf()等,用于数据处理和验证。
4.1.2 典型 Rego 策略结构
在 Gatekeeper 的 ConstraintTemplate 中,Rego 代码通常包含两个关键部分:violation 规则和 deny 规则。
package mylibrary
# violation 规则:当条件满足时,生成一条违规消息
violation[{"msg": msg}] {
# 条件逻辑
input.request.operation == "CREATE"
container := input.request.object.spec.containers[_]
not container.securityContext.runAsNonRoot
msg := sprintf("容器 %v 未设置 runAsNonRoot: true", [container.name])
}
# deny 规则(可选):直接返回 true/false 决定是否拒绝
deny[msg] {
# 条件逻辑
input.request.object.metadata.name == "forbidden-pod"
msg := "不允许创建名为 forbidden-pod 的 Pod"
}
violation 规则返回一个包含消息的数组。如果数组非空,Gatekeeper 会拒绝该请求并返回消息。如果数组为空,则请求被允许。
4.2 ConstraintTemplate 与 Constraint 概念
Gatekeeper 通过两个 CRD 将 Rego 策略与 Kubernetes 资源绑定:ConstraintTemplate 和 Constraint。这种分离设计实现了策略逻辑与策略实例的解耦。
4.2.1 ConstraintTemplate
ConstraintTemplate 是策略的“模板”,它定义了 Rego 逻辑、参数模式(parameters schema)以及如何将参数注入到 Rego 代码中。一个 ConstraintTemplate 可以被多个 Constraint 实例化。
| 字段 | 说明 | 示例 |
|---|---|---|
apiVersion |
固定为 templates.gatekeeper.sh/v1 |
templates.gatekeeper.sh/v1 |
kind |
固定为 ConstraintTemplate |
ConstraintTemplate |
spec.crd.spec.names.kind |
定义该模板生成的 CRD 名称(即 Constraint 的 kind) | K8sRequiredLabels |
spec.targets[0].rego |
包含 Rego 策略代码的字符串 | 见下方代码块 |
spec.targets[0].libs |
可选的 Rego 库代码,用于复用 | [] |
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
input.request.operation == "CREATE"
required_label := input.parameters.labels[_]
not input.request.object.metadata.labels[required_label]
msg := sprintf("缺少必需的标签: %v", [required_label])
}
4.2.2 Constraint
Constraint 是 ConstraintTemplate 的实例化对象。它通过 spec.match 字段指定策略的生效范围(如命名空间、资源类型),并通过 spec.parameters 字段传入具体参数。
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-label
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "production"
parameters:
labels:
- "team"
- "owner"
spec.match 和 spec.parameters 作为可配置字段,通过 Kustomize 的 patches 或 vars 实现环境差异化。
4.3 ConstraintTemplate 与 Constraint 的关系
下图展示了 ConstraintTemplate 与 Constraint 之间的逻辑关系,以及它们如何协同工作以实现准入控制。
4.4 策略执行流程
当 Kubernetes API Server 收到资源变更请求时,Gatekeeper 的 Webhook 会拦截该请求,并按照以下流程执行策略评估:
- 请求拦截:API Server 将 AdmissionReview 请求发送到 Gatekeeper Webhook。
- 匹配 Constraint:Gatekeeper 根据请求的资源类型、命名空间、操作等字段,匹配所有已安装的 Constraint。
- 加载 Rego:对于每个匹配的 Constraint,Gatekeeper 加载对应的 ConstraintTemplate 中的 Rego 代码,并将 Constraint 的
spec.parameters注入为input.parameters。 - 执行评估:OPA 引擎执行 Rego 规则,检查
violation或deny规则是否返回非空结果。 - 返回结果:如果存在违规,Gatekeeper 返回拒绝响应并附带消息;否则允许请求继续。
CREATE 和 UPDATE 操作。如果需要拦截 DELETE 或其他操作,必须在 ConstraintTemplate 的 Rego 代码中显式检查 input.request.operation。
4.5 常见 Rego 模式与最佳实践
| 模式 | Rego 示例 | 说明 |
|---|---|---|
| 检查标签存在 | not input.request.object.metadata.labels["app"] |
验证资源是否包含指定标签 |
| 遍历容器 | some container in input.request.object.spec.containers |
对 Pod 中的每个容器执行检查 |
| 正则匹配 | regex.match("^[a-z]+$", name) |
验证名称是否符合命名规范 |
| 参数化检查 | required_label := input.parameters.labels[_] |
从 Constraint 的 parameters 中读取动态值 |
| 排除特定命名空间 | input.request.object.metadata.namespace != "kube-system" |
跳过系统命名空间的检查 |
4.6 本章小结
OPA Gatekeeper 通过 Rego 语言提供了强大的策略定义能力,而 ConstraintTemplate 与 Constraint 的分离设计使得策略可以像 Kubernetes 原生资源一样被管理、版本化和复用。掌握 Rego 的基础语法和 Gatekeeper 的 CRD 模型,是后续在 Kustomize 中适配和组合准入策略的基石。