极狐 GitLab

恢复极狐GitLab

Tier: 基础版,专业版,旗舰版

Offering: 私有化部署

极狐GitLab 恢复操作从备份中恢复数据,以维持系统连续性并从数据丢失中恢复。恢复操作:

  • 恢复数据库记录和配置
  • 恢复 Git 仓库、容器镜像仓库镜像和上传的内容
  • 恢复软件包仓库数据和 CI/CD 产物
  • 恢复账号和群组设置
  • 恢复项目和群组 Wiki
  • 恢复项目级安全文件
  • 恢复外部合并请求差异

恢复过程需要一个与备份版本相同的现有极狐GitLab 安装。请遵循前提条件并在生产环境中使用前测试完整的恢复过程。

恢复前提条件#

目标极狐GitLab 实例必须已经在运行#

您需要拥有一个可正常工作的极狐GitLab 安装,然后才能执行恢复。这是因为执行恢复操作的系统用户(git)通常没有创建或删除用于导入数据的 SQL 数据库(gitlabhq_production)的权限。

目标极狐GitLab 实例不能有现有数据#

恢复过程根据数据类型以不同方式处理现有数据:

  • PostgreSQL 数据在恢复过程中自动擦除。
  • Git 仓库:如果已存在同名仓库,恢复会失败并显示“仓库已存在”错误。有关更多信息,请参见议题 118459。
  • 文件系统数据在恢复前会尝试移动到单独的目录。
  • 对象存储数据不会自动清除。您必须在恢复前手动清空对象存储桶,以避免保留孤立数据。

为了获得可靠的恢复过程,例如自动化生产到预发布环境的恢复,请使用与备份相同版本的纯净极狐GitLab 安装。

恢复 SQL 数据会跳过由 PostgreSQL 扩展拥有的视图。

目标极狐GitLab 实例必须具有完全相同的版本#

您只能将备份恢复到创建该备份时完全相同的极狐GitLab 版本和类型(基础版 或 企业版)。例如,基础版 15.1.4。

如果您的备份与当前安装的版本不同,您必须先降级升级您的极狐GitLab 安装,然后再恢复备份。

必须恢复极狐GitLab 密钥#

要恢复备份,您还必须恢复极狐GitLab 密钥。如果要迁移到新的极狐GitLab 实例,则必须从旧服务器复制极狐GitLab 密钥文件。这些密钥包括数据库加密密钥、CI/CD 变量以及用于双重认证的变量。如果没有这些密钥,将出现多个问题,包括启用了双重认证的用户无法访问,以及极狐GitLab Runner 无法登录。

恢复到不同 FQDN 时 WebAuthn 设备会被禁用: WebAuthn 注册(例如 YubiKeys)在加密上绑定到其创建时的来源 (域/主机名)。如果您将备份恢复到与原始实例具有不同 FQDN 的极狐GitLab 实例, 所有 WebAuthn 设备都将被禁用。 用户需要在恢复完成后重新注册其 WebAuthn 设备。 有关 WebAuthn 和主机名要求的更多信息,请参见 双重认证

根据您的安装方法,恢复以下内容:

plaintext
/etc/gitlab/gitlab-secrets.json

另请参见:

某些极狐GitLab 配置必须与原始备份环境匹配#

您可能需要单独恢复之前的 /etc/gitlab/gitlab.rb(对于 Linux 包安装)或 /home/git/gitlab/config/gitlab.yml(对于自编译安装)以及任何 TLS 或 SSH 密钥和证书。

某些配置与 PostgreSQL 中的数据耦合。例如:

  • 如果原始环境有三个仓库存储(例如 defaultmy-storage-1my-storage-2),那么目标环境也必须在配置中至少定义这些存储名称。
  • 从使用本地存储的环境恢复备份会恢复到本地存储,即使目标环境使用对象存储也是如此。迁移到对象存储必须在恢复之前或之后完成。

有关更多信息,请参见备份中未包含的数据

恢复作为挂载点的目录#

如果您正在恢复到作为挂载点的目录中,您必须确保这些目录在尝试恢复之前是空的。否则,极狐GitLab 在恢复新数据之前会尝试移动这些目录,这会导致错误。

