零停机时间升级
通过零停机时间升级,可以在不下线的情况下升级正在运行的极狐GitLab 环境。本指南将带您完成执行此类升级的核心流程。
从高层次来看,这一过程是通过按一定顺序依次升级极狐GitLab 节点来完成的,利用负载均衡、HA 系统和优雅重载的组合来最大限度地减少中断。
本指南仅涉及适用的核心极狐GitLab 组件。对于第三方服务的升级或管理,如 AWS RDS,请参考相应的文档。
在您开始之前
实现升级过程中的_真正_零停机对于任何分布式应用程序来说都是非常困难的。本指南中详细描述的过程已经在我们的 HA 参考架构中进行了测试,结果是几乎没有可观察到的停机时间,但请注意,具体结果可能因系统组成的不同而有所差异。
为了增强信心,一些客户通过进一步的技术取得了成功,例如通过使用特定的负载均衡器或基础设施功能手动排空节点。这些技术在很大程度上依赖于底层基础设施的能力,因此未在本指南中介绍。有关任何其他信息,请联系您的极狐GitLab 代表或支持团队。
要求和注意事项
零停机时间升级过程有以下要求:
- 零停机时间升级仅支持使用 Linux 软件包构建并配置了负载均衡和 HA 机制的多节点极狐GitLab 环境:
- 为 Rails 节点配置的外部负载均衡器,启用了针对 Readiness (
/-/readiness
) 端点的健康检查。 - 为任何 PgBouncer 和 Praefect 组件配置的内部负载均衡器,启用了 TCP 健康检查。
- 为 Consul、Postgres 和 Redis 组件配置的 HA 机制(如果存在)。
- 任何未以 HA 方式部署的组件将需要单独升级并可能会有停机时间。
- 为 Rails 节点配置的外部负载均衡器,启用了针对 Readiness (
-
一次只能升级一个小版本。所以从
16.1
升级到16.2
,而不是16.3
。如果跳过版本,数据库修改可能会按错误的顺序运行,并使数据库架构处于损坏状态。 - 您必须使用部署后迁移。
- 极狐GitLab Charts 不支持零停机时间升级。这也意味着这种类型的升级不适用于云原生混合环境。
除了上述内容,请注意以下注意事项:
- 大多数情况下,如果补丁版本不是最新的,您可以安全地从补丁版本升级到下一个小版本。例如,从
16.3.2
升级到16.4.1
应该是安全的,即使16.3.3
已经发布。您应该验证与您的升级路径相关的特定版本升级说明,并注意任何必要的升级停顿: - 某些版本可能包括后台迁移。这些迁移由 Sidekiq 在后台执行,通常用于迁移数据。后台迁移仅在每月发布的版本中添加。
- 某些主要或次要版本可能需要完成一组后台迁移。虽然这不需要停机(如果满足上述条件),但在每次主要或次要版本升级之间,您必须等待后台迁移完成。
- 完成这些迁移所需的时间可以通过增加可以在
background_migration
队列中处理作业的 Sidekiq 工作人员的数量来减少。要查看此队列的大小,在升级之前检查后台迁移。
- PostgreSQL 主要版本升级是一个单独的过程,并不包括在零停机时间升级中(较小的升级包括在内)。
- 对于您已使用极狐GitLab Linux 软件包部署的任何极狐GitLab 组件,支持零停机时间升级。如果您通过支持的第三方服务(如 AWS RDS 中的 PostgreSQL 或 GCP Memorystore 中的 Redis)部署了选定的组件,则这些服务的升级将需要根据其标准流程单独执行。
- 一般来说,您的数据量越大,升级完成所需的时间就越多。在测试中,任何小于 10 GB 的数据库通常不应超过一个小时,但具体情况可能会有所不同。
升级顺序
我们建议采用“从后到前”的方法来安排零停机时间升级组件的顺序。通常,这意味着首先是有状态的后端,然后是它们的依赖项,最后是前端。虽然部署的顺序可以更改,但最好将运行极狐GitLab 应用程序代码的组件(Rails、Sidekiq)一起部署。如果可能,单独升级支持基础设施(PostgreSQL、PgBouncer、Consul、Gitaly、Praefect、Redis),因为这些组件不依赖于版本更新中的更改。因此,我们通常建议以下顺序:
- Consul
- PostgreSQL
- PgBouncer
- Redis
- Gitaly
- Praefect
- Rails
- Sidekiq
多节点 / HA 部署
在本节中,我们将通过按照升级顺序依次升级每个节点,并让负载均衡器 / HA 机制相应地处理每个节点的停机,来逐步完成多节点极狐GitLab 环境的升级过程。
为了本指南的目的,我们将升级一个使用 Linux 软件包构建的200 RPS 或 10,000 用户参考架构。
Consul、PostgreSQL、PgBouncer 和 Redis
Consul、PostgreSQL、PgBouncer和 Redis 组件都遵循相同的基础流程以实现无停机时间的升级。
在每个组件的节点上按顺序运行以下步骤以执行升级:
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
-
重新配置并重新启动以获取最新代码:
sudo gitlab-ctl reconfigure sudo gitlab-ctl restart
Gitaly
Gitaly 在升级时遵循相同的核心流程,但有一个关键区别,即 Gitaly 进程本身不会重启,因为它有一个内置的进程,可以在最早的机会优雅地重新加载。请注意,任何其他组件仍然需要重启。
此过程适用于 Gitaly 分片和集群设置。在每个 Gitaly 节点上按顺序运行以下步骤以执行升级:
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
- 升级极狐GitLab 软件包。
-
运行
reconfigure
命令以获取最新代码并指示 Gitaly 在下次机会时优雅地重新加载:sudo gitlab-ctl reconfigure
-
最后,虽然 Gitaly 会优雅地重新加载,但任何其他已部署的组件仍然需要重启:
# 获取除 Gitaly 外其他已部署组件的列表 sudo gitlab-ctl status # 重启除 Gitaly 外的每个组件。示例给出了 Consul、Node Exporter 和 Logrotate sudo gitlab-ctl restart consul node-exporter logrotate
Praefect
对于 Gitaly 集群设置,您必须通过使用优雅的重新加载来部署和升级 Praefect。
不过,对于 Praefect,还需要进行其数据库迁移以升级其数据。迁移只需要在一个 Praefect 节点上运行,以避免冲突。最好选择一个节点作为部署节点进行配置以运行迁移,而其他节点则不运行。我们将在下文中将其称为 Praefect 部署节点:
-
在 Praefect 部署节点上:
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
-
确保在
/etc/gitlab/gitlab.rb
中设置了praefect['auto_migrate'] = true
以便运行数据库迁移。 -
运行
reconfigure
命令以获取最新代码,应用 Praefect 数据库迁移并优雅地重启:sudo gitlab-ctl reconfigure
-
-
在所有 剩余的 Praefect 节点上:
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
-
确保在
/etc/gitlab/gitlab.rb
中设置了praefect['auto_migrate'] = false
以防止reconfigure
自动运行数据库迁移。 -
运行
reconfigure
命令以获取最新代码并优雅地重启:sudo gitlab-ctl reconfigure
-
-
最后,虽然 Praefect 会优雅地重新加载,但任何其他已部署的组件仍然需要重启。在所有 Praefect 节点上:
# 获取除 Praefect 外其他已部署组件的列表 sudo gitlab-ctl status # 重启除 Praefect 外的每个组件。示例给出了 Consul、Node Exporter 和 Logrotate sudo gitlab-ctl restart consul node-exporter logrotate
Rails
作为 Web 服务器的 Rails 主要由 Puma、Workhorse和 NGINX 组成。
每个组件在执行实时升级时具有不同的行为。虽然 Puma 可以进行优雅的重新加载,但 Workhorse 不能。最佳方法是通过其他方式优雅地排空节点,例如使用负载均衡器。您也可以通过在节点上使用 NGINX 的优雅关闭功能来实现。本节解释了 NGINX 方法。
此外,Rails 是执行主要数据库迁移的地方。与 Praefect 类似,最佳方法是使用部署节点。如果当前使用 PgBouncer,还需要绕过它,因为 Rails 在尝试运行迁移时使用建议锁,以防止在同一数据库上运行并发迁移。这些锁不会在事务之间共享,导致 ActiveRecord::ConcurrentMigrationError
和使用事务池模式在 PgBouncer 中运行数据库迁移时的其他问题。
-
在 Rails 部署节点上:
-
优雅地排空节点流量。您可以通过多种方式实现,但一种方法是通过发送
QUIT
信号来使用 NGINX 然后停止服务。您可以使用以下 shell 脚本来实现:# 向 NGINX 主进程发送 QUIT 信号以排空并退出 NGINX_PID=$(cat /var/opt/gitlab/nginx/nginx.pid) kill -QUIT $NGINX_PID # 等待排空完成 while kill -0 $NGINX_PID 2>/dev/null; do sleep 1; done # 停止 NGINX 服务以防止自动重启 gitlab-ctl stop nginx
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
- 在
/etc/gitlab/gitlab.rb
配置文件中设置gitlab_rails['auto_migrate'] = true
来配置常规迁移。- 如果部署节点当前通过 PgBouncer 连接到数据库,则在运行迁移之前,您必须绕过它并直接连接到数据库主节点。
- 要查找数据库主节点,您可以在任何数据库节点上运行以下命令 -
sudo gitlab-ctl patroni members
。
-
运行常规迁移并获取最新代码:
sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-ctl reconfigure
- 现在保持此节点不变,因为稍后您将返回运行部署后迁移。
-
-
在每个其他 Rails 节点上按顺序执行:
-
优雅地排空节点流量。您可以通过多种方式实现,但一种方法是通过发送
QUIT
信号来使用 NGINX 然后停止服务。您可以使用以下 shell 脚本来实现:# 向 NGINX 主进程发送 QUIT 信号以排空并退出 NGINX_PID=$(cat /var/opt/gitlab/nginx/nginx.pid) kill -QUIT $NGINX_PID # 等待排空完成 while kill -0 $NGINX_PID 2>/dev/null; do sleep 1; done # 停止 NGINX 服务以防止自动重启 gitlab-ctl stop nginx
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
-
确保在
/etc/gitlab/gitlab.rb
中设置gitlab_rails['auto_migrate'] = false
以防止reconfigure
自动运行数据库迁移。 -
运行
reconfigure
命令以获取最新代码并重启:sudo gitlab-ctl reconfigure sudo gitlab-ctl restart
-
-
在 Rails 部署节点上运行部署后迁移:
- 确保部署节点仍直接指向数据库主节点。如果节点当前通过 PgBouncer 连接到数据库,则在运行迁移之前,您必须绕过它并直接连接到数据库主节点。
- 要查找数据库主节点,您可以在任何数据库节点上运行以下命令 -
sudo gitlab-ctl patroni members
。
- 要查找数据库主节点,您可以在任何数据库节点上运行以下命令 -
-
运行部署后迁移:
sudo gitlab-rake db:migrate
- 通过在
/etc/gitlab/gitlab.rb
配置文件中设置gitlab_rails['auto_migrate'] = false
,将配置恢复正常。- 如果正在使用 PgBouncer,请确保数据库配置再次指向它
-
再次运行 reconfigure 以重新应用正常配置并重启:
sudo gitlab-ctl reconfigure sudo gitlab-ctl restart
- 确保部署节点仍直接指向数据库主节点。如果节点当前通过 PgBouncer 连接到数据库,则在运行迁移之前,您必须绕过它并直接连接到数据库主节点。
Sidekiq
Sidekiq 遵循与其他组件相同的基础流程,以实现无停机时间的升级。
在每个组件节点上按顺序运行以下步骤以执行升级:
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
-
运行
reconfigure
命令以获取最新代码并重启:sudo gitlab-ctl reconfigure sudo gitlab-ctl restart
使用 Geo 进行多节点高可用部署
本节描述了升级实时极狐GitLab 环境与 Geo 部署所需的步骤。
总体而言,该方法与常规流程基本相同,但每个辅助站点需要执行一些额外的步骤。所需的顺序是首先升级主站点,然后是辅助站点。在所有辅助站点更新后,您还必须在主站点上运行任何部署后迁移。
主站点
主站点的升级过程与常规流程相同,唯一的例外是在所有辅助站点更新之前不要运行部署后迁移。
按照描述的主站点步骤进行操作,但在 Rails 节点步骤的运行部署后迁移处停止。
辅助站点
任何辅助站点的升级过程遵循与常规流程相同的步骤,除了 Rails 节点,还需要进行一些额外的步骤,如下所述。
要升级站点,请按照常规流程步骤进行操作,直到 Rails 节点,然后按照以下步骤进行操作:
Rails
-
在 Rails 部署节点上:
-
优雅地排空节点流量。您可以通过多种方式实现,但一种方法是通过发送
QUIT
信号来使用 NGINX 然后停止服务。您可以使用以下 shell 脚本来实现:# 向 NGINX 主进程发送 QUIT 信号以排空并退出 NGINX_PID=$(cat /var/opt/gitlab/nginx/nginx.pid) kill -QUIT $NGINX_PID # 等待排空完成 while kill -0 $NGINX_PID 2>/dev/null; do sleep 1; done # 停止 NGINX 服务以防止自动重启 gitlab-ctl stop nginx
-
停止 Geo Log Cursor 进程以确保其切换到另一个节点:
gitlab-ctl stop geo-logcursor
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
-
如果主站点的 Rails 节点和辅助站点的 Rails 节点不同,请将
/etc/gitlab/gitlab-secrets.json
文件从主站点的 Rails 节点复制到辅助站点的 Rails 节点。文件在站点的所有节点上必须相同。 -
确保没有迁移被配置为自动运行,通过在
/etc/gitlab/gitlab.rb
配置文件中设置gitlab_rails['auto_migrate'] = false
和geo_secondary['auto_migrate'] = false
。 -
运行
reconfigure
命令以获取最新代码并重启:sudo gitlab-ctl reconfigure sudo gitlab-ctl restart
-
运行常规 Geo 跟踪迁移并获取最新代码:
sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-rake db:migrate:geo
-
-
在每个其他 Rails 节点上按顺序执行:
-
优雅地排空节点流量。您可以通过多种方式实现,但一种方法是通过发送
QUIT
信号来使用 NGINX 然后停止服务。您可以使用以下 shell 脚本来实现:# 向 NGINX 主进程发送 QUIT 信号以排空并退出 NGINX_PID=$(cat /var/opt/gitlab/nginx/nginx.pid) kill -QUIT $NGINX_PID # 等待排空完成 while kill -0 $NGINX_PID 2>/dev/null; do sleep 1; done # 停止 NGINX 服务以防止自动重启 gitlab-ctl stop nginx
-
停止 Geo Log Cursor 进程以确保其切换到另一个节点:
gitlab-ctl stop geo-logcursor
-
在
/etc/gitlab/skip-auto-reconfigure
处创建一个空文件。这可以防止升级时运行gitlab-ctl reconfigure
,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:sudo touch /etc/gitlab/skip-auto-reconfigure
-
确保没有迁移被配置为自动运行,通过在
/etc/gitlab/gitlab.rb
配置文件中设置gitlab_rails['auto_migrate'] = false
和geo_secondary['auto_migrate'] = false
。 -
运行
reconfigure
命令以获取最新代码并重启:sudo gitlab-ctl reconfigure sudo gitlab-ctl restart
-
Sidekiq
按照主要流程,现在剩下的就是升级 Sidekiq 了。
按主节中描述的方式升级 Sidekiq。
部署后迁移
最后,回到主站点并通过运行部署后迁移来完成升级:
-
在主站点的 Rails 部署节点 上运行部署后迁移:
-
确保部署节点仍旧直接指向数据库 leader。如果当前节点通过 PgBouncer 来连接数据,则您必须绕过它,并在运行迁移之前直接连接到数据库。 - 要查找数据库主节点,您可以在任何数据库节点上运行以下命令 -
sudo gitlab-ctl patroni members
。 -
运行部署后迁移:
sudo gitlab-rake db:migrate
- 验证 Geo 配置和依赖项:
sudo gitlab-rake gitlab:geo:check
-
返回配置到正常状态,通过在
/etc/gitlab/gitlab.rb
配置文件中设置gitlab_rails['auto_migrate'] = false
。 - 如果使用 PgBouncer,请确保将数据库配置重新指向它。 -
运行
reconfigure
以重新应用正常配置并重启:
sudo gitlab-ctl reconfigure sudo gitlab-ctl restart
-
-
在辅助站点的 Rails 部署节点 上运行部署后 Geo 跟踪迁移:
-
运行部署后 Geo 跟踪迁移:
sudo gitlab-rake db:migrate:geo
-
验证 Geo 状态:
sudo gitlab-rake geo:status
-