3. OPA Gatekeeper入门:OPA与Rego语言基础、Gatekeeper架构、安装与部署
在云原生安全策略引擎的版图中,OPA(Open Policy Agent)与 Gatekeeper 的组合是业界最成熟的策略即代码实现方案之一。本章将带你从零掌握 OPA 的核心概念、Rego 策略语言的基本语法,理解 Gatekeeper 在 Kubernetes 集群中的架构定位,并完成完整的安装与部署流程。
3.1 OPA 核心概念与策略即代码
OPA 是一个开源的、通用的策略引擎,它将策略决策与业务逻辑解耦。OPA 不负责执行策略,而是根据输入数据(Input)和策略规则(Policy)输出决策结果(Decision)。
| 概念 | 说明 | 类比 |
|---|---|---|
| Policy(策略) | 用 Rego 语言编写的规则集合,定义“允许”或“拒绝”的条件 | 交通法规 |
| Input(输入) | 策略评估时的外部数据,如 Kubernetes 资源对象的 JSON 表示 | 当前路况与车辆信息 |
| Data(数据) | 策略依赖的静态或动态上下文数据,如白名单、配置基线 | 地图与限速标志 |
| Decision(决策) | 策略评估结果,通常为 allow 或 deny,可附带消息 |
交警的放行或处罚决定 |
关键理解: OPA 本身不存储状态,每次决策都是基于输入和数据的纯函数计算。这种设计使其天然适合在 Kubernetes 准入控制场景中做实时校验。
3.2 Rego 语言基础
Rego 是 OPA 的专用声明式查询语言,灵感来源于 Datalog。Rego 的核心是规则(Rule)和查询(Query)。
3.2.1 基本语法结构
package kubernetes.admission
# 规则:拒绝没有设置 resource limits 的 Pod
deny[msg] {
input.request.kind.kind == "Pod"
not input.request.object.spec.containers[_].resources.limits
msg := "容器必须设置 resource limits"
}
- Package:策略的命名空间,用于组织规则。
- Rule:
deny[msg]表示当条件满足时,生成一条拒绝消息。 - Iteration:
containers[_]中的下划线表示遍历所有容器。 - Negation:
not用于检查某个条件不成立。
3.2.2 常用内置函数与操作符
| 类别 | 示例 | 说明 |
|---|---|---|
| 比较 | ==, !=, <, > |
与大多数语言一致 |
| 集合 | count(array), array[_] |
获取长度、遍历元素 |
| 字符串 | startswith(s, prefix), regex.match(pattern, s) |
前缀匹配、正则匹配 |
| 对象 | object.get(obj, key, default) |
安全访问嵌套字段 |
学习建议: Rego 的调试利器是
print() 函数和 opa eval 命令行工具。在编写复杂规则时,先用 opa eval --data policy.rego --input input.json "data.kubernetes.admission" 验证规则逻辑。
3.3 Gatekeeper 架构解析
Gatekeeper 是 OPA 在 Kubernetes 上的原生集成实现,它利用 Kubernetes 的准入 Webhook 机制,在资源创建或更新时触发策略评估。
3.3.1 核心组件职责
- Gatekeeper Webhook:作为 Kubernetes 的 ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook 注册,拦截资源请求。
- OPA 引擎:嵌入在 Gatekeeper Pod 中,负责执行 Rego 策略评估。
- ConstraintTemplate:自定义资源(CRD),用于定义可复用的 Rego 策略模板。
- Constraint:ConstraintTemplate 的实例化对象,通过参数(如
allowedRegistries)定制策略行为。
3.4 安装与部署 Gatekeeper
Gatekeeper 的安装支持 Helm Chart 和 YAML 清单两种方式。以下以 Helm 3 为例进行部署。
3.4.1 前置条件
| 组件 | 版本要求 | 说明 |
|---|---|---|
| Kubernetes 集群 | >= 1.20 | 需要支持 ValidatingAdmissionWebhook |
| Helm | >= 3.0 | 推荐使用 Helm 3 进行安装管理 |
| kubectl | 与集群版本匹配 | 用于验证部署状态 |
3.4.2 使用 Helm 安装 Gatekeeper
# 添加 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.4.3 验证部署状态
# 检查 Pod 运行状态
kubectl get pods -n gatekeeper-system
# 预期输出示例:
# NAME READY STATUS RESTARTS AGE
# gatekeeper-audit-7d8f6b9c6f-abc12 1/1 Running 0 2m
# gatekeeper-controller-manager-6f9c7d8e4f-xyz34 1/1 Running 0 2m
# gatekeeper-controller-manager-6f9c7d8e4f-uvw56 1/1 Running 0 2m
# 检查 Webhook 配置是否注册成功
kubectl get validatingwebhookconfigurations
# 应看到 gatekeeper-validating-webhook-configuration
常见问题: 如果 Gatekeeper Pod 一直处于
CrashLoopBackOff 状态,请检查集群的 PodSecurityPolicy 或 ValidatingAdmissionWebhook 是否被其他组件(如 Kyverno)冲突拦截。建议先排查 Webhook 配置的 failurePolicy 是否为 Ignore。
3.5 部署后的快速验证
安装完成后,可以通过部署一个简单的 ConstraintTemplate 和 Constraint 来验证 Gatekeeper 是否正常工作。
# 1. 创建 ConstraintTemplate:禁止特权容器
cat <<EOF | kubectl apply -f -
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8spspprivilegedcontainer
spec:
crd:
spec:
names:
kind: K8sPSPPrivilegedContainer
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spspprivilegedcontainer
violation[{"msg": msg}] {
c := input.review.object.spec.containers[_]
c.securityContext.privileged == true
msg := sprintf("容器 %v 不允许使用特权模式", [c.name])
}
EOF
# 2. 创建 Constraint 实例
cat <<EOF | kubectl apply -f -
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
name: no-privileged-containers
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
EOF
# 3. 测试:尝试创建特权 Pod
kubectl run test-privileged --image=nginx --privileged
# 预期输出:Error from server (Forbidden): ... 容器 test-privileged 不允许使用特权模式
验证要点: 如果测试 Pod 被成功拒绝,说明 Gatekeeper 的准入控制链路已打通。此时可以继续编写更复杂的策略,如镜像仓库白名单、资源配额校验等。