阅读更多关于配置 NFS 挂载的信息。

适用于 Linux 包安装的恢复#

此过程假设:

  • 您已安装用于创建备份的完全相同版本和类型(基础版/企业版)的极狐GitLab。
  • 您至少运行过一次 sudo gitlab-ctl reconfigure
  • 极狐GitLab 正在运行。如果没有,使用 sudo gitlab-ctl start 启动它。

首先确保您的备份 tar 文件位于 gitlab.rb 配置 gitlab_rails['backup_path'] 中描述的备份目录中。默认为 /var/opt/gitlab/backups。备份文件需要归 git 用户所有。

shell
sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/ sudo chown git:git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar

停止连接到数据库的进程。让极狐GitLab 的其余部分保持运行:

shell
sudo gitlab-ctl stop puma sudo gitlab-ctl stop sidekiq # 验证 sudo gitlab-ctl status

接下来,确保您已完成恢复前提条件步骤,并在从原始安装复制极狐GitLab 密钥文件后运行了 gitlab-ctl reconfigure

然后,恢复备份,指定您想要恢复的备份 ID:

以下命令会覆盖极狐GitLab 数据库的内容!

shell
# 注意:名称中省略了 "_gitlab_backup.tar" sudo gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce

如果您的备份 tar 文件与已安装的极狐GitLab 版本不匹配,恢复命令会中止并显示错误消息:

plaintext
极狐GitLab 版本不匹配: 您当前的极狐GitLab 版本 (16.5.0-ee) 与备份中的极狐GitLab 版本不同! 请切换到以下版本并重试: 版本: 16.4.3-ee

安装正确的极狐GitLab 版本,然后重试。

当您的安装使用 PgBouncer 时,无论是出于性能原因还是与 Patroni 集群一起使用,恢复命令都需要额外的参数

在 PostgreSQL 节点上运行 reconfigure:

shell
sudo gitlab-ctl reconfigure

接下来,启动并检查极狐GitLab:

shell
sudo gitlab-ctl start sudo gitlab-rake gitlab:check SANITIZE=true

验证数据库值是否可以解密,特别是当 /etc/gitlab/gitlab-secrets.json 被恢复,或者恢复目标是不同的服务器时。

shell
sudo gitlab-rake gitlab:doctor:secrets

为了更加确保,您可以对上传的文件进行完整性检查:

shell
sudo gitlab-rake gitlab:artifacts:check sudo gitlab-rake gitlab:lfs:check sudo gitlab-rake gitlab:uploads:check

恢复完成后,建议生成数据库统计信息以提高数据库性能并避免 UI 中的不一致:

  1. 进入数据库控制台

  2. 运行以下命令:

    sql
    SET STATEMENT_TIMEOUT=0 ; ANALYZE VERBOSE;

关于将此命令集成到恢复命令中的讨论正在进行中,详情请参见议题 276184。

恢复后验证指南:

适用于 Docker 镜像和极狐GitLab Helm chart 安装的恢复#

对于使用 Docker 镜像或在 Kubernetes 集群上使用极狐GitLab Helm chart 的极狐GitLab 安装,恢复任务期望恢复目录为空。但是,对于 Docker 和 Kubernetes 卷挂载,某些系统级目录可能会在卷根目录下创建,例如 Linux 操作系统中的 lost+found 目录。这些目录通常归 root 所有,这可能因恢复 Rake 任务以 git 用户身份运行而导致访问权限错误。要恢复极狐GitLab 安装,用户必须确认恢复目标目录为空。

对于这两种安装类型,备份 tar 包必须放在备份位置(默认位置为 /var/opt/gitlab/backups)。

适用于 Helm chart 安装的恢复#

极狐GitLab Helm chart 使用恢复极狐GitLab Helm chart 安装中记录的过程。

适用于 Docker 镜像安装的恢复#

如果您使用 Docker Swarm,容器可能在恢复过程中因 Puma 关闭而重启,从而导致容器健康检查失败。要解决此问题,请暂时禁用健康检查机制。

  1. 编辑 docker-compose.yml

    yaml
    healthcheck: disable: true
  2. 部署堆栈:

    shell
    docker stack deploy --compose-file docker-compose.yml mystack

