3. OPA Gatekeeper 入门:OPA 与 Rego 语言简介、Gatekeeper 架构、安装与部署

3.1 OPA 与 Rego 语言简介

Open Policy Agent (OPA) 是一个开源的、通用策略引擎,它将策略决策与业务逻辑解耦。OPA 通过一种高级声明式语言 Rego 来表达策略,使得策略的编写、审计和更新不再依赖特定的应用代码。

Rego 语言的核心思想是:策略即代码。它将输入数据(Input)与系统状态(Data)进行匹配,输出一个布尔值或结构化数据作为决策结果。Rego 并非图灵完备的通用编程语言,而是专为策略评估设计的领域特定语言(DSL),这保证了策略的可读性和可分析性。

核心概念对比:传统策略 vs OPA 策略
维度 传统策略(硬编码) OPA 策略(Rego)
部署方式 嵌入应用代码,随应用发布 独立部署,通过 API 调用
更新频率 需要重新编译、构建、部署 热加载,无需重启服务
可读性 依赖编程语言,非技术人员难以理解 声明式规则,接近自然语言
审计能力 日志分散,难以追溯 内置决策日志,可追溯每次评估

以下是一个简单的 Rego 规则示例,用于检查容器镜像是否来自允许的仓库:

package kubernetes.admission

# 定义允许的镜像仓库前缀
allowed_repos := ["docker.io/library/", "gcr.io/my-company/"]

# 默认拒绝
default allow := false

# 规则:如果镜像前缀在允许列表中,则允许
allow {
    input.request.object.spec.containers[_].image
    startswith(input.request.object.spec.containers[_].image, allowed_repos[_])
}

# 规则:如果镜像前缀不在允许列表中,则拒绝并返回消息
deny[msg] {
    container := input.request.object.spec.containers[_]
    not startswith(container.image, allowed_repos[_])
    msg := sprintf("镜像 '%v' 来自未授权的仓库", [container.image])
}

3.2 Gatekeeper 架构

Gatekeeper 是 OPA 在 Kubernetes 生态中的原生集成方案。它不是一个独立的 OPA 实例,而是一个 Kubernetes 准入控制器 Webhook,将 OPA 的策略评估能力无缝嵌入到 API Server 的资源处理流程中。

Gatekeeper 的架构由三个核心组件构成:

  • API Server 扩展:通过 ValidatingWebhookConfiguration 和 MutatingWebhookConfiguration 注册到 Kubernetes 集群。
  • Gatekeeper 控制器:运行在集群内的 Pod 中,负责监听策略资源(ConstraintTemplate、Constraint)的变化,并动态编译 Rego 策略。
  • OPA 引擎:内嵌在 Gatekeeper 控制器中,用于执行策略评估。
关键设计理念:Gatekeeper 将策略定义(ConstraintTemplate)与策略实例化(Constraint)分离。ConstraintTemplate 定义 Rego 逻辑和参数 schema,Constraint 则提供具体的参数值并触发评估。这种设计使得策略可以像 Kubernetes 资源一样被版本管理和复用。
Gatekeeper 架构组件与数据流 Kubernetes API Server 创建/更新 Pod、Service 等 ValidatingWebhook Configuration MutatingWebhook Configuration Gatekeeper 控制器 (Pod) 监听 ConstraintTemplate / Constraint 编译 Rego 策略并缓存 OPA 引擎 (内嵌) 执行 Rego 策略评估 策略资源 ConstraintTemplate Constraint 决策结果 allow / deny + 结构化消息

3.3 安装与部署

Gatekeeper 的部署方式非常灵活,推荐使用 Helm Chart 进行生产级安装。以下步骤演示了如何在标准 Kubernetes 集群上部署 Gatekeeper v3.x。

3.3.1 前置条件

  • Kubernetes 集群版本 >= 1.16(支持 admissionregistration.k8s.io/v1)。
  • 集群已安装 Helm v3。
  • 集群管理员权限(用于创建 ClusterRole 和 Webhook 配置)。

3.3.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

3.3.3 验证安装

安装完成后,检查 Pod 和 Webhook 配置是否正常:

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

# 预期输出示例:
# NAME                                             READY   STATUS    RESTARTS   AGE
# gatekeeper-audit-5d8f7c6b9f-2x7k4               1/1     Running   0          2m
# gatekeeper-controller-manager-6f9c8d7c5b-4j2m9   1/1     Running   0          2m
# gatekeeper-controller-manager-6f9c8d7c5b-9k3p1   1/1     Running   0          2m

# 检查 Webhook 配置
kubectl get validatingwebhookconfigurations
# 预期输出:gatekeeper-validating-webhook-configuration

kubectl get mutatingwebhookconfigurations
# 预期输出:gatekeeper-mutating-webhook-configuration
常见问题:如果 Gatekeeper Pod 启动失败,请检查集群是否安装了 cert-manager,或者手动签发 TLS 证书。Gatekeeper 默认使用 cert-manager 管理 Webhook 证书。如果集群没有 cert-manager,可以在 Helm 安装时设置 --set webhook.certManager.enabled=false,并自行提供证书 Secret。

3.3.4 部署选项对比

部署方式 复杂度 生产推荐度 说明
Helm Chart 低 ★★★★★ 官方维护,支持参数化配置,自动处理证书
静态 YAML 中 ★★★☆☆ 适合离线环境,但升级和配置管理较繁琐
Operator 高 ★★☆☆☆ 社区方案,功能与 Helm 类似,但维护成本高

3.4 快速验证:部署一个简单的约束

安装完成后,可以通过部署一个 ConstraintTemplate 和 Constraint 来验证 Gatekeeper 是否正常工作。以下示例强制要求所有 Pod 必须包含 owner 标签。

# 1. 定义 ConstraintTemplate
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}] {
          provided := input.request.object.metadata.labels
          required := input.parameters.labels[_]
          not required == provided[_]
          msg := sprintf("缺少必需的标签: %v", [required])
        }
---
# 2. 实例化 Constraint
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: pod-must-have-owner
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    labels: ["owner"]

应用上述 YAML 后,尝试创建一个没有 owner 标签的 Pod,API Server 将拒绝该请求,并返回 Gatekeeper 定义的违规消息。

Gatekeeper 策略生命周期 1. 定义 编写 Rego 规则 创建 ConstraintTemplate 2. 部署 kubectl apply 创建 Constraint 实例 3. 评估 API Server 触发 Webhook OPA 执行 Rego 规则 4. 响应 允许 / 拒绝 返回违规消息 关键资源类型 ConstraintTemplate: 策略模板 Constraint: 策略实例 + 参数
生产建议:在部署 Gatekeeper 到生产环境前,建议先在测试集群中启用 --set auditFromCache=false 进行全量审计,以发现现有工作负载中的策略违规。同时,为 Gatekeeper 控制器配置 PodAntiAffinity 和 PDB,确保高可用。