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