有关更多信息,请参见议题 6846。

可以从主机运行恢复任务:

shell
1# 停止连接到数据库的进程 2docker exec -it <容器名称> gitlab-ctl stop puma 3docker exec -it <容器名称> gitlab-ctl stop sidekiq 4 5# 继续之前验证进程都已停止 6docker exec -it <容器名称> gitlab-ctl status 7 8# 运行恢复。注意:名称中省略了 "_gitlab_backup.tar" 9docker exec -it <容器名称> gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce 10 11# 重启极狐GitLab 容器 12docker restart <容器名称> 13 14# 检查极狐GitLab 15docker exec -it <容器名称> gitlab-rake gitlab:check SANITIZE=true

适用于自编译安装的恢复#

  1. 首先,确保您的备份 tar 文件位于 gitlab.yml 配置中描述的备份目录中:

    yaml
    ## Backup settings backup: path: "tmp/backups" # 相对路径相对于 Rails.root(默认:tmp/backups/)

    默认路径是 /home/git/gitlab/tmp/backups,并且需要归 git 用户所有。

  2. 开始备份恢复过程:

    shell
    # 停止连接到数据库的进程 sudo service gitlab stop sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production

    示例输出:

    plaintext
    1解压备份... [完成] 2恢复数据库表: 3-- create_table("events", {:force=>true}) 4 -> 0.2231s 5[...] 6- 加载固定数据 events...[完成] 7- 加载固定数据 issues...[完成] 8- 加载固定数据 keys...[跳过] 9- 加载固定数据 merge_requests...[完成] 10- 加载固定数据 milestones...[完成] 11- 加载固定数据 namespaces...[完成] 12- 加载固定数据 notes...[完成] 13- 加载固定数据 projects...[完成] 14- 加载固定数据 protected_branches...[跳过] 15- 加载固定数据 schema_migrations...[完成] 16- 加载固定数据 services...[跳过] 17- 加载固定数据 snippets...[跳过] 18- 加载固定数据 taggings...[跳过] 19- 加载固定数据 tags...[跳过] 20- 加载固定数据 users...[完成] 21- 加载固定数据 users_projects...[完成] 22- 加载固定数据 web_hooks...[跳过] 23- 加载固定数据 wikis...[跳过] 24恢复仓库: 25- 恢复仓库 abcd... [完成] 26- 对象池 1 ... 27删除临时目录...[完成]
  3. 如果需要,恢复 /home/git/gitlab/.secret

  4. 重启极狐GitLab:

    shell
    sudo service gitlab restart

从备份中仅恢复一个或几个项目或群组#

尽管用于恢复极狐GitLab 实例的 Rake 任务不支持恢复单个项目或群组,但您可以通过将备份恢复到单独的临时极狐GitLab 实例,然后从那里导出您的项目或群组来解决:

  1. 安装一个新的极狐GitLab 实例,其版本与要恢复的备份实例相同。
  2. 将备份恢复到该新实例,然后导出您的项目群组。有关导出和不支持导出的内容的更多信息,请参见导出功能的文档。
  3. 导出完成后,转到旧实例,然后导入它。
  4. 所需项目或群组导入完成后,您可以删除新的临时极狐GitLab 实例。

有关提供直接恢复单个项目或群组的功能请求正在议题 #17517 中讨论。

恢复增量仓库备份#

当您使用 gitlab-backup 创建增量仓库备份时,生成的备份存档包含完整恢复所需的所有仓库数据。要恢复,请使用与恢复任何其他常规备份存档相同的说明。

在内部,增量仓库备份仅存储前一个备份后所做的更改。创建增量备份时,gitlab-backup 会将从原始完整备份开始的每一步都打包到备份存档中。这意味着该存档是自包含的,即使各个仓库备份包之间存在依赖关系。

使用服务器端仓库备份时,备份存档不包含仓库数据。相反,仓库数据由每个 Gitaly 节点存储在对象存储中,并且每个增量存储为单独的对象。在服务器端恢复中,Gitaly 读取备份清单并按顺序应用每个增量。

不要从对象存储中删除增量备份文件。如果删除了中间文件(例如,通过对象存储生命周期策略),备份链将中断,备份将无法恢复。

