OPA多集群策略配置迁移与发布门禁 - 第4节

4.1 Gatekeeper 概述与架构

Gatekeeper 是 Kubernetes 生态中最成熟的 OPA 集成方案,它将 OPA 策略引擎以 Admission Webhook 的形式嵌入集群,实现声明式策略的校验与强制执行。作为多集群变更门禁的核心组件,Gatekeeper 提供了策略模板化、约束实例化、审计与自动化修复等能力。

4.1.1 核心架构组件

Gatekeeper 由以下关键组件构成,它们协同工作以拦截并验证所有符合 API 资源的变更请求:

组件 部署形态 职责
Gatekeeper Controller Deployment(通常 2 副本) 管理 ConstraintTemplate 与 Constraint 的 CRD 生命周期,监听策略变更并同步至 OPA
Gatekeeper Webhook ValidatingWebhookConfiguration 拦截 CREATE / UPDATE 请求,将对象与已加载的策略进行匹配校验
OPA Engine(内置) 嵌入 Controller 进程 执行 Rego 策略评估,返回 allow / deny 决策
Audit 组件 Controller 内定时任务 周期性扫描集群现有资源,标记违反策略的资源并更新 Constraint 状态
架构要点: Gatekeeper 不依赖外部 OPA 服务,OPA 引擎以内嵌库形式运行在 Controller 进程中,减少了网络延迟与运维复杂度。所有策略数据通过 CRD 持久化,无需额外存储。

4.1.2 架构交互流程

下图展示了 Gatekeeper 在 Kubernetes API 请求链路中的位置与核心交互关系:

Gatekeeper 架构交互流程 kubectl / 客户端 API Server ValidatingWebhook Gatekeeper Controller (内嵌 OPA 引擎) ConstraintTemplate Constraint Audit 定时扫描 创建/更新 AdmissionReview 调用 读取模板 实例化 触发 状态回写 💡 请求路径:客户端 → API Server → ValidatingWebhook → Gatekeeper Controller(OPA 评估)→ 返回 allow/deny 审计路径:Controller 定时扫描集群已有资源,对比 Constraint 规则,更新违反状态。
关键理解: Gatekeeper 的 Webhook 仅拦截 变更请求(CREATE / UPDATE),不会拦截 LIST / WATCH / DELETE 请求。审计组件则负责发现集群中已存在的违规资源,弥补 Webhook 只拦截变更的不足。

4.2 安装部署

Gatekeeper 支持 Helm 和静态 YAML 两种部署方式。本节以 Helm 3 为例,展示标准安装步骤。

4.2.1 前置条件

  • Kubernetes 集群版本 ≥ 1.19(推荐 1.24+)
  • Helm 3.2.0+
  • 集群管理员权限(创建 CRD、Webhook、ClusterRole)
  • 确保集群已启用 admissionregistration.k8s.io/v1 API

4.2.2 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 constraintViolationsLimit=100

4.2.3 验证安装

# 检查 Pod 状态
kubectl get pods -n gatekeeper-system

# 预期输出示例
NAME                                             READY   STATUS    RESTARTS   AGE
gatekeeper-audit-5d8f7c6b9f-abc12                1/1     Running   0          2m
gatekeeper-controller-manager-6b9f7c8d9-def34    1/1     Running   0          2m
gatekeeper-controller-manager-6b9f7c8d9-ghi56    1/1     Running   0          2m

# 检查 CRD 是否注册
kubectl get crd | grep gatekeeper

# 预期输出
constrainttemplates.templates.gatekeeper.sh   2024-01-15T10:00:00Z
constraints.constraints.gatekeeper.sh         2024-01-15T10:00:00Z
安装注意事项:
  • Gatekeeper 会创建 ValidatingWebhookConfiguration,默认拦截所有命名空间的 CREATE/UPDATE 请求。建议在安装前确认集群没有其他冲突的 Webhook 配置。
  • 生产环境建议将 Controller 副本数设为 2 或 3,并配置 PodAntiAffinity 以分散到不同节点。
  • 审计间隔(auditInterval)默认 60 秒,可根据集群规模适当调整,避免频繁扫描造成 API Server 压力。

4.3 ConstraintTemplate 与 Constraint 概念

Gatekeeper 的策略体系建立在两个核心 CRD 之上:ConstraintTemplate 和 Constraint。理解二者的关系是编写 Gatekeeper 策略的基础。

4.3.1 概念对比

维度 ConstraintTemplate Constraint
类比 编程语言中的 类(Class) 类的 实例(Instance)
定义内容 Rego 策略逻辑 + 参数 Schema 具体参数值 + 目标资源选择器
作用域 集群级别(Cluster-scoped) 集群级别,但可通过 spec.match 限定命名空间
是否可复用 是,一个模板可被多个 Constraint 引用 每个 Constraint 对应一个策略规则
更新影响 更新模板会重新编译所有引用它的 Constraint 更新 Constraint 仅影响该规则

4.3.2 关系示意图

下图展示了 ConstraintTemplate 与 Constraint 之间的“模板-实例”关系,以及它们如何共同作用于资源校验:

