故障隔离设计基于policy as code的升级窗口控制 - 第4节
4.1 OPA 架构:策略决策与执行分离
Open Policy Agent (OPA) 是一个开源的、通用策略引擎,它将策略决策从软件的业务逻辑中解耦出来。OPA 的核心思想是“策略即代码”(Policy as Code),通过统一的声明式语言 Rego 来描述策略,并通过 REST API 对外提供策略查询服务。
核心架构原则: OPA 不负责执行策略(如阻断请求、修改资源),只负责做出策略决策(允许/拒绝/评分)。执行动作由调用方(如 Kubernetes API Server、API 网关)根据 OPA 的决策结果自行完成。
4.1.1 OPA 组件与数据流
OPA 的架构由以下几个核心组件构成:
- OPA Agent (opa 进程): 核心引擎,加载策略(Rego 文件)和数据(JSON 文档),对外提供 HTTP/gRPC 查询接口。
- Rego 策略: 使用 Rego 语言编写的规则文件,定义决策逻辑。
- 数据文档 (Data Documents): 结构化数据(JSON),作为策略决策的输入上下文,例如集群状态、用户信息、资源元数据。
- 输入文档 (Input Documents): 每次查询时由调用方传入的临时数据,例如准入请求的 AdmissionReview 对象。
- 查询接口 (Query API): 调用方通过
POST /v1/data/{path}发送查询请求,OPA 返回决策结果。
4.2 Rego 语言基础:声明式策略编写
Rego 是 OPA 的专用策略语言,受 Datalog 启发,采用声明式范式。编写 Rego 策略的核心是定义“规则”(Rules),规则的结果可以是布尔值(true/false)、对象或数组。
4.2.1 基本语法与规则
| 概念 | 语法示例 | 说明 |
|---|---|---|
| 包声明 | package kubernetes.admission |
定义策略所属的包路径,对应查询 API 的 URL 路径。 |
| 完整规则 | allow { ... } |
当大括号内所有条件为真时,规则结果为 true。 |
| 部分规则 | violations[msg] { ... } |
生成一个集合,每满足一次条件就向集合中添加一个元素。 |
| 默认值 | default allow = false |
为规则设置默认值,避免未定义导致的意外行为。 |
| 迭代 | input.request.object.spec.containers[_] |
使用下划线 _ 遍历数组或集合中的每个元素。 |
4.2.2 完整策略示例:禁止特权容器
以下是一个典型的 Kubernetes 准入控制策略,用于禁止创建特权容器:
package kubernetes.admission
import future.keywords.if
import future.keywords.in
# 默认拒绝
default deny := false
# 当容器设置了 securityContext.privileged = true 时,生成拒绝消息
deny if {
container := input.request.object.spec.containers[_]
container.securityContext.privileged == true
reason := sprintf("容器 '%s' 设置了 privileged=true,违反安全策略", [container.name])
}
# 也可以使用部分规则收集所有违规消息
violations[msg] {
container := input.request.object.spec.containers[_]
container.securityContext.privileged == true
msg := sprintf("容器 '%s' 不允许使用特权模式", [container.name])
}
编写建议: 始终为布尔规则(如
allow、deny)设置 default 值。在复杂策略中,优先使用部分规则(如 violations)收集多条违规信息,便于调用方一次性获取所有问题。
4.3 OPA 与 Kubernetes 集成:准入控制
OPA 与 Kubernetes 最主流的集成方式是通过 OPA Gatekeeper(基于 OPA 的 Kubernetes 专用策略控制器)。Gatekeeper 以 Admission Webhook 的形式运行,拦截资源创建/更新请求,交由 OPA 策略引擎决策。
4.3.1 集成架构
Gatekeeper 在 Kubernetes 集群中部署为三个核心组件:
- Gatekeeper Controller: 管理
ConstraintTemplate和Constraint自定义资源,将策略模板实例化。 - OPA Agent (sidecar): 内嵌在 Gatekeeper 的 Webhook Pod 中,加载策略并处理准入请求。
- Admission Webhook: 注册到 Kubernetes API Server,拦截
CREATE和UPDATE操作。
4.3.2 ConstraintTemplate 与 Constraint
Gatekeeper 通过两个 CRD 实现策略的模板化和参数化:
| CRD | 作用 | 示例 |
|---|---|---|
| ConstraintTemplate | 定义 Rego 策略模板,声明参数 schema 和 Rego 代码。 | k8srequiredlabels 模板要求资源必须包含指定标签。 |
| Constraint | 实例化模板,传入具体参数(如标签键值对)。 | require-team-label 实例要求所有 Namespace 必须有 team 标签。 |
4.3.3 集成最佳实践
生产注意事项: Gatekeeper 的 Webhook 超时时间默认为 3 秒,复杂策略应优化 Rego 查询性能,避免超时导致资源创建失败。建议在策略中使用
index 和 comprehension 优化,并开启 OPA 的 --cache 选项。
- 策略分层: 将通用策略(如标签校验)与业务策略(如升级窗口控制)分离,分别部署为不同的 ConstraintTemplate。
- 审计模式: 新策略上线前先使用
enforcementAction: dryrun运行一段时间,观察违规记录再切换为deny。 - 数据同步: 利用 Gatekeeper 的
data.inventory功能同步集群资源状态,实现跨资源策略(如检查 Service 对应的 Deployment 是否存在)。 - 监控告警: 暴露 OPA 的决策指标(
opa_decision_duration_seconds、opa_http_request_duration_seconds)到 Prometheus,设置策略拒绝率告警。