恢复选项#

极狐GitLab 提供的用于从备份恢复的命令行工具支持更多选项。

存在多个备份时指定要恢复的备份#

备份文件使用以备份 ID 开头的命名方案。当存在多个备份时,您必须通过设置环境变量 BACKUP=<backup-id> 来指定要恢复的 <备份ID>_gitlab_backup.tar 文件。

恢复期间禁用提示#

在从备份恢复期间,恢复脚本会提示确认:

  • 如果启用了写入 authorized_keys 设置,则在恢复脚本删除并重建 authorized_keys 文件之前。
  • 恢复数据库时,在恢复脚本删除所有现有表之前。
  • 恢复数据库后,如果恢复架构时出现错误,则在继续之前,因为很可能会出现更多问题。

要禁用这些提示,请将 GITLAB_ASSUME_YES 环境变量设置为 1

  • Linux 包安装:

    shell
    sudo GITLAB_ASSUME_YES=1 gitlab-backup restore
  • 自编译安装:

    shell
    sudo -u git -H GITLAB_ASSUME_YES=1 bundle exec rake gitlab:backup:restore RAILS_ENV=production

force=yes 环境变量也会禁用这些提示。

恢复时排除任务#

您可以通过添加环境变量 SKIP 在恢复时排除特定任务,其值是一个逗号分隔的列表,包含以下选项:

  • db(数据库)
  • uploads(附件)
  • builds(CI 作业输出日志)
  • artifacts(CI 作业产物)
  • lfs(LFS 对象)
  • terraform_state(Terraform 状态)
  • registry(容器镜像仓库镜像)
  • pages(Pages 内容)
  • repositories(Git 仓库数据)
  • packages(软件包)

要排除特定任务:

  • Linux 包安装:

    shell
    sudo gitlab-backup restore BACKUP=<backup-id> SKIP=db,uploads
  • 自编译安装:

    shell
    sudo -u git -H bundle exec rake gitlab:backup:restore BACKUP=<backup-id> SKIP=db,uploads RAILS_ENV=production

恢复特定仓库存储#

版本历史
  • 在极狐GitLab 15.0 中引入。

极狐GitLab 17.1 及更早版本受到竞态条件影响,可能导致数据丢失。该问题影响已分叉的仓库和使用极狐GitLab 对象池的仓库。为避免数据丢失,请仅使用极狐GitLab 17.2 或更高版本恢复备份。

使用多个仓库存储时,可以使用 REPOSITORIES_STORAGES 选项分别恢复特定仓库存储中的仓库。该选项接受以逗号分隔的存储名称列表。

例如:

  • Linux 包安装:

    shell
    sudo gitlab-backup restore BACKUP=<backup-id> REPOSITORIES_STORAGES=storage1,storage2
  • 自编译安装:

    shell
    sudo -u git -H bundle exec rake gitlab:backup:restore BACKUP=<backup-id> REPOSITORIES_STORAGES=storage1,storage2

恢复特定仓库#

版本历史
  • 在极狐GitLab 15.1 中引入。

极狐GitLab 17.1 及更早版本受到竞态条件影响,可能导致数据丢失。该问题影响已分叉的仓库和使用极狐GitLab 对象池的仓库。为避免数据丢失,请仅使用极狐GitLab 17.2 或更高版本恢复备份。

您可以使用 REPOSITORIES_PATHSSKIP_REPOSITORIES_PATHS 选项恢复特定仓库。这两个选项都接受以逗号分隔的项目和群组路径列表。如果您指定群组路径,该群组及其后代群组中所有项目的所有仓库都将根据您使用的选项被包含或跳过。群组和项目必须存在于指定的备份中或目标实例上。

REPOSITORIES_PATHSSKIP_REPOSITORIES_PATHS 选项仅适用于 Git 仓库。它们不适用于项目或群组数据库条目。如果您使用 SKIP=db 创建了仓库备份,则该备份本身无法用于将特定仓库恢复到新实例。