ConstraintTemplate 与 Constraint 关系 ConstraintTemplate (策略模板定义) Rego 策略逻辑(violation 规则) 参数 Schema(parameters 定义) 目标资源类型(target 字段) 实例化 Constraint (策略实例) spec.enforcementAction: deny / dryrun spec.match: 限定命名空间 / 资源类型 spec.parameters: 传入模板的具体参数值 💡 一个 ConstraintTemplate 可被多个 Constraint 引用,每个 Constraint 传入不同的参数和匹配规则。
核心理解: ConstraintTemplate 定义“做什么检查”(Rego 逻辑),Constraint 定义“对谁做检查”(match)以及“检查的阈值是多少”(parameters)。这种分离使得策略逻辑与配置解耦,便于在多集群间复用模板,仅需调整 Constraint 参数即可适配不同集群的合规要求。

4.4 第一个约束示例

本节通过一个完整的示例,演示如何创建 ConstraintTemplate 和 Constraint,实现“禁止在 default 命名空间部署 Pod”的策略。

4.4.1 创建 ConstraintTemplate

首先定义 Rego 策略模板,该模板接收一个 disallowedNamespaces 参数,检查资源是否属于被禁止的命名空间:

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: block-default-namespace
spec:
  crd:
    spec:
      names:
        kind: BlockDefaultNamespace  # Constraint 的 CRD 名称
      validation:
        openAPIV3Schema:
          type: object
          properties:
            disallowedNamespaces:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package block_default_namespace

        violation[{"msg": msg}] {
          # 获取 Constraint 中传入的参数
          disallowed := input.parameters.disallowedNamespaces[_]
          # 检查资源所在的命名空间是否在禁止列表中
          input.review.object.metadata.namespace == disallowed
          # 构造违规消息
          msg := sprintf("命名空间 '%v' 不允许部署资源,请使用其他命名空间", [disallowed])
        }

4.4.2 创建 Constraint

基于上述模板,创建一个 Constraint 实例,指定禁止 default 和 kube-system 命名空间:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: BlockDefaultNamespace
metadata:
  name: block-default-and-kube-system
spec:
  enforcementAction: deny  # deny 表示拒绝请求;dryrun 仅记录不拒绝
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    # 不指定 namespaces 表示匹配所有命名空间
  parameters:
    disallowedNamespaces:
      - "default"
      - "kube-system"

4.4.3 测试策略效果

部署上述两个 YAML 文件后,尝试在 default 命名空间创建 Pod:

# 应用模板和约束
kubectl apply -f constraint-template.yaml
kubectl apply -f constraint.yaml

# 测试:在 default 命名空间创建 Pod
kubectl run test-pod --image=nginx --namespace=default

# 预期输出(被拒绝)
Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request:
[block-default-and-kube-system] 命名空间 'default' 不允许部署资源,请使用其他命名空间

# 测试:在合法命名空间创建 Pod(需先创建 ns)
kubectl create ns allowed-ns
kubectl run test-pod --image=nginx --namespace=allowed-ns

# 预期输出:Pod 创建成功
pod/test-pod created

4.4.4 查看约束状态

# 查看 Constraint 的详细状态,包括审计结果
kubectl get constraint block-default-and-kube-system -o yaml

# 关键字段说明
# status.byPod[].constraintUID: 当前约束的 UID
# status.byPod[].enforced: true 表示策略已生效
# status.auditTimestamp: 最近一次审计时间
# status.violations: 审计发现的违规资源列表
快速验证技巧: 在创建 Constraint 后,可以使用 kubectl get constraint 查看所有约束实例。如果 enforced 状态为 true,说明策略已成功加载到 OPA 引擎。对于已有资源,Gatekeeper 的审计组件会在下一个审计周期(默认 60 秒)后更新 violations 列表。
常见错误排查:
  • 如果 Constraint 创建后 enforced 为 false,检查 ConstraintTemplate 的 Rego 语法是否正确,可通过 kubectl logs -n gatekeeper-system <controller-pod> 查看错误日志。
  • 确保 Constraint 的 spec.match.kinds 中指定的 apiGroups 和 kinds 与实际资源匹配。例如,核心 API 组的 apiGroups 为 ""(空字符串),而不是 v1。
  • 如果 Webhook 未生效,检查 ValidatingWebhookConfiguration 是否被其他组件修改或删除。

4.5 本章小结

通过本章学习,你已经掌握了 Gatekeeper 的核心概念与操作流程:

  • 架构理解: Gatekeeper 以内嵌 OPA 引擎的 Admission Webhook 形式运行,由 Controller、Webhook、审计组件协同工作。
  • 安装部署: 使用 Helm 3 可快速部署生产级 Gatekeeper 实例,注意副本数与审计间隔的配置。
  • 策略模型: ConstraintTemplate 定义 Rego 逻辑与参数 Schema,Constraint 提供具体参数与匹配规则,二者构成“模板-实例”关系。
  • 实战验证: 通过“禁止 default 命名空间部署 Pod”的示例,完整走通了从模板定义到约束生效的流程。