4. OPA Gatekeeper 概述:架构、Webhook 与 Rego 策略语言

OPA Gatekeeper 是 Kubernetes 生态中最成熟的 策略即代码 实现方案。它基于 开放策略代理(OPA) 引擎,通过 Admission Webhook 机制拦截所有资源变更请求,并使用 Rego 策略语言 编写声明式规则,最终决定请求是允许还是拒绝。本章将拆解 Gatekeeper 的核心架构、Webhook 工作流程以及 Rego 语言的核心概念。

4.1 Gatekeeper 架构总览

Gatekeeper 以 Operator 模式 运行在 Kubernetes 集群内,由三个核心组件构成:

组件 部署形态 核心职责
Gatekeeper Controller Deployment(通常 1 副本) 监听 ConstraintTemplate 和 Constraint 自定义资源,编译 Rego 策略并缓存;管理 Webhook 配置的注入与更新。
Gatekeeper Webhook Deployment(建议 2+ 副本) 接收 APIServer 发起的 AdmissionReview 请求,执行 Rego 策略评估,返回 allowed 或 denied 结果。
Gatekeeper Audit 周期性 Job / 常驻 Pod 对集群中已有资源进行 事后审计,标记违反策略的资源,并写入 Constraint 对象的 status 字段。
关键设计原则: Gatekeeper 将策略定义(ConstraintTemplate)与策略实例(Constraint)分离。前者是 Rego 代码的模板,后者是带有具体参数(如故障域标签值)的实例化对象。这种设计使得策略逻辑可复用,参数可灵活配置。
OPA Gatekeeper 核心架构组件关系图 OPA Gatekeeper 核心架构 Kubernetes API Server AdmissionReview 请求 Gatekeeper Webhook 策略评估引擎 Gatekeeper Controller 策略编译 & 缓存 Gatekeeper Audit 事后审计扫描 自定义资源 ConstraintTemplate Constraint Config (策略定义/实例) 数据流方向 APIServer → Webhook Controller ↔ CRDs

4.2 Admission Webhook 工作原理

Kubernetes 提供了两种 Webhook 钩子来扩展准入控制流程:

  • MutatingAdmissionWebhook:在对象持久化之前,允许修改(mutate)请求对象。Gatekeeper 默认不使用此钩子,但可通过 mutations 功能扩展。
  • ValidatingAdmissionWebhook:在对象持久化之前,验证请求是否合规。Gatekeeper 的核心准入控制基于此钩子实现。

一个完整的 Webhook 请求处理流程包含以下步骤:

  1. 用户发起请求:kubectl apply -f pod.yaml 或 API 调用。
  2. APIServer 路由:请求到达 APIServer,经过身份认证、鉴权后,进入准入控制链。
  3. Webhook 拦截:APIServer 根据 ValidatingWebhookConfiguration 中配置的规则(匹配资源、操作、命名空间等),将请求封装为 AdmissionReview 对象,通过 HTTPS POST 发送给 Gatekeeper Webhook 服务。
  4. 策略评估:Gatekeeper Webhook 从请求中提取对象内容,与已缓存的 Rego 策略进行匹配和评估。
  5. 返回结果:Webhook 返回 AdmissionReview 响应,包含 allowed: true/false 以及可选的 status.message(拒绝原因)。
  6. 最终处理:APIServer 根据 Webhook 的响应决定是允许对象写入 etcd,还是拒绝并返回错误给用户。
性能考量: Webhook 的超时时间默认为 30 秒。如果 Gatekeeper 响应超时或服务不可用,APIServer 的行为由 failurePolicy 决定:Fail(拒绝所有请求,集群进入“防崩溃”模式)或 Ignore(跳过 Webhook,允许请求通过)。生产环境建议设置为 Fail 并确保 Webhook 高可用。
ValidatingAdmissionWebhook 请求处理流程 ValidatingAdmissionWebhook 请求处理流程 用户 / kubectl API Server Webhook 配置 Gatekeeper Rego 策略缓存 允许 / 拒绝 返回 AdmissionReview

4.3 Rego 策略语言简介

Rego 是 OPA 项目专门设计的 声明式查询语言,灵感来源于 Datalog。它并非通用编程语言,而是专注于 策略决策 的领域特定语言(DSL)。在 Gatekeeper 中,所有策略逻辑都用 Rego 编写。

4.3.1 核心概念

概念 说明 Gatekeeper 中的角色
规则(Rule) 形如 rule_name = value { condition } 的声明,当条件为真时,规则被赋值。 定义策略的评估逻辑,如 violation[msg] { ... }。
查询(Query) 对规则进行求值,返回所有满足条件的绑定。 Gatekeeper 引擎自动执行查询,检查是否有 violation 规则被触发。
输入(input) 表示当前被评估的 Kubernetes 对象(AdmissionReview 中的 Object)。 通过 input.review.object 访问 Pod、Namespace 等资源字段。
数据(data) 表示外部数据,包括集群中的其他资源、参数等。 通过 data.inventory 访问集群资源;通过 data.parameters 访问 Constraint 参数。

4.3.2 一个简单的 Rego 策略示例

以下策略检查 Pod 是否设置了 failure-domain.beta.kubernetes.io/zone 标签:

package k8s.faultdomain

violation[msg] {
  # 获取输入对象
  obj := input.review.object
  # 检查是否为 Pod
  obj.kind == "Pod"
  # 检查标签是否存在
  not obj.metadata.labels["failure-domain.beta.kubernetes.io/zone"]
  # 构造违规消息
  msg := sprintf("Pod '%v' 缺少故障域标签 'failure-domain.beta.kubernetes.io/zone'", [obj.metadata.name])
}
常见陷阱: Rego 中的 = 是 赋值/统一 操作符,而非比较。比较应使用 == 或 !=。另外,Rego 默认所有变量都是 不可变 的,循环依赖递归实现,而非 for 循环。

4.3.3 Rego 在 Gatekeeper 中的执行上下文

在 Gatekeeper 的 ConstraintTemplate 中,Rego 代码被包裹在一个固定的框架内:

  • package:必须声明包名,通常遵循 k8s.<category> 命名规范。
  • violation 规则:这是 Gatekeeper 约定的入口规则。如果 violation 规则被触发(即产生至少一条消息),则请求被拒绝。
  • 参数注入:通过 data.parameters 访问用户在 Constraint 对象中定义的参数,实现策略的差异化配置。

下表总结了 Rego 与常见编程语言的关键差异:

特性 Rego Python / Go
编程范式 声明式(逻辑编程) 命令式 / 面向对象
变量可变性 不可变(一次赋值) 可变
循环结构 集合推导(Comprehension) for / while
副作用 无副作用(纯函数) 允许 I/O、状态修改
错误处理 规则未定义即返回 false try / except / panic
学习建议: 对于有 Python 或 Go 背景的开发者,Rego 的集合推导式(如 [x | x := array[_]; condition])是最容易上手的切入点。建议先在 OPA Playground 中练习基础语法,再编写 Gatekeeper 策略。