例如,恢复群组 A(group-a)中所有项目的所有仓库、群组 B 中的项目 C(group-b/project-c)的仓库,并跳过群组 A 中的项目 D(group-a/project-d):

  • Linux 包安装:

    shell
    sudo gitlab-backup restore BACKUP=<backup-id> REPOSITORIES_PATHS=group-a,group-b/project-c SKIP_REPOSITORIES_PATHS=group-a/project-d
  • 自编译安装:

    shell
    sudo -u git -H bundle exec rake gitlab:backup:restore BACKUP=<backup-id> REPOSITORIES_PATHS=group-a,group-b/project-c SKIP_REPOSITORIES_PATHS=group-a/project-d

恢复未压缩备份#

如果发现未压缩备份(使用 SKIP=tar 创建),并且没有使用 BACKUP=<backup-id> 选择备份,则将使用未压缩备份。

例如:

  • Linux 包安装:

    shell
    sudo gitlab-backup restore
  • 自编译安装:

    shell
    sudo -u git -H bundle exec rake gitlab:backup:restore

使用服务器端仓库备份进行恢复#

版本历史
  • 在极狐GitLab 16.3 的 gitlab-backup 中引入。
  • 在极狐GitLab 16.6 中,gitlab-backup 支持服务器端恢复指定备份而非最新备份。
  • 在极狐GitLab 16.6 中,gitlab-backup 支持创建增量备份的服务器端支持。
  • 在极狐GitLab 17.0 中,backup-utility 支持服务器端。

当收集了服务器端备份时,恢复过程默认使用创建服务器端仓库备份中所示的服务器端恢复机制。您可以配置备份恢复,使得托管每个仓库的 Gitaly 节点负责直接从对象存储拉取必要的备份数据。

  1. 在 Gitaly 中配置服务器端备份目标
  2. 启动服务器端备份恢复过程,并指定您想要恢复的备份 ID
shell
sudo gitlab-backup restore BACKUP=11493107454_2018_04_25_10.6.4-ce

故障排查#

以下是您可能遇到的问题以及可能的解决方案。

恢复数据库备份时使用 Linux 包安装的输出警告#

如果您使用备份恢复过程,可能会遇到以下警告消息:

plaintext
ERROR: 必须是扩展 pg_trgm 的所有者 ERROR: 必须是扩展 btree_gist 的所有者 ERROR: 必须是扩展 plpgsql 的所有者 WARNING: 无法对 "public" 撤销权限(出现两次) WARNING: 未对 "public" 授予权限(出现两次)

请注意,尽管出现这些警告消息,备份已成功恢复。

Rake 任务以 gitlab 用户身份运行,该用户对数据库没有超级用户访问权限。当启动恢复时,它也会以 gitlab 用户身份运行,但它也尝试更改无法访问的对象。这些对象对数据库备份或恢复没有影响,但会显示警告消息。

有关更多信息,请参见:

因 Git 服务器钩子导致恢复失败#

在从备份恢复时,若满足以下条件,你可能会遇到错误:

  • 使用 极狐GitLab 15.10 及更早版本 的方法配置了一个 Git 服务器钩子(custom_hook
  • 你的 极狐GitLab 版本是 15.11 及更高版本
  • 你创建了指向 极狐GitLab 管理的位置之外目录的符号链接

错误如下所示:

plaintext
{"level":"fatal","msg":"restore: pipeline: 1 failures encountered:\n - @hashed/path/to/hashed_repository.git (path/to_project): manager: restore custom hooks, \"@hashed/path/to/hashed_repository/<BackupID>_<GitLabVersion>-jh.001.custom_hooks.tar\": rpc error: code = Internal desc = setting custom hooks: generating prepared vote: walking directory: copying file to hash: read /mnt/gitlab-app/git-data/repositories/+gitaly/tmp/default-repositories.old.<timestamp>.<temporaryfolder>/custom_hooks/compliance-triggers.d: is a directory\n","pid":3256017,"time":"2023-08-10T20:09:44.395Z"}

要解决此问题,你可以更新适用于 极狐GitLab 15.11 及更高版本的 Git 服务器钩子,并创建新备份。

使用 fapolicyd 时恢复成功但代码库显示为空#

当使用 fapolicyd 增强安全性时,极狐GitLab 可能报告恢复成功,但代码库显示为空。有关更多故障排除帮助,请参阅 Gitaly 故障排除文档