零停机时间升级

通过零停机时间升级,可以在不下线的情况下升级正在运行的极狐GitLab 环境。本指南将带您完成执行此类升级的核心流程。

从高层次来看,这一过程是通过按一定顺序依次升级极狐GitLab 节点来完成的,利用负载均衡、HA 系统和优雅重载的组合来最大限度地减少中断。

本指南仅涉及适用的核心极狐GitLab 组件。对于第三方服务的升级或管理,如 AWS RDS,请参考相应的文档。

在您开始之前

实现升级过程中的_真正_零停机对于任何分布式应用程序来说都是非常困难的。本指南中详细描述的过程已经在我们的 HA 参考架构中进行了测试,结果是几乎没有可观察到的停机时间,但请注意,具体结果可能因系统组成的不同而有所差异。

为了增强信心,一些客户通过进一步的技术取得了成功,例如通过使用特定的负载均衡器或基础设施功能手动排空节点。这些技术在很大程度上依赖于底层基础设施的能力,因此未在本指南中介绍。有关任何其他信息,请联系您的极狐GitLab 代表或支持团队

要求和注意事项

零停机时间升级过程有以下要求:

  • 零停机时间升级仅支持使用 Linux 软件包构建并配置了负载均衡和 HA 机制的多节点极狐GitLab 环境:
    • 为 Rails 节点配置的外部负载均衡器,启用了针对 Readiness (/-/readiness) 端点的健康检查。
    • 为任何 PgBouncer 和 Praefect 组件配置的内部负载均衡器,启用了 TCP 健康检查。
    • 为 Consul、Postgres 和 Redis 组件配置的 HA 机制(如果存在)。
      • 任何未以 HA 方式部署的组件将需要单独升级并可能会有停机时间。
  • 一次只能升级一个小版本。所以从 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 的数据库通常不应超过一个小时,但具体情况可能会有所不同。
note如果您想要升级多个版本或不满足这些要求,则应探索有停机时间的升级

升级顺序

我们建议采用“从后到前”的方法来安排零停机时间升级组件的顺序。通常,这意味着首先是有状态的后端,然后是它们的依赖项,最后是前端。虽然部署的顺序可以更改,但最好将运行极狐GitLab 应用程序代码的组件(Rails、Sidekiq)一起部署。如果可能,单独升级支持基础设施(PostgreSQL、PgBouncer、Consul、Gitaly、Praefect、Redis),因为这些组件不依赖于版本更新中的更改。因此,我们通常建议以下顺序:

  1. Consul
  2. PostgreSQL
  3. PgBouncer
  4. Redis
  5. Gitaly
  6. Praefect
  7. Rails
  8. Sidekiq

多节点 / HA 部署

在本节中,我们将通过按照升级顺序依次升级每个节点,并让负载均衡器 / HA 机制相应地处理每个节点的停机,来逐步完成多节点极狐GitLab 环境的升级过程。

为了本指南的目的,我们将升级一个使用 Linux 软件包构建的200 RPS 或 10,000 用户参考架构

Consul、PostgreSQL、PgBouncer 和 Redis

ConsulPostgreSQLPgBouncerRedis 组件都遵循相同的基础流程以实现无停机时间的升级。

在每个组件的节点上按顺序运行以下步骤以执行升级:

  1. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

    sudo touch /etc/gitlab/skip-auto-reconfigure
    
  2. 升级极狐GitLab 软件包

  3. 重新配置并重新启动以获取最新代码:

    sudo gitlab-ctl reconfigure
    sudo gitlab-ctl restart
    

Gitaly

Gitaly 在升级时遵循相同的核心流程,但有一个关键区别,即 Gitaly 进程本身不会重启,因为它有一个内置的进程,可以在最早的机会优雅地重新加载。请注意,任何其他组件仍然需要重启。

note升级过程尝试优雅地交接到新的 Gitaly 进程。开始升级之前启动的现有长时间运行的 Git 请求可能会在此交接过程中最终被丢弃。

此过程适用于 Gitaly 分片和集群设置。在每个 Gitaly 节点上按顺序运行以下步骤以执行升级:

  1. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

    sudo touch /etc/gitlab/skip-auto-reconfigure
    
  2. 升级极狐GitLab 软件包
  3. 运行 reconfigure 命令以获取最新代码并指示 Gitaly 在下次机会时优雅地重新加载:

    sudo gitlab-ctl reconfigure
    
  4. 最后,虽然 Gitaly 会优雅地重新加载,但任何其他已部署的组件仍然需要重启:

    # 获取除 Gitaly 外其他已部署组件的列表
    sudo gitlab-ctl status
    
    # 重启除 Gitaly 外的每个组件。示例给出了 Consul、Node Exporter 和 Logrotate
    sudo gitlab-ctl restart consul node-exporter logrotate
    

Praefect

对于 Gitaly 集群设置,您必须通过使用优雅的重新加载来部署和升级 Praefect。

note升级过程尝试优雅地交接到新的 Praefect 进程。开始升级之前启动的现有长时间运行的 Git 请求可能会在此交接过程中最终被丢弃。

