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 资源一样被版本管理和复用。
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 到生产环境前,建议先在测试集群中启用
--set auditFromCache=false 进行全量审计,以发现现有工作负载中的策略违规。同时,为 Gatekeeper 控制器配置 PodAntiAffinity 和 PDB,确保高可用。