4. OPA 与 Kubernetes 集成:Admission Controller 机制、OPA Gatekeeper 安装、约束模板与约束

本章深入解析 OPA(Open Policy Agent)与 Kubernetes 集成的核心路径——通过 Admission Controller 机制实现策略即代码。我们将从 Kubernetes 准入控制链入手,逐步讲解 OPA Gatekeeper 的安装部署、约束模板(ConstraintTemplate)与约束(Constraint)的声明式定义,最终构建一个可扩展的策略执行层。

4.1 Kubernetes Admission Controller 机制

Kubernetes API Server 在处理资源请求时,会经过一系列内置与动态准入控制器(Admission Controller)的校验。OPA Gatekeeper 正是以 动态准入 Webhook 的形式嵌入这一链路,在资源持久化之前执行策略检查。

关键流程: 请求 → 认证 → 授权 → MutatingAdmissionWebhook(可选修改) → 对象模式验证 → ValidatingAdmissionWebhook(策略校验) → 持久化 etcd。

下表对比了两种动态准入 Webhook 在策略场景中的角色:

Webhook 类型 作用时机 OPA Gatekeeper 使用场景 典型操作
MutatingAdmissionWebhook 对象验证之前 自动注入标签、Sidecar、默认值 修改请求对象
ValidatingAdmissionWebhook 对象验证之后、持久化之前 安全策略、合规检查、资源配额校验 拒绝或允许请求
实践要点: Gatekeeper 默认只注册 ValidatingWebhookConfiguration,若需要变更操作(如自动添加标签),需额外配置 MutatingWebhookConfiguration 并启用 Gatekeeper 的突变功能。
Kubernetes API 请求准入链路与 OPA Gatekeeper 介入点 API 请求 认证 / 授权 Mutating Webhook Validating Webhook etcd OPA Gatekeeper 组件 • Gatekeeper-controller-manager:管理约束模板与约束 • Gatekeeper-audit:周期性审计现有资源合规性 • Webhook 服务:接收 AdmissionReview 并执行 Rego 策略 允许 / 拒绝

4.2 OPA Gatekeeper 安装

OPA Gatekeeper 以一组 Kubernetes 原生资源的形式部署,推荐使用 Helm Chart 或直接应用官方 YAML 清单。安装后,集群中会新增以下核心 CRD:

  • ConstraintTemplate:定义策略逻辑(Rego 代码)与参数 schema。
  • Constraint:实例化约束模板,指定匹配范围与参数。
  • Config:配置 Gatekeeper 的同步、排除命名空间等行为。
快速安装命令(Helm):
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace=gatekeeper-system --create-namespace

安装完成后,验证关键 Pod 与 CRD 是否就绪:

kubectl get pods -n gatekeeper-system
# 预期输出:gatekeeper-controller-manager-xxx  Running
#          gatekeeper-audit-xxx               Running

kubectl get crd | grep gatekeeper
# 预期输出:constrainttemplates.templates.gatekeeper.sh
#          constraints.constraints.gatekeeper.sh
#          configs.config.gatekeeper.sh
版本兼容性: Gatekeeper v3.14+ 要求 Kubernetes 1.22+。若集群版本较低,请选择对应兼容版本(如 v3.11.x 支持 1.19+)。安装前务必检查 kube-apiserver 的 --enable-admission-plugins 参数是否包含 MutatingAdmissionWebhook 和 ValidatingAdmissionWebhook。

4.3 约束模板(ConstraintTemplate)

约束模板是 Gatekeeper 策略的核心抽象,它封装了 Rego 策略逻辑和参数声明。一个模板可被多个约束实例化,实现策略复用。

以下是一个约束模板示例,用于强制所有 Pod 必须包含 app 标签:

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 := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("缺少必要标签: %v", [missing])
        }
字段 说明 示例值
spec.crd.spec.names.kind 约束的 CRD 名称,即后续创建约束时使用的 kind K8sRequiredLabels
spec.crd.spec.validation 定义约束实例可接受的参数 schema(OpenAPI v3) labels: array of string
spec.targets[].rego Rego 策略代码,violation 规则返回违规消息 检查缺失标签
Rego 调试技巧: 在约束模板中可以使用 input.review 访问 AdmissionReview 对象,input.parameters 获取约束实例传入的参数。推荐在本地使用 opa eval 命令配合测试数据验证 Rego 逻辑。

4.4 约束(Constraint)

约束是约束模板的实例化资源,它指定了策略的生效范围(通过 match 字段)和具体参数。一个约束模板可以对应多个约束,应用于不同的命名空间或资源类型。

基于上述 K8sRequiredLabels 模板,创建一个约束,要求所有命名空间 production 中的 Pod 必须包含 app 和 env 标签:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: pod-must-have-app-env
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces: ["production"]
  parameters:
    labels:
      - "app"
      - "env"

约束的 spec.match 支持丰富的选择器,下表列出常用匹配维度:

匹配字段 作用 示例
kinds 按资源类型匹配(支持 apiGroups 和 kinds 数组) [{apiGroups: [""], kinds: ["Pod"]}]
namespaces 按命名空间白名单匹配 ["production", "staging"]
excludedNamespaces 排除特定命名空间 ["kube-system"]
labelSelector 按资源标签选择器匹配 {matchLabels: {tier: "frontend"}}
namespaceSelector 按命名空间标签选择器匹配 {matchExpressions: [...]}
约束冲突与优先级: 当多个约束作用于同一资源时,Gatekeeper 会执行所有匹配的约束,只要任一约束判定违规,请求即被拒绝。建议在约束模板中设计清晰的 violation 消息,便于排查拒绝原因。
约束模板与约束的实例化关系 ConstraintTemplate k8srequiredlabels Rego 策略 + 参数 Schema Constraint 1 pod-must-have-app-env Constraint 2 deploy-must-have-team Constraint 3 ns-must-have-owner 实例化说明 • 每个 Constraint 引用 同一模板 • 可设置不同的 match 和 parameters • 模板更新后,所有 约束自动生效 • 约束可独立启用/ 禁用(通过 label)

4.5 策略生效验证与审计

部署约束后,可以通过创建违反策略的资源来验证 Gatekeeper 是否正常工作:

kubectl run test-pod --image=nginx -n production
# 预期输出:Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request: [pod-must-have-app-env] 缺少必要标签: {"app", "env"}

Gatekeeper 还内置了 审计(Audit) 功能,定期扫描集群中已有资源,将违反约束的资源记录在约束的 status 字段中:

kubectl get constraint pod-must-have-app-env -o jsonpath='{.status.violations}'
审计周期: 默认每 60 秒执行一次,可通过 Config 资源中的 spec.sync.syncOnly 和 spec.auditInterval 调整。审计结果不会自动删除违规资源,仅用于报告和告警触发。