3. Gatekeeper 概述:OPA/Gatekeeper 架构、约束模板与约束概念、安装与部署
3.1 OPA 与 Gatekeeper 的定位
在云原生灾备准入策略评审中,Kubernetes 原生 RBAC 与 Admission Webhook 只能提供基础的“允许/拒绝”判断,无法表达复杂的策略逻辑。Open Policy Agent(OPA)与 Gatekeeper 的组合填补了这一空白:OPA 提供通用的策略引擎,Gatekeeper 将其封装为 Kubernetes 原生的准入控制器。
| 组件 | 角色 | 在灾备准入中的价值 |
|---|---|---|
| OPA | 通用策略引擎(Rego 语言) | 定义灾备资源(如 Velero 备份、VolumeSnapshot)的合规规则 |
| Gatekeeper | Kubernetes 原生准入 Webhook + 策略控制器 | 将 OPA 策略注入集群,拦截并验证灾备资源的创建/更新请求 |
| ConstraintTemplate | 策略模板(CRD) | 封装 Rego 逻辑,定义灾备策略的通用骨架 |
| Constraint | 策略实例(CR) | 为特定命名空间或资源类型设定具体的灾备约束参数 |
关键理解:OPA 是策略引擎的“大脑”,Gatekeeper 是“手脚”,ConstraintTemplate 是“模具”,Constraint 是“成品”。在灾备场景中,这四层共同确保每一次备份策略变更都经过合规校验。
3.2 OPA/Gatekeeper 架构
Gatekeeper 以 Deployment 形式运行在集群中,监听 AdmissionReview 请求,并通过 OPA 引擎执行 Rego 策略。下图展示了请求从 API Server 到策略决策的完整路径:
架构要点:Gatekeeper 作为动态准入 Webhook,在资源持久化之前拦截请求。OPA 引擎根据 ConstraintTemplate 中定义的 Rego 规则和 Constraint 中传入的参数,返回
true(允许)或 false(拒绝)。灾备场景下,这一机制可防止未授权的备份策略变更、不合规的存储类选择或缺少必要标签的备份任务。
3.3 约束模板(ConstraintTemplate)与约束(Constraint)
ConstraintTemplate 和 Constraint 是 Gatekeeper 策略体系的两大核心 CRD。理解它们的区别是编写灾备准入策略的基础。
| 维度 | ConstraintTemplate | Constraint |
|---|---|---|
| 类型 | Cluster-scoped CRD | Cluster-scoped CR(实例) |
| 职责 | 定义 Rego 策略逻辑与参数 schema | 为模板提供具体参数值并作用于目标资源 |
| 灾备示例 | 检查备份资源是否包含 backup-retention 标签 |
要求 production 命名空间的备份保留期 ≥ 30 天 |
| 复用性 | 一个模板可被多个 Constraint 引用 | 每个 Constraint 绑定一个模板 |
| 更新影响 | 修改模板会影响所有引用它的 Constraint | 修改 Constraint 只影响当前策略实例 |
以下是一个灾备场景的 ConstraintTemplate 示例,用于验证 Velero Backup 资源是否包含必需的标签:
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredbackuplabels
spec:
crd:
spec:
names:
kind: K8sRequiredBackupLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredbackuplabels
violation[{"msg": msg}] {
input.review.object.kind == "Backup"
input.review.object.apiVersion == "velero.io/v1"
provided_labels := {label | input.review.object.metadata.labels[label]}
required_labels := {label | label := input.parameters.labels[_]}
missing_labels := required_labels - provided_labels
count(missing_labels) > 0
msg := sprintf("缺少必需的备份标签: %v", [missing_labels])
}
对应的 Constraint 实例,为 production 命名空间设定具体标签要求:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredBackupLabels
metadata:
name: prod-backup-label-constraint
spec:
match:
kinds:
- apiGroups: ["velero.io"]
kinds: ["Backup"]
namespaces: ["production"]
parameters:
labels:
- "backup-retention"
- "backup-schedule"
常见陷阱:ConstraintTemplate 中的 Rego 代码必须严格匹配目标资源的 GVK(Group/Version/Kind)。灾备资源(如 Velero Backup)的 apiVersion 可能随版本变化,务必在 Rego 中正确声明,否则策略会静默失效。
3.4 Gatekeeper 安装与部署
Gatekeeper 的部署方式主要有两种:Helm Chart 和静态 YAML。在生产环境中推荐使用 Helm,便于版本管理和参数定制。
3.4.1 使用 Helm 安装
# 添加 Gatekeeper Helm 仓库
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
# 更新仓库
helm repo update
# 安装 Gatekeeper(默认命名空间 gatekeeper-system)
helm install gatekeeper/gatekeeper \
--name-template gatekeeper \
--namespace gatekeeper-system \
--create-namespace \
--set replicas=2 \
--set auditInterval=60 \
--set logLevel=INFO
3.4.2 使用静态 YAML 安装
# 下载最新 release 的 YAML
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
3.4.3 验证安装
安装完成后,检查关键组件是否正常运行:
# 查看 Pod 状态
kubectl get pods -n gatekeeper-system
# 预期输出示例:
# NAME READY STATUS RESTARTS AGE
# gatekeeper-audit-5d8f9c6b7f-abc12 1/1 Running 0 2m
# gatekeeper-controller-manager-7f9c8d6e5-xyz34 1/1 Running 0 2m
# 查看 CRD 是否注册
kubectl get crd | grep gatekeeper
# 预期输出包含:
# constrainttemplates.templates.gatekeeper.sh
# constraints.constraints.gatekeeper.sh
# configs.config.gatekeeper.sh
| 组件 | 功能 | 灾备相关配置建议 |
|---|---|---|
| gatekeeper-controller-manager | 处理准入请求,执行 Rego 策略 | 生产环境至少 2 副本;灾备集群建议 3 副本 |
| gatekeeper-audit | 定期审计已有资源,标记违反策略的对象 | 设置 auditInterval=60(秒),及时发现存量违规 |
| gatekeeper-webhook | 注册 ValidatingWebhookConfiguration | 灾备场景建议开启 failurePolicy=Fail,防止策略绕过 |
灾备部署建议:在灾备集群中部署 Gatekeeper 时,建议将
auditFromCache 设置为 true,减少对 API Server 的重复查询。同时,为 Gatekeeper 组件配置 PodDisruptionBudget,确保灾备切换期间策略引擎持续可用。