不过,对于 Praefect,还需要进行其数据库迁移以升级其数据。迁移只需要在一个 Praefect 节点上运行,以避免冲突。最好选择一个节点作为部署节点进行配置以运行迁移,而其他节点则不运行。我们将在下文中将其称为 Praefect 部署节点

  1. Praefect 部署节点上:

    1. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

      sudo touch /etc/gitlab/skip-auto-reconfigure
      
    2. 升级极狐GitLab 软件包

    3. 确保在 /etc/gitlab/gitlab.rb 中设置了 praefect['auto_migrate'] = true 以便运行数据库迁移。

    4. 运行 reconfigure 命令以获取最新代码,应用 Praefect 数据库迁移并优雅地重启:

      sudo gitlab-ctl reconfigure
      
  2. 在所有 剩余的 Praefect 节点上:

    1. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

      sudo touch /etc/gitlab/skip-auto-reconfigure
      
    2. 升级极狐GitLab 软件包

    3. 确保在 /etc/gitlab/gitlab.rb 中设置了 praefect['auto_migrate'] = false 以防止 reconfigure 自动运行数据库迁移。

    4. 运行 reconfigure 命令以获取最新代码并优雅地重启:

      sudo gitlab-ctl reconfigure
      
  3. 最后,虽然 Praefect 会优雅地重新加载,但任何其他已部署的组件仍然需要重启。在所有 Praefect 节点上:

    # 获取除 Praefect 外其他已部署组件的列表
    sudo gitlab-ctl status
    
    # 重启除 Praefect 外的每个组件。示例给出了 Consul、Node Exporter 和 Logrotate
    sudo gitlab-ctl restart consul node-exporter logrotate
    

Rails

作为 Web 服务器的 Rails 主要由 PumaWorkhorseNGINX 组成。

每个组件在执行实时升级时具有不同的行为。虽然 Puma 可以进行优雅的重新加载,但 Workhorse 不能。最佳方法是通过其他方式优雅地排空节点,例如使用负载均衡器。您也可以通过在节点上使用 NGINX 的优雅关闭功能来实现。本节解释了 NGINX 方法。

此外,Rails 是执行主要数据库迁移的地方。与 Praefect 类似,最佳方法是使用部署节点。如果当前使用 PgBouncer,还需要绕过它,因为 Rails 在尝试运行迁移时使用建议锁,以防止在同一数据库上运行并发迁移。这些锁不会在事务之间共享,导致 ActiveRecord::ConcurrentMigrationError 和使用事务池模式在 PgBouncer 中运行数据库迁移时的其他问题。

  1. Rails 部署节点上:

    1. 优雅地排空节点流量。您可以通过多种方式实现,但一种方法是通过发送 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
      
    2. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

      sudo touch /etc/gitlab/skip-auto-reconfigure
      
    3. 升级极狐GitLab 软件包

    4. /etc/gitlab/gitlab.rb 配置文件中设置 gitlab_rails['auto_migrate'] = true 来配置常规迁移。
      • 如果部署节点当前通过 PgBouncer 连接到数据库,则在运行迁移之前,您必须绕过它并直接连接到数据库主节点。
      • 要查找数据库主节点,您可以在任何数据库节点上运行以下命令 - sudo gitlab-ctl patroni members
    5. 运行常规迁移并获取最新代码:

      sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-ctl reconfigure
      
    6. 现在保持此节点不变,因为稍后您将返回运行部署后迁移。
  2. 在每个其他 Rails 节点上按顺序执行:

    1. 优雅地排空节点流量。您可以通过多种方式实现,但一种方法是通过发送 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
      
    2. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

      sudo touch /etc/gitlab/skip-auto-reconfigure
      
    3. 升级极狐GitLab 软件包

    4. 确保在 /etc/gitlab/gitlab.rb 中设置 gitlab_rails['auto_migrate'] = false 以防止 reconfigure 自动运行数据库迁移。

    5. 运行 reconfigure 命令以获取最新代码并重启:

      sudo gitlab-ctl reconfigure
      sudo gitlab-ctl restart
      
  3. Rails 部署节点上运行部署后迁移:

    1. 确保部署节点仍直接指向数据库主节点。如果节点当前通过 PgBouncer 连接到数据库,则在运行迁移之前,您必须绕过它并直接连接到数据库主节点。
      • 要查找数据库主节点,您可以在任何数据库节点上运行以下命令 - sudo gitlab-ctl patroni members
    2. 运行部署后迁移:

      sudo gitlab-rake db:migrate
      
    3. 通过在 /etc/gitlab/gitlab.rb 配置文件中设置 gitlab_rails['auto_migrate'] = false,将配置恢复正常。
      • 如果正在使用 PgBouncer,请确保数据库配置再次指向它
    4. 再次运行 reconfigure 以重新应用正常配置并重启:

      sudo gitlab-ctl reconfigure
      sudo gitlab-ctl restart
      

Sidekiq

Sidekiq 遵循与其他组件相同的基础流程,以实现无停机时间的升级。

