使用 OPA/Gatekeeper 和 RabbitMQ 消息拓扑资源
许多组织都有关于 RabbitMQ 使用的策略,他们希望强制执行这些策略。这篇博文通过示例解释了如何将 Open Policy Agent Gatekeeper 项目 与 RabbitMQ Messaging Topology Operator 结合使用,以管理 Kubernetes 上的 RabbitMQ 资源,并通过扩展 Kubernetes API 对这些资源强制执行策略。
RabbitMQ Messaging Topology Operator
Messaging Topology Operator 允许通过使用 自定义资源定义 (CRD) 扩展 Kubernetes API,从而以声明方式管理 RabbitMQ 集群内的消息拓扑状态。这种消息拓扑状态包括虚拟主机、队列、交换机、绑定、策略、联邦、铲子、用户和权限。这些对象类型中的每一种都由 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
这个仲裁队列被命名为 my-queue
,位于虚拟主机 my-vhost
和 RabbitMQ 集群 my-rabbit-cluster
上。
如果开发人员被分配了允许他们创建 Queue 资源的 roles,那么他们可以自由创建任何具有任何配置的队列。
假设我们有一些关于队列的策略想要强制执行,例如,以下策略列表
- RabbitMQ 集群必须命名为
my-rabbit-cluster
。 - 队列必须在虚拟主机
my-vhost
上声明。
一种选择是限制开发人员的 Kubernetes roles,以防止他们创建队列,而是建立一个手动工单系统,由 Kubernetes 管理员为他们创建 Queue 对象。然而,这种策略执行方法是手动的、耗时的,并且阻止开发人员满足自己的需求。
使用 Gatekeeper 执行策略
Gatekeeper 以不同的方式扩展了 Kubernetes API,允许我们创建 webhook 以确保 Kubernetes API 对象符合通过 OPA Rego 语言定义的策略。一旦我们在 Kubernetes 集群中部署了 Gatekeeper,我们就可以执行我们选择的任何策略。特别是,我们可以创建一个约束,使我们能够执行上述策略。
部署约束包括三个组件
- Gatekeeper 配置,通知 gatekeeper 我们想要监控的资源类型。
- 一个约束模板,让 gatekeeper 知道我们想要执行的约束类型,并包含 rego 策略配置。
- 约束的特定实例。
回到我们的示例,在 RabbitMQ 队列上执行策略所需的 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 集群名称和虚拟主机配置为参数。rego 代码确保 rabbitmqClusterReference
和 vhost
与指定的允许值匹配。更一般地,rego
代码块必须包含一个 violation 函数,当发生策略违规时,该函数评估为 true,并附带一条解释策略违规的消息。
我们必须首先部署 ConstraintTemplate
并允许 Gatekeeper 为类型 QueueValidator
创建 CRD,然后我们才能部署 QueueValidator
实例。
---
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
完成所有这些配置后,如果我们尝试创建一个不符合策略的队列,它将被 webhook 拒绝并显示错误。
结论
Gatekeeper 是一个扩展 Kubernetes API 以执行策略的 operator。与 RabbitMQ Messaging Topology Operator 一起,可以声明式地管理 RabbitMQ 对象,并通过 Kubernetes API 确保合规性。我们展示了一个简单的例子,但是用于配置策略的 OPA 语言是高度可扩展的,允许 Gatekeeper 执行高级策略管理。