3. OPA 策略引擎入门:OPA 是什么、Rego 语言简介、OPA 部署模式
3.1 OPA 是什么
Open Policy Agent (OPA) 是一个开源的、通用策略引擎,它将策略决策与业务逻辑的执行分离。OPA 提供了一种统一的、声明式的语言(Rego)来描述策略,并通过 REST API 或 gRPC 接口对外提供策略查询服务。在云原生生态中,OPA 常被用于实现微服务、Kubernetes、服务网格等场景下的细粒度访问控制、合规检查和数据过滤。
3.2 OPA 架构与决策流程
OPA 的决策流程遵循“输入-策略-输出”的模型。外部系统(如 Envoy、Kubernete API Server)将请求上下文(Input)发送给 OPA,OPA 根据加载的 Rego 策略和全局数据(Data)进行评估,最终返回决策结果(Decision)。
3.3 Rego 语言简介
Rego 是 OPA 的原生策略语言,受 Datalog 启发,专为在复杂嵌套文档(如 JSON、YAML)上定义策略而设计。Rego 的核心是规则(Rules)和查询(Queries)。策略编写者通过定义规则来描述允许或禁止的条件。
3.3.1 Rego 基础语法
- 包(Package): 用于组织策略,类似命名空间。
- 规则(Rule): 形如
allow { condition },当条件为真时,规则为真。 - 默认值(Default): 使用
default allow = false设置规则的默认拒绝行为。 - 迭代(Iteration): 使用
some关键字遍历集合。 - 内置函数(Built-in Functions): 如
http.send、regex.match、time.now_ns等。
3.3.2 Rego 策略示例
以下示例展示了一个简单的 Rego 策略,用于控制服务网格中服务 A 对服务 B 的访问:
package service_mesh.authz
import future.keywords.if
import future.keywords.in
# 默认拒绝所有请求
default allow := false
# 允许规则:如果请求来自 service-a,目标为 service-b,且 HTTP 方法为 GET
allow if {
input.source_service == "service-a"
input.destination_service == "service-b"
input.http_method == "GET"
}
# 允许规则:如果请求携带有效的 JWT ,且 中的角色为 "admin"
allow if {
input.jwt.role == "admin"
}
3.4 OPA 部署模式
OPA 可以以多种模式集成到服务网格或 Kubernetes 环境中。选择合适的部署模式取决于性能、延迟、管理复杂度和安全隔离需求。下表对比了三种主流部署模式:
| 部署模式 | 架构描述 | 延迟 | 管理复杂度 | 适用场景 |
|---|---|---|---|---|
| Sidecar | OPA 作为独立容器与业务容器同 Pod 运行 | 极低(本地 IPC) | 中等(需管理 Sidecar 注入) | 对延迟敏感、需要隔离策略执行的场景 |
| Daemon | OPA 作为 DaemonSet 在每个节点上运行 | 低(节点内通信) | 低(集中管理,节点级共享) | 节点级策略执行,如节点安全审计 |
| 外部服务 | OPA 作为独立服务集群部署,通过网络调用 | 中等(网络开销) | 高(需考虑高可用、负载均衡) | 策略逻辑复杂、需要全局数据聚合的场景 |
3.4.1 Sidecar 模式
在服务网格中,Sidecar 模式是最常见的 OPA 部署方式。每个微服务 Pod 内除了业务容器和 Envoy 代理外,还会运行一个 OPA 容器。Envoy 通过 ext_authz 过滤器将请求上下文发送给本地的 OPA 实例进行决策。这种模式延迟最低,且策略执行失败不会影响其他 Pod。
3.4.2 Daemon 模式
Daemon 模式将 OPA 部署为 Kubernetes DaemonSet,每个节点上运行一个 OPA 实例。节点上的所有 Pod 可以共享该 OPA 实例进行策略查询。这种模式减少了 Pod 内的资源开销,但引入了节点级别的单点故障风险。
3.4.3 外部服务模式
外部服务模式将 OPA 部署为一个独立的、可水平扩展的服务。所有 Envoy 代理或应用通过 DNS 或 Service Mesh 的流量规则将策略查询请求发送到 OPA 集群。这种模式便于统一管理和更新策略,但会增加网络延迟,且需要额外的负载均衡和故障转移机制。