2. OPA 与 Gatekeeper 基础

在 Kubernetes 集群中实施策略控制,OPA(Open Policy Agent)与 Gatekeeper 是业界最成熟的开源方案。本章从 OPA 架构出发,逐步深入到 Rego 语言、Gatekeeper 安装配置以及约束模板(ConstraintTemplate)的核心概念,为后续策略冲突排查与配额调整打下坚实基础。

2.1 OPA 架构

OPA 是一个通用的策略引擎,将策略从具体服务中解耦。其核心架构遵循“策略即代码”理念,通过统一的决策接口对外提供服务。

OPA 架构图 OPA 架构图 外部请求 服务层 (K8s API) OPA 策略引擎 决策接口 策略存储 Rego 策略 数据输入 说明: 1. 外部请求(如 K8s API 调用)被服务层拦截。 2. 服务层向 OPA 引擎发送决策查询(Query)。 3. OPA 引擎加载 Rego 策略和数据输入,返回 Allow/Deny 决策。

核心要点:OPA 通过“查询-决策”模型工作,不直接修改资源,只返回策略评估结果。这种解耦设计使得策略变更不影响服务本身。

2.2 Rego 语言简介

Rego 是 OPA 专用的声明式策略语言,灵感来源于 Datalog。它专注于描述“策略规则”,而非“如何执行”。

2.2.1 Rego 基础语法

概念 语法示例 说明
规则定义 allow { input.replicas < 5 } 当条件满足时,规则为真
变量赋值 max_replicas := 10 使用 := 进行局部赋值
数组/对象遍历 some i; input.containers[i] 使用 some 关键字迭代
内置函数 count(input.containers) > 1 如 count、split、regex.match
否定 not input.readOnlyRootFilesystem 使用 not 表示条件不成立

2.2.2 一个完整的 Rego 策略示例

package kubernetes.admission

# 拒绝所有 replicas 超过 3 的 Deployment
deny[msg] {
    input.request.kind.kind == "Deployment"
    input.request.object.spec.replicas > 3
    msg := sprintf("Deployment %v 的副本数 %v 超过最大限制 3", 
                   [input.request.object.metadata.name, 
                    input.request.object.spec.replicas])
}

# 允许所有符合规则的请求
allow {
    not deny[_]
}

提示:Rego 策略通常包含 deny 和 allow 规则。Gatekeeper 默认使用 deny 规则来拒绝违规请求,allow 规则用于显式放行。

2.3 Gatekeeper 安装与配置

Gatekeeper 是 OPA 在 Kubernetes 上的原生集成方案,以 Admission Webhook 的形式运行。安装过程分为 Helm 和 YAML 两种方式。

2.3.1 安装方式对比

方式 命令/步骤 适用场景
Helm helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper/gatekeeper --generate-name
生产环境,便于版本管理和升级
YAML 直接部署 kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml 测试环境或离线部署

2.3.2 验证安装

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

# 查看 Webhook 配置
kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io gatekeeper-validating-webhook-configuration

注意:Gatekeeper 安装后默认不会拒绝任何请求,需要先创建约束模板(ConstraintTemplate)和约束(Constraint)才能生效。安装完成后请立即检查 Webhook 是否正常注册。

2.4 约束模板(ConstraintTemplate)概念

约束模板是 Gatekeeper 的核心抽象,它定义了一类策略的“骨架”。约束模板使用 Rego 编写,描述策略的评估逻辑;而约束(Constraint)则是模板的具体实例,提供参数化配置。

约束模板与约束关系图 约束模板与约束关系图 ConstraintTemplate kind: ConstraintTemplate spec.crd.spec.names.kind: "K8sRequiredLabels" targets[0].rego: (策略逻辑) Constraint apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sRequiredLabels spec.match: (资源选择器) 实例化 关键区别: • ConstraintTemplate:定义策略逻辑(Rego 代码),是全局的、不可参数化的模板。 • Constraint:使用模板创建的具体策略实例,可配置参数(如标签键值、副本数上限)。 • 一个模板可以被多个约束引用,每个约束针对不同的资源范围或参数。

2.4.1 约束模板示例

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels

        violation[{"msg": msg}] {
            input.request.kind.kind == "Deployment"
            required_label := input.parameters.labels[_]
            not input.request.object.metadata.labels[required_label]
            msg := sprintf("Deployment %v 缺少必需标签 %v", 
                           [input.request.object.metadata.name, required_label])
        }

2.4.2 约束实例示例

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: deployment-must-have-team-label
spec:
  match:
    kinds:
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
    namespaces: ["production"]
  parameters:
    labels:
      - "team"

实践要点:在集群升级前,务必检查所有约束模板和约束是否兼容新版本 API。例如,Kubernetes 1.22 移除了 admission.k8s.io/v1beta1,Gatekeeper 3.7+ 已适配 v1 版本。约束模板中的 Rego 代码应避免使用已废弃的字段。

2.5 本章小结

  • OPA 架构:策略引擎与业务解耦,通过查询-决策模型工作。
  • Rego 语言:声明式策略语言,核心是 deny/allow 规则。
  • Gatekeeper:Kubernetes 原生策略控制器,通过 Admission Webhook 拦截请求。
  • 约束模板:策略逻辑的抽象层,约束是具体实例,支持参数化配置。