将 OPA/Gatekeeper 与 RabbitMQ Messaging Topology Operator 结合使用
许多组织都有关于 RabbitMQ 使用的策略,并希望强制执行这些策略。这篇博文通过示例解释了如何将 Open Policy Agent Gatekeeper 项目 与 RabbitMQ Messaging Topology Operator 结合使用,以在 Kubernetes 上管理 RabbitMQ 资源,并通过扩展 Kubernetes API 来强制执行对这些资源的策略。
RabbitMQ 消息拓扑运算符
消息拓扑运算符通过使用自定义资源定义 (CRD) 扩展 Kubernetes API,可以声明式地管理 RabbitMQ 集群内的消息拓扑状态。这种消息拓扑状态包括 vhosts、队列、交换器、绑定、策略、联邦、Shovel、用户和权限。这些对象类型中的每一种都由一个 Kubernetes CRD 表示,并且可以在文档中找到这些自定义资源 (CR) 的示例。
为了具体说明,我们考虑一个队列
---
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
name: my-queue
spec:
name: my-queue
vhost: my-vhost
type: quorum
rabbitmqClusterReference:
name: my-rabbit-cluster
这个仲裁队列(quorum queue)名为 my-queue,位于 my-vhost vhost 上,属于 RabbitMQ 集群 my-rabbit-cluster。
如果开发人员被授予创建 Queue 资源的权限,那么他们可以自由地创建任何他们想要的、具有任何配置的队列。
假设我们有一些关于队列的策略需要强制执行,例如,以下策略列表
- RabbitMQ 集群的名称必须是
my-rabbit-cluster。 - 队列必须在
my-vhostvhost 上声明。
一种选择是限制开发人员的 Kubernetes 角色,以阻止他们创建队列,而是建立一个手动票务系统,由 Kubernetes 管理员为他们创建 Queue 对象。然而,这种策略强制执行方法是手动的、耗时的,并且阻碍了开发人员满足自身需求。
使用 Gatekeeper 强制执行策略
Gatekeeper 以不同的方式扩展 Kubernetes API,允许我们创建 Webhook 以确保 Kubernetes API 对象符合通过OPA Rego 语言定义的策略。一旦我们在 Kubernetes 集群中部署了 Gatekeeper,我们就可以强制执行我们选择的任何策略。特别是,我们可以创建一个约束来强制执行上述策略。
部署约束包括三个组件
- Gatekeeper 配置,告知 Gatekeeper 我们希望监视哪些类型的资源。
- 约束模板,让 Gatekeeper 知道我们希望强制执行哪种类型的约束,并包含 Rego 策略配置。
- 约束的具体实例。
以我们的示例为例,强制执行 RabbitMQ Queue 策略所需的 Gatekeeper 配置是
---
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
name: config
namespace: gatekeeper-system
spec:
sync:
syncOnly:
- group: rabbitmq.com
version: v1beta1
kind: Queue
为了强制执行上述策略,我们创建了以下 ConstraintTemplate
---
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: queuevalidator
spec:
crd:
spec:
names:
kind: QueueValidator
validation:
openAPIV3Schema:
properties:
rabbit:
type: string
vhost:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package queuevalidator
violation[{"msg":msg}] {
allowedRabbit := input.parameters.rabbit
givenRabbit := input.review.object.spec.rabbitmqClusterReference.name
givenRabbit != allowedRabbit
allowedVhost := input.parameters.vhost
givenVhost := input.review.object.spec.vhost
givenVhost != allowedVhost
msg := sprintf("Rabbit Cluster must be %v, queues must be declared on vhost %v", [allowedRabbit, allowedVhost])
}
从这个 ConstraintTemplate 开始,Gatekeeper 将创建一个名为 QueueValidator 的自定义资源种类,它接受两个属性:rabbit 和 vhost,均为字符串。这允许我们在部署约束实例时,将允许的 RabbitMQ 集群名称和 vhost 作为参数进行配置。Rego 代码确保 rabbitmqClusterReference 和 vhost 与指定的允许值匹配。更一般地说,rego 块必须包含一个违规函数,当发生策略违规时该函数评估为 true,并附带一条解释策略违规的消息。
在部署 QueueValidator 实例之前,我们必须先部署 ConstraintTemplate 并允许 Gatekeeper 创建 QueueValidator 种类的 CRD。
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: QueueValidator
metadata:
name: queue-validator
spec:
match:
kinds:
- apiGroups: ["rabbitmq.com"]
kinds: ["Queue"]
parameters:
- rabbit: my-rabbit-cluster
- vhost: my-vhost
在所有这些配置到位后,如果我们尝试创建一个不符合策略的 Queue,它将被 webhook 拒绝并报错。
结论
Gatekeeper 是一个扩展 Kubernetes API 以强制执行策略的运算符。与 RabbitMQ Messaging Topology Operator 结合使用,可以声明式地管理 RabbitMQ 对象并通过 Kubernetes API 确保合规性。我们已经展示了一个简单的例子,但是用于配置策略的 OPA 语言是高度可扩展的,允许 Gatekeeper 执行高级策略管理。
