滚动(就地)升级
滚动升级是一种流行的升级策略,其中节点逐个升级:每个节点停止、升级,然后启动。升级后的节点重新加入集群,集群暂时在混合版本模式下工作:一些节点运行旧版本,一些运行新版本。
虽然所有节点都必须在升级期间重启,但整个集群在整个过程中保持可用(当然,除非它只有一个节点)。
滚动升级不支持跳过版本,补丁版本除外(例如,你可以直接从 3.13.0 升级到 3.13.7,但你不能直接从 3.12.x 升级到 4.0)。此外,对于特定的升级,可能适用额外的约束。请参阅版本可升级性表以获取更多信息。
升级前
调查当前版本和目标版本是否具有滚动升级路径
请参阅版本可升级性表,了解有关支持的升级路径的信息。
检查 Erlang 版本要求
请参阅Erlang 版本要求。
如果当前和目标 RabbitMQ 版本都支持相同的 Erlang 版本,你可以保持 Erlang 不变。但是,你可以考虑同时将 Erlang 升级到最新的支持版本。Erlang 和 RabbitMQ 升级都需要重启,因此同时进行可能更方便。
如果目标 RabbitMQ 版本需要更新的 Erlang 版本,你需要准备好将 Erlang 与 RabbitMQ 一起升级。
仔细阅读所选 RabbitMQ 版本之前的发行说明
发行说明可能会指出特定的额外升级步骤。始终查阅当前部署版本和目标版本之间的所有版本的发行说明。
验证所有稳定的特性标志是否已启用
每次升级后,应启用所有稳定的特性标志。否则,升级过程并没有真正完成,因为某些更改没有生效。如果你遵循此建议,则在升级之前应该无需对特性标志执行任何操作,因为它们在上一次升级后已全部启用。
但是,由于尝试在禁用特性标志的情况下进行升级可能会导致严重问题,因此最好在开始升级之前检查是否已启用所有稳定的特性标志。你可以安全地运行 rabbitmqctl enable_feature_flag all
- 如果所有标志都已启用,它将不会执行任何操作。
确保所有软件包依赖项(包括 Erlang)都可用
如果你使用的是 Debian 或 RPM 软件包,则必须确保所有依赖项都可用。特别是,正确版本的 Erlang。你可能必须设置额外的第三方软件包存储库才能实现这一点。
请阅读基于 Debian 的和基于 RPM 的发行版的建议,以找到 Erlang 的适当存储库。
评估集群健康状况
确保节点运行状况良好,并且没有网络分区或磁盘或内存警报生效。
RabbitMQ 管理 UI、CLI 工具或 HTTP API 可用于评估系统健康状况。
管理 UI 中的概览页面显示有效的 RabbitMQ 和 Erlang 版本、多个集群范围的指标和速率。从此页面确保所有节点都在运行,并且它们都是“绿色”(关于文件描述符、内存、磁盘空间等)。
我们建议记录持久队列的数量、它们持有的消息数量以及与拓扑结构相关的其他信息。这些数据将有助于验证系统在升级后是否在合理的参数范围内运行。
使用节点健康检查来审查各个节点。
处于流状态的队列或阻塞/阻止连接可能不是问题,具体取决于你的工作负载。由你来确定这是否是正常情况,或者集群是否处于意外负载下,从而决定是否可以安全地继续升级。
但是,如果队列处于未定义状态(也称为 NaN
或“幽灵”队列),你应首先了解问题所在,然后再开始升级。
确保集群具有升级容量
请参阅系统资源使用情况的变化,了解有关升级过程如何影响资源使用情况的信息。
执行升级
升级过程的主要部分是通过逐个停止、升级和启动每个节点来执行的。应为所有节点执行以下步骤。
停止节点
停止节点的具体方法取决于节点的启动方式。
创建备份
可选地,当节点停止时,你可以备份其数据文件夹。
升级节点
安装新版本的 RabbitMQ 和其他必要的软件包。
确保你拥有与新 RabbitMQ 版本兼容的 Erlang 版本。
启动节点
启动节点并验证它是否加入集群。
你可以执行以下检查以确保节点已启动并成功重新加入集群
- 运行
rabbitmqctl cluster_status
并验证输出- 升级后的节点应列为正在运行
- 不应存在网络分区或活动警报
- 检查管理 UI
- 所有节点都应在主页上列出
- 资源使用情况应在可接受的限制范围内
- 检查日志
- 不应存在错误
升级后
验证升级是否成功
就像你在升级前所做的那样,验证健康状况和监控数据,以确保所有集群节点都处于良好状态,并且服务再次运行。
启用新的特性标志
一旦所有节点都升级并且集群健康,启用所有稳定的特性标志。如果新版本未提供任何新的特性标志,你仍然可以运行 rabbitmqctl enable_feature_flag all
- 它只会不做任何事情。
真实世界示例
滚动升级策略不特定于任何特定的部署工具或基础设施。许多编排工具都具有内置的滚动升级概念,并带有允许在每个节点升级之前和之后执行自定义操作的钩子。
Kubernetes 就是这样一种编排工具。它可以执行 StatefulSet
的滚动更新。让我们逐步了解当你想要使用集群 Operator升级部署到 Kubernetes 的 RabbitMQ 时会发生什么。假设集群有三个节点,这意味着节点名为 server-0
、server-1
和 server-2
(会有集群名称的前缀,但这与此示例无关)。
- 确保现有集群正在运行 RabbitMQ 3.13 并且已启用所有稳定的特性标志
- 使用新镜像更新
RabbitmqCluster
对象(例如,从rabbitmq:3.13.7-management
更改为rabbitmq:4.0.5-management
) - 集群 Operator 将使用新镜像更新
StatefulSet
对象,从而触发 Kubernetes 内置的滚动升级机制 - Kubernetes 将停止
server-2
(它始终从最高索引到最低索引)- Pod 将通过调用
rabbitmq-upgrade await_online_quorum_plus_one
来检查它是否可以安全停止 - 当该命令以零状态退出时,Pod 将停止
- Pod 将通过调用
- Kubernetes 将下载并启动新的 OCI 镜像。实际上,它升级了 RabbitMQ、Erlang 和其他系统依赖项的软件包
server-2
启动并尝试重新加入集群- 它启用了与停止之前相同的特性标志(特性标志的状态存储在一个文件中)
- RabbitMQ 4.0 中引入的或未启用的特性标志此时
- 因此,升级后的节点可以加入集群
- 节点启动后,它会同步其元数据(例如,了解在其关闭时声明的队列),并启动仲裁队列和流成员,它们应迅速赶上集群的其余部分(在节点关闭时发布的任何消息都会复制到它,等等)
- 一旦
server-2
正在运行,Kubernetes 将停止server-1
,并且该过程重复 - 一旦
server-0
升级并运行,所有节点都将在新版本上运行 - 你现在可以启用新的特性标志并重新平衡集群
虽然该过程有很多步骤(并且我们跳过了一些细节),但你只需更改 image
值,等待几分钟,然后运行两个命令来启用新的特性标志并重新平衡集群。
当在没有 Kubernetes 的情况下执行滚动升级时,你需要完成相同的步骤 - 你只需手动或使用其他自动化方式来完成它们。使用 OCI 镜像进一步简化了该过程,因为该镜像已包含新的 RabbitMQ 版本以及兼容的 Erlang 版本和其他依赖项。