在每个组件节点上按顺序运行以下步骤以执行升级:

  1. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

    sudo touch /etc/gitlab/skip-auto-reconfigure
    
  2. 升级极狐GitLab 软件包

  3. 运行 reconfigure 命令以获取最新代码并重启:

    sudo gitlab-ctl reconfigure
    sudo gitlab-ctl restart
    

使用 Geo 进行多节点高可用部署

本节描述了升级实时极狐GitLab 环境与 Geo 部署所需的步骤。

总体而言,该方法与常规流程基本相同,但每个辅助站点需要执行一些额外的步骤。所需的顺序是首先升级主站点,然后是辅助站点。在所有辅助站点更新后,您还必须在主站点上运行任何部署后迁移。

note升级实时极狐GitLab 环境与 Geo 的相同要求和注意事项适用。

主站点

主站点的升级过程与常规流程相同,唯一的例外是在所有辅助站点更新之前不要运行部署后迁移。

按照描述的主站点步骤进行操作,但在 Rails 节点步骤的运行部署后迁移处停止。

辅助站点

任何辅助站点的升级过程遵循与常规流程相同的步骤,除了 Rails 节点,还需要进行一些额外的步骤,如下所述。

要升级站点,请按照常规流程步骤进行操作,直到 Rails 节点,然后按照以下步骤进行操作:

Rails

  1. Rails 部署节点上:

    1. 优雅地排空节点流量。您可以通过多种方式实现,但一种方法是通过发送 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
      
    2. 停止 Geo Log Cursor 进程以确保其切换到另一个节点:

      gitlab-ctl stop geo-logcursor
      
    3. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

      sudo touch /etc/gitlab/skip-auto-reconfigure
      
    4. 升级极狐GitLab 软件包

    5. 如果主站点的 Rails 节点和辅助站点的 Rails 节点不同,请将 /etc/gitlab/gitlab-secrets.json 文件从主站点的 Rails 节点复制到辅助站点的 Rails 节点。文件在站点的所有节点上必须相同。

    6. 确保没有迁移被配置为自动运行,通过在 /etc/gitlab/gitlab.rb 配置文件中设置 gitlab_rails['auto_migrate'] = falsegeo_secondary['auto_migrate'] = false

    7. 运行 reconfigure 命令以获取最新代码并重启:

      sudo gitlab-ctl reconfigure
      sudo gitlab-ctl restart
      
    8. 运行常规 Geo 跟踪迁移并获取最新代码:

      sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-rake db:migrate:geo
      
  2. 在每个其他 Rails 节点上按顺序执行:

    1. 优雅地排空节点流量。您可以通过多种方式实现,但一种方法是通过发送 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
      
    2. 停止 Geo Log Cursor 进程以确保其切换到另一个节点:

      gitlab-ctl stop geo-logcursor
      
    3. /etc/gitlab/skip-auto-reconfigure 处创建一个空文件。这可以防止升级时运行 gitlab-ctl reconfigure,默认情况下它会自动停止极狐GitLab,运行所有数据库迁移,并重新启动极狐GitLab:

      sudo touch /etc/gitlab/skip-auto-reconfigure
      
    4. 升级极狐GitLab 软件包

    5. 确保没有迁移被配置为自动运行,通过在 /etc/gitlab/gitlab.rb 配置文件中设置 gitlab_rails['auto_migrate'] = falsegeo_secondary['auto_migrate'] = false

    6. 运行 reconfigure 命令以获取最新代码并重启:

      sudo gitlab-ctl reconfigure
      sudo gitlab-ctl restart
      

Sidekiq

按照主要流程,现在剩下的就是升级 Sidekiq 了。

主节中描述的方式升级 Sidekiq。

部署后迁移

最后,回到主站点并通过运行部署后迁移来完成升级:

  1. 在主站点的 Rails 部署节点 上运行部署后迁移:

    1. 确保部署节点仍旧直接指向数据库 leader。如果当前节点通过 PgBouncer 来连接数据,则您必须绕过它,并在运行迁移之前直接连接到数据库。 - 要查找数据库主节点,您可以在任何数据库节点上运行以下命令 - sudo gitlab-ctl patroni members

    2. 运行部署后迁移:

       sudo gitlab-rake db:migrate
    
    1. 验证 Geo 配置和依赖项:
       sudo gitlab-rake gitlab:geo:check
    
    1. 返回配置到正常状态,通过在 /etc/gitlab/gitlab.rb 配置文件中设置 gitlab_rails['auto_migrate'] = false。 - 如果使用 PgBouncer,请确保将数据库配置重新指向它。

    2. 运行 reconfigure 以重新应用正常配置并重启:

       sudo gitlab-ctl reconfigure
       sudo gitlab-ctl restart
    
  2. 在辅助站点的 Rails 部署节点 上运行部署后 Geo 跟踪迁移:

    1. 运行部署后 Geo 跟踪迁移:

      sudo gitlab-rake db:migrate:geo
      
    2. 验证 Geo 状态:

      sudo gitlab-rake geo:status