使用 RabbitMQ 消息拓扑 Kubernetes Operator
使用此信息了解如何部署将由消息拓扑 Operator 管理的自定义资源对象。
如何使用 RabbitMQ 消息拓扑 Operator
如果 RabbitMQ 消息拓扑 Operator 尚未安装,请参阅快速入门信息以部署它。
此信息包括以下部分
- Cluster Operator 要求
- 跨多个命名空间的作用域
- 非 Operator 管理的 RabbitMQ
- 自定义连接 URI
- 队列和策略
- 用户和用户权限
- 交换器和绑定
- 虚拟主机
- Federation
- Shovel
- 更新资源
- 删除资源
- 限制
- TLS
- 使用 HashiCorp Vault
- 配置 Operator 的日志级别
- 基于时间的协调
注意: 有关在 Openshift 上使用 Operator 的更多信息,请访问在 Openshift 上使用 RabbitMQ Kubernetes Operator。
RabbitMQ Cluster Operator 要求
- 消息拓扑 Operator 可以与使用 Kubernetes Cluster Operator 部署的 RabbitMQ 集群一起使用。 Cluster Operator 的最低版本要求为
2.0.0
。
跨多个命名空间的作用域
消息拓扑 Operator 可以在任何命名空间中协调其对象。但是,默认情况下,它会将其交互限制为与拓扑对象(例如 Queue
)相同命名空间内的 RabbitmqCluster
对象。换句话说,仅当 RabbitmqCluster
对象也位于 default
命名空间中时,消息拓扑 Operator 才会协调 default
命名空间中的 Queue
对象。
这是默认行为,可以自定义以允许来自特定命名空间列表的协调。要创建允许的命名空间列表,必须使用键 rabbitmq.com/topology-allowed-namespaces
和值(以逗号分隔的列表,不带空格)来注释 RabbitmqCluster
对象,例如 default,ns1,my-namespace
。 星号 *
值可用于允许所有命名空间。
可以使用 .spec.rabbitmqClusterReference.namespace
将任何拓扑对象声明为以不同命名空间中的 RabbitmqCluster
为目标。与 RabbitmqCluster
位于同一命名空间中的拓扑对象始终被允许。
以下 YAML 声明了一个 RabbitmqCluster
对象,该对象允许来自命名空间 my-app
的拓扑对象
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
name: example-rabbit
namespace: rabbitmq-service
annotations:
rabbitmq.com/topology-allowed-namespaces: "my-app"
spec:
replicas: 1
请注意,上面的 YAML 指定了命名空间 rabbitmq-service
。 然后,以下 YAML 将以来自命名空间 my-app
的上述 RabbitMQ 为目标。
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
name: test # name of this custom resource; does not have to the same as the actual queue name
namespace: my-app
spec:
name: test-queue # name of the queue
rabbitmqClusterReference:
name: example-rabbit
namespace: rabbitmq-service
关于禁止跨命名空间对象的重要信息
如果拓扑对象(例如 Queue
)以 RabbitmqCluster
为目标,并且此类 RabbitmqCluster
不允许来自拓扑对象命名空间的请求,则会创建一个状态条件,其中包含错误消息,并且该对象不会被协调,直到更新为止。
例如,命名空间 ns1
中的 RabbitmqCluster
允许来自 my-app
的拓扑,而命名空间 not-allowed
中的拓扑对象 Queue
以所述 RabbitmqCluster
为目标,则消息拓扑 Operator 将记录错误消息,更新 Queue
对象中的状态条件,并放弃协调 Queue
对象。 如果更新 RabbitmqCluster
对象以允许来自命名空间 not-allowed
的拓扑对象,则 必须手动更新 Queue
对象以触发协调; 例如,通过向 Queue
对象添加标签。
非 Operator 管理的 RabbitMQ
- 对于任何不是由 Cluster Operator 部署的 RabbitMQ,可以提供连接密钥以创建 RabbitMQ 拓扑对象。
- 此功能自消息拓扑 Operator
1.4.0
版本发布。
请注意,spec.rabbitmqClusterReference
是一个不可变字段。 例如,connectionSecret
名称一旦创建就无法更新
以下清单创建了一个队列,并使用 Kubernetes 密钥 my-rabbit-creds
中的凭据连接到 RabbitMQ 服务器
---
apiVersion: v1
kind: Secret
metadata:
name: my-rabbit-creds
type: Opaque
stringData:
# has to be an existing user
username: a-user
password: a-secure-password
# uri for the management api; when no scheme is provided in the uri, 'http' will be used by default
uri: https://my.rabbit:15672
---
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
name: qq-example
spec:
name: my-queue
rabbitmqClusterReference:
connectionSecret:
# has to be an existing secret in the same namespace as this Queue object
name: my-rabbit-creds
- 如果设置了
rabbitmqClusterReference.namespace
,将使用该命名空间中的密钥
---
apiVersion: v1
kind: Secret
metadata:
name: my-rabbit-creds
namespace: rabbitmq-system
annotations:
# has to be "*" or match namespace name(s) where RabbitMQ objects are deployed
rabbitmq.com/topology-allowed-namespaces: "qq-namespace"
type: Opaque
stringData:
# has to be an existing user
username: a-user
password: a-secure-password
# uri for the management api; when no scheme is provided in the uri, 'http' will be used by default
uri: https://my.rabbit:15672
---
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
name: qq-example
namespace: qq-namespace
spec:
name: my-queue
rabbitmqClusterReference:
namespace: rabbitmq-system
connectionSecret:
# has to be an existing secret in the namespace specified in rabbitmqClusterReference.namespace
name: my-rabbit-creds
请注意,spec.rabbitmqClusterReference
是一个不可变字段。 例如,connectionSecret
名称一旦创建就无法更新。
跨命名空间连接密钥
从消息拓扑 Operator 1.13
开始,可以在 connectionSecret
对象中设置 namespace
。 但是,Secret
必须使用 rabbitmq.com/topology-allowed-namespaces
进行注释,并具有允许的命名空间列表。 例如,命名空间 central-vault
中的 Secret
,使用 rabbitmq.com/topology-allowed-namespaces: rabbitmq-service
注释,可以被拓扑 Operator 用来读取 RabbitMQ 凭据,前提是拓扑对象(例如 Queue
)位于命名空间 rabbitmq-service
中。
---
apiVersion: v1
kind: Secret
metadata:
name: rabbitmq-service-credentials
namespace: central-vault
annotations:
rabbitmq.com/topology-allowed-namespaces: rabbitmq-service
type: Opaque
stringData:
username: a-user # user must already exist in RabbitMQ
password: a-secure-password
uri: https://my.rabbit:15672 # (optional) uri for the management api; when scheme is not provided in uri, operator defaults to 'http'
---
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
name: my-queue
namespace: rabbitmq-service
spec:
name: my-queue
rabbitmqClusterReference:
connectionSecret:
name: rabbitmq-service-credentials
namespace: central-vault
自定义连接 URI
- 对于无法通过其 Kubernetes 服务对象连接的 RabbitmqCluster(例如,如果 TLS 证书是为自定义域而不是 Kubernetes 服务生成的),您可以使用自定义连接 URI 注释 RabbitmqCluster。 消息拓扑 Operator 将使用提供的信息进行连接,而不是 Kubernetes dns。
- 此功能自消息拓扑 Operator
1.12.0
版本发布。
要注释 RabbitmqCluster,
kubectl annotate rmq RMQ-NAME rabbitmq.com/operator-connection-uri=https://test:1234
队列和策略
消息拓扑 Operator 可以在 RabbitMQ 集群中声明队列和策略。
以下清单将在默认 vhost 中创建一个名为“test”的队列
apiVersion: rabbitmq.com/v1beta1
kind: Queue
metadata:
name: test # name of this custom resource; does not have to the same as the actual queue name
namespace: rabbitmq-system
spec:
name: test # name of the queue
autoDelete: false
durable: true
rabbitmqClusterReference:
name: example-rabbit
以下清单将在默认虚拟主机中创建一个名为“lazy-queue”的策略
apiVersion: rabbitmq.com/v1beta1
kind: Policy
metadata:
name: policy-example # name of this custom resource
namespace: rabbitmq-system
spec:
name: lazy-queue
pattern: "^lazy-queue-" # matches any queue begins with "lazy-queue-"
applyTo: "queues"
definition:
queue-mode: lazy
rabbitmqClusterReference:
name: example-rabbit
请注意,不建议直接在队列上设置可选队列参数。 一旦设置,队列属性将无法更改。 请改用策略。
交换器和绑定
消息拓扑 Operator 可以管理交换器和绑定。 以下清单将创建一个 fanout 交换器
apiVersion: rabbitmq.com/v1beta1
kind: Exchange
metadata:
name: fanout
namespace: rabbitmq-system
spec:
name: fanout-exchange # name of the exchange
type: fanout # default to 'direct' if not provided; can be set to 'direct', 'fanout', 'headers', and 'topic'
autoDelete: false
durable: true
rabbitmqClusterReference:
name: example-rabbit
以下清单将在交换器和队列之间创建一个绑定
apiVersion: rabbitmq.com/v1beta1
kind: Binding
metadata:
name: binding
namespace: rabbitmq-system
spec:
source: test # an existing exchange
destination: test # an existing queue
destinationType: queue # can be 'queue' or 'exchange'
rabbitmqClusterReference:
name: example-rabbit
用户和用户权限
您可以使用消息拓扑 Operator 创建 RabbitMQ 用户并分配用户权限。 在访问控制指南中了解更多关于用户管理的信息。
具有自动生成的用户名和密码的用户
默认情况下,消息拓扑 Operator 创建具有生成的凭据的用户。
以下清单将创建一个具有生成的用户名和密码的用户,并且可以通过 Kubernetes 密钥对象访问生成的用户名和密码
apiVersion: rabbitmq.com/v1beta1
kind: User
metadata:
name: user-example
namespace: rabbitmq-system
spec:
tags:
- policymaker
rabbitmqClusterReference:
name: example-rabbitmq
要获取包含生成的用户名和密码的 Kubernetes 密钥对象的名称,请运行以下命令
kubectl get users.rabbitmq.com user-example -o jsonpath='{.status.credentials.name}'
请注意,Operator 不会监视生成的密钥对象,并且更新密钥对象不会更新凭据。 作为一种解决方法,请向 users.rabbitmq.com
对象添加标签或注释,以触发 Operator 进行协调。
具有提供的用户名和密码的用户
Operator 还支持创建具有提供的凭据的 RabbitMQ 用户。 当创建具有提供的用户名和密码的用户时,创建一个 Kubernetes 密钥对象,其中在其 Data 字段中包含键 username
和 password
。 Operator 不会监视提供的密钥对象,并且更新密钥对象不会更新凭据。 作为一种解决方法,请向 users.rabbitmq.com
对象添加标签或注释,以触发 Operator 进行协调。
以下清单将创建一个用户,其用户名和密码从密钥“my-rabbit-user”提供
apiVersion: rabbitmq.com/v1beta1
kind: User
metadata:
name: import-user-sample
spec:
tags:
- policymaker
- monitoring # other available tags are 'management' and 'administrator'
rabbitmqClusterReference:
name: rabbit-example
importCredentialsSecret:
name: my-rabbit-user # name of the secret
具有密码哈希和无密码用户的用户
自拓扑 Operator v1.15.0
起,可以使用 SHA-512 哈希提供用户密码。 拓扑 Operator 资源不支持其他哈希算法。 要创建具有密码哈希的用户,请在凭据 Secret
中使用字段 passwordHash
---
apiVersion: v1
kind: Secret
metadata:
name: my-user-credentials # IMPORTANT: this Secret name must match .spec.importCredentialsSecret.name field in User object
type: Opaque
stringData:
username: my-user
passwordHash: tLXSw48rCJO5gc8zu2UJRxR+RfbmNIJMWA6udRQlb6zVWwZg # SHA-512 hash of "foobarbaz"
---
apiVersion: rabbitmq.com/v1beta1
kind: User
metadata:
name: my-admin-user
spec:
tags:
- administrator
rabbitmqClusterReference:
name: test # rabbitmqCluster must exist in the same namespace as this resource
importCredentialsSecret:
name: my-user-credentials # must match the name of the Secret
如果存在 passwordHash
字段,则 password
字段将被忽略,并且生成的凭据 Secret
将仅包含哈希。 如果哈希是空字符串,则会创建一个无密码用户。 例如
---
apiVersion: v1
kind: Secret
metadata:
name: my-user-credentials
type: Opaque
stringData:
username: my-user
passwordHash: ""
重要的是要注意,passwordHash
的空字符串与根本不提供该字段不相同。 为了生成无密码用户,必须将空字符串 ""
作为 passwordHash
提供。
用户权限对象
要在现有用户上设置用户权限,请创建 permissions.rabbitmq.com
资源。 以下示例将权限分配给用户 rabbit-user-1
apiVersion: rabbitmq.com/v1beta1
kind: Permission
metadata:
name: rabbit-user-1-permission
namespace: rabbitmq-system
spec:
vhost: "/"
user: "rabbit-user-1" # name of the RabbitMQ user
permissions:
write: ".*"
configure: ".*"
read: ".*"
rabbitmqClusterReference:
name: sample
虚拟主机
消息拓扑 Operator 可以创建虚拟主机。
以下清单将在名为“example-rabbit”的 RabbitmqCluster 中创建一个名为“test”的 vhost
apiVersion: rabbitmq.com/v1beta1
kind: Vhost
metadata:
name: test-vhost # name of this custom resource
namespace: rabbitmq-system
spec:
name: test # name of the vhost
rabbitmqClusterReference:
name: example-rabbit
Federation
消息拓扑 Operator 可以定义 Federation 上游。
由于 Federation 上游 URI 包含凭据,因此通过 Kubernetes Secret 对象提供。 “uri”键对于 Secret 对象是强制性的。 它的值可以是单个 URI 或以逗号分隔的 URI 列表。
以下清单将在名为“example-rabbit”的 RabbitmqCluster 中定义一个名为“origin”的上游
apiVersion: rabbitmq.com/v1beta1
kind: Federation
metadata:
name: federation-example
namespace: rabbitmq-system
spec:
name: "origin"
uriSecret:
# secret must be created in the same namespace as this Federation object; in this case 'rabbitmq-system'
name: {secret-name}
ackMode: "on-confirm"
rabbitmqClusterReference:
name: example-rabbit
更多 federation 示例。
Shovel
消息拓扑 Operator 可以声明动态 Shovel。
Shovel 源和目标 URI 通过 Kubernetes Secret 对象提供。 Secret 对象必须包含两个键“srcUri”和“destUri”,并且每个键的值可以是单个 URI 或以逗号分隔的 URI 列表。
以下清单将在名为“example-rabbit”的 RabbitmqCluster 中创建一个名为“my-shovel”的 Shovel
apiVersion: rabbitmq.com/v1beta1
kind: Shovel
metadata:
name: shovel-example
namespace: rabbitmq-system
spec:
name: "my-shovel"
uriSecret:
# secret must be created in the same namespace as this Shovel object; in this case 'rabbitmq-system'
name: {secret-name}
srcQueue: "the-source-queue"
destQueue: "the-destination-queue"
rabbitmqClusterReference:
name: example-rabbit
更多 shovel 示例。
更新资源
某些自定义资源属性是不可变的。 消息拓扑 Operator 实现了验证 Webhook,以防止对不可变字段进行更新。 禁止的更新将被拒绝。 例如
kubectl apply -f test-queue.yaml
Error from server (Forbidden):
...
Resource: "rabbitmq.com/v1beta1, Resource=queues", GroupVersionKind: "rabbitmq.com/v1beta1, Kind=Queue"
Name: "example", Namespace: "rabbitmq-system"
for: "test-queue.yaml": admission webhook "vqueue.kb.io" denied the request: Queue.rabbitmq.com "example" is forbidden: spec.name: Forbidden: updates on name, vhost, and rabbitmqClusterReference are all forbidden
无法更新的属性在消息拓扑 Operator API 文档中进行了记录。
删除资源
删除自定义资源将删除 RabbitMQ 集群中相应的资源。 消息拓扑 Operator 在所有自定义资源上设置 Kubernetes finalizers。 如果该对象已在 RabbitMQ 集群中删除,或者 RabbitMQ 集群已被删除,则消息拓扑 Operator 将删除自定义资源,而无需尝试删除 RabbitMQ 对象。
限制
消息拓扑 Operator 不适用于使用导入定义部署的 RabbitmqCluster。 Operator 读取 RabbitmqCluster 状态 status.binding
中设置的默认用户密钥,如果 RabbitmqCluster 是使用导入的定义部署的,则定义将覆盖默认用户凭据,并可能导致消息拓扑 Operator 无法访问 RabbitmqCluster。 要解决此问题,您可以创建一个不导入定义的 RabbitmqCluster,或者您可以手动更新默认用户 Kubernetes 密钥为定义中设置的实际用户凭据。
TLS
如果消息拓扑 Operator 管理的 RabbitmqCluster 配置为通过 HTTPS 提供管理界面,则需要一些额外的步骤来配置消息拓扑 Operator。 请按照此TLS 专用指南来配置 Operator。
(可选)使用 HashiCorp Vault
如果消息拓扑 Operator 管理的 RabbitmqCluster 配置为将其默认用户凭据存储在 Vault 中,则需要一些额外的步骤来配置消息拓扑 Operator。 请按照此Vault 专用指南来配置 Operator。
配置 Operator 的日志级别
消息拓扑 Operator 记录协调结果和错误。 可以通过 kubectl -n rabbitmq-system logs -l app.kubernetes.io/name=messaging-topology-operator
检查 Operator 日志。 它使用 zap logger,可以通过在 Operator 部署清单中传递命令行标志来配置它。
例如,要将日志级别配置为“debug”
apiVersion: apps/v1
kind: Deployment
metadata:
name: messaging-topology-operator
namespace: rabbitmq-system
spec:
template:
spec:
containers:
- args:
- --zap-log-level=debug
command:
- /manager
有关 zap logger 的其他可用命令行标志,请参见 controller runtime 中的文档。
基于时间的协调
默认情况下,当特定自定义资源发生创建/更新/删除事件时,消息拓扑 Operator 会协调拓扑对象。 从版本 1.6.0
开始,您可以通过在 Operator 部署中设置环境变量来配置 Operator 以特定频率对所有拓扑对象执行协调
apiVersion: apps/v1
kind: Deployment
metadata:
[...]
name: messaging-topology-operator
namespace: rabbitmq-system
spec:
template:
spec:
containers:
- command:
- /manager
env:
- name: SYNC_PERIOD
value: 5m # needs to be in a format that's readable by golang time.ParseDuration(), e.g. “1000s”, “5.3h” or “20h35m”
...
重新创建已删除的队列将不会恢复任何消息。
请注意,此频率适用于 Operator 管理的所有拓扑对象。 根据您使用拓扑 Operator 创建了多少对象,以一定频率协调所有对象可能会对 Operator 和 RabbitMQ 服务器造成不必要的负载。 仅当您的用例需要基于时间的协调时才使用此功能。