备份极狐GitLab
- Tier: 基础版,专业版,旗舰版
- Offering: 私有化部署
极狐GitLab备份保护您的数据并帮助进行灾难恢复。
最佳备份策略取决于您的极狐GitLab部署配置、数据量和存储位置。这些因素决定了使用哪些备份方法、在哪里存储备份以及如何安排备份计划。
对于较大的极狐GitLab实例,替代备份策略包括:
- 增量备份。
- 特定仓库的备份。
- 跨多个存储位置的备份。
备份中包含的数据
默认情况下,备份会在一个单一压缩的 tar 文件中创建一个归档。该文件包括:
- 数据库数据和配置
- Git 仓库、容器注册表图像和上传的内容
- 软件包注册表数据和 CI/CD 产物
- 账户和群组设置
- 项目和群组 wiki
- 项目级别的安全文件
- 外部合并请求差异
简单备份程序
作为一个粗略的指导,如果您使用 1k 参考架构 并且数据量小于 100 GB,请按照以下步骤操作:
扩展备份
随着极狐GitLab数据量的增长,备份命令执行的时间会更长。备份选项比如 并发备份 Git 仓库 和 增量仓库备份 可以帮助减少执行时间。在某些时候,备份命令本身变得不切实际。例如,它可能需要 24 小时或更长时间。
在某些情况下,可能需要进行架构更改以允许备份扩展。如果您使用极狐GitLab参考架构,请参阅 备份和恢复大型参考架构。
有关更多信息,请参阅 替代备份策略。
需要备份什么数据?
PostgreSQL 数据库
在最简单的情况下,极狐GitLab在与所有其他极狐GitLab服务相同的虚拟机上有一个 PostgreSQL 数据库。但是根据配置,极狐GitLab可能会使用多个 PostgreSQL 数据库在多个 PostgreSQL 服务器上。
通常,这些数据是 Web 界面中大多数用户生成内容的唯一真实来源,例如议题和合并请求内容、评论、权限和凭证。
PostgreSQL 还存储一些缓存数据,比如 HTML 渲染的 Markdown,默认情况下,合并请求差异。但是,合并请求差异也可以配置为卸载到文件系统或对象存储,请参阅 Blobs。
Gitaly Cluster 的 Praefect 服务使用 PostgreSQL 数据库作为管理其 Gitaly 节点的唯一真实来源。
一个常见的 PostgreSQL 工具,pg_dump,生成一个备份文件,该文件可以用于恢复 PostgreSQL 数据库。备份命令在后台使用此实用程序。
不幸的是,数据库越大,pg_dump执行的时间就越长。根据您的情况,持续时间在某些时候变得不切实际(例如几天)。如果您的数据库超过 100 GB,pg_dump以及扩展的备份命令,可能无法使用。有关更多信息,请参阅 替代备份策略。
Git 仓库
一个极狐GitLab实例可以有一个或多个仓库碎片。每个碎片都是一个 Gitaly 实例或 Gitaly 集群,负责允许访问和操作本地存储的 Git 仓库。Gitaly 可以在机器上运行:
- 使用单个磁盘。
- 使用多个磁盘作为单个挂载点(例如 RAID 阵列)。
- 使用 LVM。
每个项目可以有最多 3 个不同的仓库:
- 项目仓库,存储源代码。
- wiki 仓库,存储 wiki 内容。
- 设计仓库,设计产物被索引(资产实际上在 LFS 中)。
它们都位于同一个碎片中,并共享相同的基本名称,-wiki 和 -design 后缀用于 Wiki 和设计仓库案例。
个人和项目片段,以及群组 wiki 内容,都存储在 Git 仓库中。
项目分叉在一个实时的极狐GitLab站点中使用池仓库进行去重。
备份命令为每个仓库生成一个 Git 包,并将它们全部打包。这会将池仓库数据复制到每个分叉中。在我们的测试中,100 GB 的 Git 仓库备份和上传到 S3 花费了稍微超过 2 小时。在大约 400 GB 的 Git 数据时,备份命令可能不适用于常规备份。有关更多信息,请参阅 替代备份策略。
Blobs
极狐GitLab将 blob(或文件)如议题附件或 LFS 对象存储到:
- 文件系统中的特定位置。
- 一个 对象存储 解决方案。对象存储解决方案可以是:
- 云端的,如 Amazon S3 和 Google Cloud Storage。
- 您自己托管的(如 MinIO)。
- 一个存储设备,提供一个对象存储兼容的 API。
对象存储
备份命令不备份未存储在文件系统上的 blob。如果您正在使用 对象存储,请确保启用与对象存储提供商的备份。例如,请参阅:
- Amazon S3 备份
- Google Cloud Storage 转移服务和 Google Cloud Storage 对象版本控制
容器注册表
极狐GitLab容器注册表存储可以配置在以下位置:
- 文件系统中的特定位置。
- 一个 对象存储 解决方案。对象存储解决方案可以是:
- 云端的,如 Amazon S3 和 Google Cloud Storage。
- 您自己托管的(如 MinIO)。
- 一个存储设备,提供一个对象存储兼容的 API。
备份命令不备份存储在对象存储中的注册表数据。
存储配置文件
极狐GitLab提供的备份 Rake 任务不存储您的配置文件。主要原因是您的数据库包含包括用于双因素认证和 CI/CD 安全变量的加密信息的项目。将加密信息存储在与其密钥相同的位置会失去使用加密的目的。例如,密钥文件包含您的数据库加密密钥。如果丢失它,极狐GitLab应用程序将无法解密数据库中的任何加密值。
密钥文件可能在升级后发生变化。
您应该备份配置目录。至少,您必须备份:
- /etc/gitlab/gitlab-secrets.json
- /etc/gitlab/gitlab.rb
有关更多信息,请参阅 备份和恢复 Linux 软件包 (Omnibus) 配置。
您可能还希望备份任何 TLS 密钥和证书 (/etc/gitlab/ssl, /etc/gitlab/trusted-certs),以及您的 SSH 主机密钥,以避免在进行完整机器恢复时出现中间人攻击警告。
在不太可能发生的密钥文件丢失情况下,请参阅 当密钥文件丢失时。
其他数据
极狐GitLab使用 Redis 作为缓存存储,并为我们的后台作业系统 Sidekiq保存持久数据。提供的备份命令不备份 Redis 数据。这意味着要进行一致的备份,必须没有待处理或正在运行的后台作业。有可能手动备份 Redis。
Elasticsearch 是一个可选的数据库,用于高级搜索。它可以在源代码级别和用户生成的内容(如议题、合并请求和讨论)中提高搜索性能。备份命令不备份 Elasticsearch 数据。Elasticsearch 数据可以在恢复后从 PostgreSQL 数据中再生。有可能手动备份 Elasticsearch。
命令行界面
极狐GitLab提供命令行界面来备份整个实例,包括:
- 数据库
- 附件
- Git 仓库数据
- CI/CD 作业输出日志
- CI/CD 作业产物
- LFS 对象
- Terraform 状态
- 容器注册表图像
- 极狐GitLab Pages 内容
- 软件包
- 代码片段
- 群组 wiki
- 项目级别的安全文件(在极狐GitLab 16.1中引入)
- 外部合并请求差异(在极狐GitLab 17.1中引入)
备份不包括:
- Mattermost 数据
- Redis(因此 Sidekiq 作业)
- Linux 软件包 (Omnibus) / Docker / 自编译安装中的对象存储
- 全局服务器钩子
- 文件钩子
极狐GitLab不备份任何配置文件 (/etc/gitlab)、TLS 密钥和证书或系统文件。强烈建议您阅读有关存储配置文件的内容。
要求
为了能够备份和恢复,请确保您的系统上安装了 Rsync。如果您安装了极狐GitLab:
-
使用 Linux 软件包,Rsync 已经安装。
-
使用自编译,检查是否安装了 rsync。如果没有安装 Rsync,请安装它。例如:
shell# Debian/Ubuntu sudo apt-get install rsync # RHEL/CentOS sudo yum install rsync
备份命令
备份命令不备份 Linux 软件包 (Omnibus) / Docker / 自编译安装中的对象存储中的项目。
当您的安装使用 PgBouncer 时,备份命令需要额外参数,无论是出于性能原因还是与 Patroni 集群一起使用。
在极狐GitLab 15.5.0 之前,备份命令不会检查是否已有其他备份正在运行。我们强烈建议您确保所有备份完成后再开始新的备份。
您只能将备份恢复到**完全相同版本和类型 (CE/EE)**的极狐GitLab上。
shellsudo gitlab-backup create
如果您的极狐GitLab部署有多个节点,您需要选择一个节点来运行备份命令。您必须确保指定的节点:
- 是持久的,并且不受自动扩展影响。
- 已经安装了极狐GitLab Rails 应用程序。如果 Puma 或 Sidekiq 正在运行,则 Rails 已安装。
- 具有足够的存储和内存来生成备份文件。
示例输出:
plaintext1Dumping database tables: 2- Dumping table events... [DONE] 3- Dumping table issues... [DONE] 4- Dumping table keys... [DONE] 5- Dumping table merge_requests... [DONE] 6- Dumping table milestones... [DONE] 7- Dumping table namespaces... [DONE] 8- Dumping table notes... [DONE] 9- Dumping table projects... [DONE] 10- Dumping table protected_branches... [DONE] 11- Dumping table schema_migrations... [DONE] 12- Dumping table services... [DONE] 13- Dumping table snippets... [DONE] 14- Dumping table taggings... [DONE] 15- Dumping table tags... [DONE] 16- Dumping table users... [DONE] 17- Dumping table users_projects... [DONE] 18- Dumping table web_hooks... [DONE] 19- Dumping table wikis... [DONE] 20Dumping repositories: 21- Dumping repository abcd... [DONE] 22Creating backup archive: <backup-id>_gitlab_backup.tar [DONE] 23Deleting tmp directories...[DONE] 24Deleting old backups... [SKIPPING]
有关备份过程的详细信息,请参阅 备份归档过程。
备份选项
极狐GitLab提供的命令行工具可以接受更多选项。
备份策略选项
默认备份策略是使用 Linux 命令 tar 和 gzip 从相应的数据位置向备份流式传输数据。这在大多数情况下都能正常工作,但在数据快速变化时可能会导致问题。
当数据在 tar 读取时发生变化时,可能会出现错误 file changed as we read it,导致备份过程失败。在这种情况下,您可以使用名为 copy 的备份策略。该策略在调用 tar 和 gzip 之前将数据文件复制到临时位置,避免了错误。
副作用是备份过程最多需要额外的 1X 磁盘空间。该过程尽最大努力在每个阶段清理临时文件,以防止问题加剧,但对于大型安装来说可能是一个重大变化。
要使用 copy 策略而不是默认流式策略,请在 Rake 任务命令中指定 STRATEGY=copy。例如:
shellsudo gitlab-backup create STRATEGY=copy
备份文件名
如果您使用自定义备份文件名,您无法 限制备份的生命周期。
备份文件根据特定默认值创建文件名。但是,您可以通过设置 BACKUP 环境变量覆盖文件名中的 <backup-id> 部分。例如:
shellsudo gitlab-backup create BACKUP=dump
生成的文件名为 dump_gitlab_backup.tar。这对于使用 rsync 和增量备份的系统非常有用,并导致显著更快的传输速度。
备份压缩
默认情况下,在备份期间对以下进行应用 Gzip 快速压缩:
- PostgreSQL 数据库 转储。
- Blobs,例如上传、作业产物、外部合并请求差异。
默认命令是 gzip -c -1。您可以使用 COMPRESS_CMD 覆盖此命令。类似地,您可以使用 DECOMPRESS_CMD 覆盖解压缩命令。
注意事项:
- 压缩命令在管道中使用,因此您的自定义命令必须输出到 stdout。
- 如果您指定了一个极狐GitLab未打包的命令,那么您必须自行安装它。
- 生成的文件名仍以 .gz 结尾。
- 默认解压缩命令在恢复期间使用的是 gzip -cd。因此,如果您将压缩命令覆盖为使用一种无法通过 gzip -cd 解压缩的格式,您必须在恢复期间覆盖解压缩命令。
- 不要在备份命令后放置环境变量。例如,gitlab-backup create COMPRESS_CMD="pigz -c --best" 无法按预期工作。
默认压缩:使用最快方法的 Gzip
shellgitlab-backup create
使用最慢方法的 Gzip
shellCOMPRESS_CMD="gzip -c --best" gitlab-backup create
如果备份使用了 gzip,则恢复不需要任何选项:
shellgitlab-backup restore
无压缩
如果您的备份目标具有内置自动压缩功能,那么您可能希望跳过压缩。
tee 命令将 stdin 管道到 stdout。
shellCOMPRESS_CMD=tee gitlab-backup create
恢复时:
shellDECOMPRESS_CMD=tee gitlab-backup restore
使用 pigz 的并行压缩
虽然我们支持使用 COMPRESS_CMD 和 DECOMPRESS_CMD 来覆盖默认的 Gzip 压缩库,但我们仅在常规基础上对默认 Gzip 库进行测试。您负责测试和验证备份的可行性。我们强烈建议这作为备份的一般最佳实践,无论是否覆盖压缩命令。如果您在其他压缩库中遇到问题,您应该返回到默认库。使用替代库进行故障排除和修复错误是极狐GitLab的次要任务。
pigz 不包含在极狐GitLab Linux 软件包中。您必须自行安装它。
使用 4 个进程压缩备份的示例:
shellCOMPRESS_CMD="pigz --compress --stdout --fast --processes=4" sudo gitlab-backup create
因为 pigz 压缩到 gzip 格式,因此不需要使用 pigz 解压缩由 pigz 压缩的备份。然而,它仍然可以在性能上优于 gzip。使用 pigz 解压缩备份的示例:
shellDECOMPRESS_CMD="pigz --decompress --stdout" sudo gitlab-backup restore
使用 zstd 的并行压缩
虽然我们支持使用 COMPRESS_CMD 和 DECOMPRESS_CMD 来覆盖默认的 Gzip 压缩库,但我们仅在常规基础上对默认 Gzip 库进行测试。您负责测试和验证备份的可行性。我们强烈建议这作为备份的一般最佳实践,无论是否覆盖压缩命令。如果您在其他压缩库中遇到问题,您应该返回到默认库。使用替代库进行故障排除和修复错误是极狐GitLab的次要任务。
zstd 不包含在极狐GitLab Linux 软件包中。您必须自行安装它。
使用 4 个线程压缩备份的示例:
shellCOMPRESS_CMD="zstd --compress --stdout --fast --threads=4" sudo gitlab-backup create
使用 zstd 解压缩备份的示例:
shellDECOMPRESS_CMD="zstd --decompress --stdout" sudo gitlab-backup restore
确认归档可以传输
为了确保生成的归档可以通过 rsync 传输,您可以设置 GZIP_RSYNCABLE=yes 选项。这会将 --rsyncable 选项设置为 gzip,仅在结合设置备份文件名选项时有用。
gzip中的 --rsyncable选项不保证在所有发行版上可用。要验证它在您的发行版中是否可用,运行 gzip --help 或查阅手册页。
shellsudo gitlab-backup create BACKUP=dump GZIP_RSYNCABLE=yes
从备份中排除特定数据
根据您的安装类型,可以在备份创建时跳过一些不同的组件。
- db(数据库)
- repositories(Git 仓库数据,包括 wikis)
- uploads(附件)
- builds(CI 作业输出日志)
- artifacts(CI 作业产物)
- pages(Pages 内容)
- lfs(LFS 对象)
- terraform_state(Terraform 状态)
- registry(容器注册表图像)
- packages(软件包)
- ci_secure_files(项目级别安全文件)
- external_diffs(外部合并请求差异)
shellsudo gitlab-backup create SKIP=db,uploads
SKIP=也用于:
- 跳过 tar 文件的创建 (SKIP=tar)。
- 跳过上传备份到远程存储 (SKIP=remote)。
跳过 tar 创建
使用对象存储进行备份时无法跳过 tar 创建。
创建备份的最后一个部分是生成包含所有部分的 .tar 文件。在某些情况下,创建 .tar 文件可能是浪费的或甚至直接有害的,因此您可以通过在环境变量中添加 tar 来跳过此步骤。示例用例:
- 当备份被其他备份软件拾取时。
- 通过避免每次都提取备份来加速增量备份(在这种情况下,PREVIOUS_BACKUP 和 BACKUP 必须不指定,否则指定的备份会被提取,但在最后不会生成 .tar 文件)。
在环境变量中添加 tar 会将包含备份的文件和目录保留在用于中间文件的目录中。这些文件在创建新备份时被覆盖,因此您应该确保它们被复制到其他地方,因为您只能在系统上拥有一个备份。
shellsudo gitlab-backup create SKIP=tar
创建服务器端仓库备份
History
- 在极狐GitLab 16.3 中引入了的 gitlab-backup。
- 在极狐GitLab 16.6 中引入了 gitlab-backup 中恢复指定备份而不是最新备份的服务器端支持。
- 在极狐GitLab 16.6 中引入了 gitlab-backup 中创建增量备份的服务器端支持。
- 在极狐GitLab 17.0 中引入了 backup-utility 中的服务器端支持。
仓库备份可以配置为托管每个仓库的 Gitaly 节点负责创建备份并将其流式传输到对象存储,而不是在备份归档中存储大型仓库备份。这有助于减少创建和恢复备份所需的网络资源。
- 在 Gitaly 中配置服务器端备份目标。
- 使用服务器端选项创建备份。请参阅以下示例。
shellsudo gitlab-backup create REPOSITORIES_SERVER_SIDE=true
并发备份 Git 仓库
使用多个仓库存储时,可以并发备份或恢复仓库,以帮助充分利用 CPU 时间。以下变量可用于修改 Rake 任务的默认行为:
- GITLAB_BACKUP_MAX_CONCURRENCY: 同时备份的最大项目数。默认为逻辑 CPU 的数量。
- GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY: 同时备份的最大项目数在每个存储上。这允许将仓库备份分散在多个存储上。默认为 2。
例如,对于 4 个仓库存储:
shellsudo gitlab-backup create GITLAB_BACKUP_MAX_CONCURRENCY=4 GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY=1
增量仓库备份
History
- 在极狐GitLab 14.10 中引入,使用名为 incremental_repository_backup 的功能标志。默认禁用。
- 在极狐GitLab 15.3 中 GA。功能标志 incremental_repository_backup 被删除。
- 在极狐GitLab 16.6 中引入的服务器端支持创建增量备份。
只有仓库支持增量备份。因此,如果您使用 INCREMENTAL=yes,任务会创建一个自包含的备份 tar 归档。这是因为除了仓库之外,所有子任务仍在创建完整备份(它们覆盖现有的完整备份)。
增量仓库备份可能比完整仓库备份更快,因为它们只在每个仓库的备份包中打包自上次备份以来的更改。增量备份归档之间没有链接:每个归档都是实例的自包含备份。必须有一个现有备份来创建增量备份。
使用 PREVIOUS_BACKUP=<backup-id> 选项选择要使用的备份。默认情况下,备份文件根据备份 ID创建。您可以通过设置BACKUP 环境变量覆盖文件名中的 <backup-id> 部分。
要创建增量备份,请运行:
shellsudo gitlab-backup create INCREMENTAL=yes PREVIOUS_BACKUP=<backup-id>
要从 tar 备份创建未打包的增量备份,请使用 SKIP=tar:
shellsudo gitlab-backup create INCREMENTAL=yes SKIP=tar
备份特定仓库存储
History
- 在极狐GitLab 15.0 中引入。
使用多个仓库存储时,可以分别备份特定仓库存储中的仓库,使用 REPOSITORIES_STORAGES 选项。该选项接受以逗号分隔的存储名称列表。
例如:
shellsudo gitlab-backup create REPOSITORIES_STORAGES=storage1,storage2
备份特定仓库
History
- 在极狐GitLab 15.1 中引入。
- 在极狐GitLab 16.1 中添加跳过特定仓库。
您可以使用 REPOSITORIES_PATHS 选项备份特定仓库。类似地,您可以使用 SKIP_REPOSITORIES_PATHS 跳过某些仓库。两个选项都接受以逗号分隔的项目或群组路径列表。如果您指定一个群组路径,则根据您使用的选项,所有项目中的所有仓库在群组和后代群组中都包含或跳过。
例如,要备份 Group A (group-a) 中所有项目的所有仓库,Group B 中 Project C (group-b/project-c) 的仓库,并跳过 Group A 中的 Project D (group-a/project-d):
shellsudo gitlab-backup create REPOSITORIES_PATHS=group-a,group-b/project-c SKIP_REPOSITORIES_PATHS=group-a/project-d
上传备份到远程(云)存储
使用对象存储进行备份时无法跳过 tar 创建。
您可以让备份脚本上传(使用Fog 库)它创建的 .tar 文件。在以下示例中,我们使用 Amazon S3 进行存储,但 Fog 还允许您使用其他存储提供商。极狐GitLab还导入云驱动程序用于 AWS、Google 和 Aliyun。一个本地驱动程序也可用在此。
使用 Amazon S3
对于 Linux 软件包 (Omnibus):
-
在 /etc/gitlab/gitlab.rb 中添加以下内容:
ruby1gitlab_rails['backup_upload_connection'] = { 2 'provider' => 'AWS', 3 'region' => 'eu-west-1', 4 # 选择一种身份验证方法 5 # IAM Profile 6 'use_iam_profile' => true 7 # 或 AWS 访问密钥和密钥 8 'aws_access_key_id' => 'AKIAKIAKI', 9 'aws_secret_access_key' => 'secret123' 10} 11gitlab_rails['backup_upload_remote_directory'] = 'my.s3.bucket' 12# 考虑在文件大小达到 100MB 时使用分段上传。输入一个字节数。 13# gitlab_rails['backup_multipart_chunk_size'] = 104857600
-
如果您使用 IAM Profile 身份验证方法,请确保运行 backup-utility 的实例设置了以下策略(将 <backups-bucket> 替换为正确的桶名称):
json1{ 2 "Version": "2012-10-17", 3 "Statement": [ 4 { 5 "Effect": "Allow", 6 "Action": [ 7 "s3:PutObject", 8 "s3:GetObject", 9 "s3:DeleteObject" 10 ], 11 "Resource": "arn:aws:s3:::<backups-bucket>/*" 12 } 13 ] 14}
-
重新配置极狐GitLab以使更改生效
加密的 S3 桶
AWS 支持这些服务器端加密模式:
- Amazon S3 管理的密钥 (SSE-S3)
- 客户主密钥 (CMKs) 存储在 AWS 密钥管理服务 (SSE-KMS) 中
- 客户提供的密钥 (SSE-C)
使用极狐GitLab选择您的模式。每种模式都有相似但略有不同的配置方法。
SSE-S3
要启用 SSE-S3,在备份存储选项中将 server_side_encryption 字段设置为 AES256。例如,在 Linux 软件包 (Omnibus) 中:
rubygitlab_rails['backup_upload_storage_options'] = { 'server_side_encryption' => 'AES256' }
SSE-KMS
要启用 SSE-KMS,您需要KMS 密钥通过其 Amazon 资源名称 (ARN) 的 arn:aws:kms:region:acct-id:key/key-id 格式。在 backup_upload_storage_options 配置设置下,设置:
- server_side_encryption 为 aws:kms。
- server_side_encryption_kms_key_id 为客户主密钥的 ARN。
例如,在 Linux 软件包 (Omnibus) 中:
rubygitlab_rails['backup_upload_storage_options'] = { 'server_side_encryption' => 'aws:kms', 'server_side_encryption_kms_key_id' => 'arn:aws:<YOUR KMS KEY ID>:' }
SSE-C
SSE-C 要求您设置以下加密选项:
- backup_encryption: AES256。
- backup_encryption_key: 未编码的 32 字节(256 位)密钥。如果这不是正好 32 字节,则上传将失败。
例如,在 Linux 软件包 (Omnibus) 中:
rubygitlab_rails['backup_encryption'] = 'AES256' gitlab_rails['backup_encryption_key'] = '<YOUR 32-BYTE KEY HERE>'
如果密钥包含二进制字符并且无法编码为 UTF-8,请通过 GITLAB_BACKUP_ENCRYPTION_KEY 环境变量指定密钥。例如:
rubygitlab_rails['env'] = { 'GITLAB_BACKUP_ENCRYPTION_KEY' => "\xDE\xAD\xBE\xEF" * 8 }
Digital Ocean Spaces
此示例可用于阿姆斯特丹 (AMS3) 的桶:
-
在 /etc/gitlab/gitlab.rb 中添加以下内容:
ruby1gitlab_rails['backup_upload_connection'] = { 2 'provider' => 'AWS', 3 'region' => 'ams3', 4 'aws_access_key_id' => 'AKIAKIAKI', 5 'aws_secret_access_key' => 'secret123', 6 'endpoint' => 'https://ams3.digitaloceanspaces.com' 7} 8gitlab_rails['backup_upload_remote_directory'] = 'my.s3.bucket'
-
重新配置极狐GitLab以使更改生效
如果使用 Digital Ocean Spaces 时看到 400 Bad Request 错误消息,原因可能是使用了备份加密。由于 Digital Ocean Spaces 不支持加密,请删除或注释包含 gitlab_rails['backup_encryption'] 的行。
其他 S3 提供商
并非所有 S3 提供商都与 Fog 库完全兼容。例如,如果在尝试上传后看到 411 Length Required 错误消息,您可能需要将 aws_signature_version 值从默认值降级到 2。
文件开头包含在 --- 中的内容不用翻译,按照原样输出即可。
私有化部署安装
-
编辑 home/git/gitlab/config/gitlab.yml:
yaml1 backup: 2 # snip 3 upload: 4 # Fog storage connection settings, see https://fog.github.io/storage/ . 5 connection: 6 provider: AWS 7 region: eu-west-1 8 aws_access_key_id: AKIAKIAKI 9 aws_secret_access_key: 'secret123' 10 # If using an IAM Profile, leave aws_access_key_id & aws_secret_access_key empty 11 # ie. aws_access_key_id: '' 12 # use_iam_profile: 'true' 13 # The remote 'directory' to store your backups. For S3, this would be the bucket name. 14 remote_directory: 'my.s3.bucket' 15 # Specifies Amazon S3 storage class to use for backups, this is optional 16 # storage_class: 'STANDARD' 17 # 18 # Turns on AWS Server-Side Encryption with Amazon Customer-Provided Encryption Keys for backups, this is optional 19 # 'encryption' must be set in order for this to have any effect. 20 # 'encryption_key' should be set to the 256-bit encryption key for Amazon S3 to use to encrypt or decrypt. 21 # To avoid storing the key on disk, the key can also be specified via the `GITLAB_BACKUP_ENCRYPTION_KEY` your data. 22 # encryption: 'AES256' 23 # encryption_key: '<key>' 24 # 25 # 26 # Turns on AWS Server-Side Encryption with Amazon S3-Managed keys (optional) 27 # https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html 28 # For SSE-S3, set 'server_side_encryption' to 'AES256'. 29 # For SS3-KMS, set 'server_side_encryption' to 'aws:kms'. Set 30 # 'server_side_encryption_kms_key_id' to the ARN of customer master key. 31 # storage_options: 32 # server_side_encryption: 'aws:kms' 33 # server_side_encryption_kms_key_id: 'arn:aws:kms:YOUR-KEY-ID-HERE'
-
重新启动极狐GitLab以使更改生效
使用 Google 云存储
要使用 Google 云存储保存备份,您首先必须从 Google 控制台创建一个访问密钥:
- 转到 Google 存储设置页面。
- 选择 Interoperability,然后创建一个访问密钥。
- 记下 访问 key 和 密钥,并在以下配置中替换它们。
- 在桶的高级设置中确保选择了访问控制选项 设置对象和桶级别的权限。
- 确保您已经创建了一个桶。
对于 Linux 软件包(Omnibus):
-
编辑 /etc/gitlab/gitlab.rb:
ruby1gitlab_rails['backup_upload_connection'] = { 2 'provider' => 'Google', 3 'google_storage_access_key_id' => 'Access Key', 4 'google_storage_secret_access_key' => 'Secret', 5 6 ## If you have CNAME buckets (foo.example.com), you might run into SSL issues 7 ## when uploading backups ("hostname foo.example.com.storage.googleapis.com 8 ## does not match the server certificate"). In that case, uncomment the following 9 ## setting. See: https://github.com/fog/fog/issues/2834 10 #'path_style' => true 11} 12gitlab_rails['backup_upload_remote_directory'] = 'my.google.bucket'
-
重新配置极狐GitLab以使更改生效
对于私有化部署安装:
-
编辑 home/git/gitlab/config/gitlab.yml:
yaml1 backup: 2 upload: 3 connection: 4 provider: 'Google' 5 google_storage_access_key_id: 'Access Key' 6 google_storage_secret_access_key: 'Secret' 7 remote_directory: 'my.google.bucket'
-
重新启动极狐GitLab以使更改生效
使用 Azure Blob 存储
-
编辑 /etc/gitlab/gitlab.rb:
ruby1gitlab_rails['backup_upload_connection'] = { 2 'provider' => 'AzureRM', 3 'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>', 4 'azure_storage_access_key' => '<AZURE STORAGE ACCESS KEY>', 5 'azure_storage_domain' => 'blob.core.windows.net', # Optional 6} 7gitlab_rails['backup_upload_remote_directory'] = '<AZURE BLOB CONTAINER>'
如果您使用的是 托管身份,请省略 azure_storage_access_key:
ruby1gitlab_rails['object_store']['connection'] = { 2 'provider' => 'AzureRM', 3 'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>', 4 'azure_storage_domain' => '<AZURE STORAGE DOMAIN>' # Optional 5} 6gitlab_rails['backup_upload_remote_directory'] = '<AZURE BLOB CONTAINER>'
-
重新配置极狐GitLab以使更改生效
有关更多详细信息,请参阅 Azure 参数表。
指定备份的自定义目录
此选项仅适用于远程存储。如果您想将备份分组,可以传递 DIRECTORY 环境变量:
shellsudo gitlab-backup create DIRECTORY=daily sudo gitlab-backup create DIRECTORY=weekly
跳过上传备份到远程存储
如果您已配置极狐GitLab在远程存储中上传备份,您可以使用 SKIP=remote 选项跳过将备份上传到远程存储。
shellsudo gitlab-backup create SKIP=remote
上传到本地挂载的共享
您可以使用 Fog Local 存储提供商将备份发送到本地挂载的共享(例如,NFS、CIFS 或 SMB)。
为此,您必须设置以下配置键:
- backup_upload_connection.local_root:备份复制到的挂载目录。
- backup_upload_remote_directory:backup_upload_connection.local_root 目录的子目录。如果不存在,则会创建它。如果您想将 tar 包复制到挂载目录的根目录,请使用 .。
挂载时,local_root 键中设置的目录必须由以下之一拥有:
- git 用户。因此,对于 CIFS 和 SMB,使用 git 用户的 uid= 挂载。
- 执行备份任务的用户。对于 Linux 软件包(Omnibus),这就是 git 用户。
由于文件系统性能可能会影响整体极狐GitLab性能,我们不推荐使用基于云的文件系统进行存储。
避免冲突的配置
不要将以下配置键设置为相同路径:
- gitlab_rails['backup_path'](私有化部署安装的 backup.path)。
- gitlab_rails['backup_upload_connection'].local_root(私有化部署安装的 backup.upload.connection.local_root)。
backup_path 配置键设置备份文件的本地位置。upload 配置键用于备份文件上传到单独的服务器时,可能用于归档目的。
如果这些配置键设置为相同位置,则上传功能将失败,因为上传位置已经存在备份。这种失败会导致上传功能删除备份,因为它假设这是上传失败后剩余的文件。
配置上传到本地挂载的共享
-
编辑 /etc/gitlab/gitlab.rb:
ruby1gitlab_rails['backup_upload_connection'] = { 2 :provider => 'Local', 3 :local_root => '/mnt/backups' 4} 5 6# The directory inside the mounted folder to copy backups to 7# Use '.' to store them in the root directory 8gitlab_rails['backup_upload_remote_directory'] = 'gitlab_backups'
-
重新配置极狐GitLab以使更改生效。
备份档案权限
极狐GitLab 创建的备份档案(1393513186_2014_02_27_gitlab_backup.tar)默认具有所有者/组 git/git 和 0600 权限。这是为了避免其他系统用户读取极狐GitLab 数据。如果您需要备份档案具有不同的权限,可以使用 archive_permissions 设置。
-
编辑 /etc/gitlab/gitlab.rb:
rubygitlab_rails['backup_archive_permissions'] = 0644 # Makes the backup archives world-readable
-
重新配置极狐GitLab以使更改生效。
配置 cron 进行每日备份
以下 cron 作业不会备份您的极狐GitLab 配置文件或SSH 主机密钥。
您可以安排一个 cron 作业来备份您的存储库和极狐GitLab 元数据。
-
编辑 root 用户的 crontab:
shellsudo su - crontab -e
-
在其中添加以下行,以便每天凌晨 2 点安排备份:
plaintext0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1
CRON=1 环境设置指示备份脚本在没有错误时隐藏所有进度输出。建议减少 cron 垃圾邮件。然而,当排查备份问题时,请将 CRON=1 替换为 --trace 以详细记录。
限制本地文件的备份生命周期(清除旧备份)
如果您使用了备份的自定义文件名,则本节中描述的过程不起作用。
为了防止定期备份占用所有磁盘空间,您可能希望设置备份的有限生命周期。备份任务下次运行时,旧于 backup_keep_time 的备份将被清除。
此配置选项仅管理本地文件。极狐GitLab 不会清除存储在第三方对象存储中的旧文件,因为用户可能没有列出和删除文件的权限。建议您为对象存储配置适当的保留策略(例如,AWS S3)。
-
编辑 /etc/gitlab/gitlab.rb:
ruby## Limit backup lifetime to 7 days - 604800 seconds gitlab_rails['backup_keep_time'] = 604800
-
重新配置极狐GitLab以使更改生效。
使用 PgBouncer 安装的备份和恢复
不要通过 PgBouncer 连接备份或恢复极狐GitLab。这些任务必须绕过 PgBouncer 并直接连接到 PostgreSQL 主数据库节点,否则会导致极狐GitLab 中断。
当极狐GitLab 备份或恢复任务与 PgBouncer 一起使用时,会显示以下错误消息:
rubyActiveRecord::StatementInvalid: PG::UndefinedTable
每次极狐GitLab 备份运行时,极狐GitLab 开始生成 500 错误,并且缺少表的错误将由 PostgreSQL 记录:
plaintextERROR: relation "tablename" does not exist at character 123
发生这种情况是因为任务使用 pg_dump,它设置空搜索路径并在每个 SQL 查询中显式包含模式以解决CVE-2018-1058。
由于在事务池模式下使用 PgBouncer 时连接被重用,PostgreSQL 无法搜索默认的 public 模式。因此,清除搜索路径导致表和列似乎丢失。
绕过 PgBouncer
有两种方法可以解决这个问题:
- 对备份任务使用环境变量覆盖数据库设置。
- 重新配置一个节点以直接连接到 PostgreSQL 主数据库节点。
环境变量覆盖
History
- 多个数据库支持在极狐GitLab 16.5 中引入。
默认情况下,极狐GitLab 使用存储在配置文件(database.yml)中的数据库配置。但是,您可以通过设置以 GITLAB_BACKUP_ 为前缀的环境变量来覆盖备份和恢复任务的数据库设置:
- GITLAB_BACKUP_PGHOST
- GITLAB_BACKUP_PGUSER
- GITLAB_BACKUP_PGPORT
- GITLAB_BACKUP_PGPASSWORD
- GITLAB_BACKUP_PGSSLMODE
- GITLAB_BACKUP_PGSSLKEY
- GITLAB_BACKUP_PGSSLCERT
- GITLAB_BACKUP_PGSSLROOTCERT
- GITLAB_BACKUP_PGSSLCRL
- GITLAB_BACKUP_PGSSLCOMPRESSION
例如,要覆盖数据库主机和端口以使用 192.168.1.10 和 5432 端口,并使用 Linux 软件包(Omnibus):
shellsudo GITLAB_BACKUP_PGHOST=192.168.1.10 GITLAB_BACKUP_PGPORT=5432 /opt/gitlab/bin/gitlab-backup create
如果您在多个数据库上运行极狐GitLab,可以通过在环境变量中包含数据库名称来覆盖数据库设置。例如,如果您的 main 和 ci 数据库托管在不同的数据库服务器上,您可以在 GITLAB_BACKUP_ 前缀后附加它们的名称,保持 PG* 名称不变:
shellsudo GITLAB_BACKUP_MAIN_PGHOST=192.168.1.10 GITLAB_BACKUP_CI_PGHOST=192.168.1.12 /opt/gitlab/bin/gitlab-backup create
gitaly-backup 用于存储库备份和恢复
备份 Rake 任务使用 gitaly-backup 二进制文件从 Gitaly 创建和恢复存储库备份。gitaly-backup 替换了以前直接从极狐GitLab 调用 Gitaly 的 RPC 的备份方法。
备份 Rake 任务必须能够找到这个可执行文件。在大多数情况下,您不需要更改二进制文件的路径,因为默认路径 /opt/gitlab/embedded/bin/gitaly-backup 应该可以正常工作。如果您有特定的原因要更改路径,可以在 Linux 软件包(Omnibus)中进行配置:
-
将以下内容添加到 /etc/gitlab/gitlab.rb:
rubygitlab_rails['backup_gitaly_backup_path'] = '/path/to/gitaly-backup'
-
重新配置极狐GitLab以使更改生效。
备用备份策略
由于每个部署可能具有不同的能力,您应首先查看需要备份的数据,以更好地理解是否以及如何利用它们。
例如,如果您使用 Amazon RDS,您可能选择使用其内置备份和恢复功能来处理您的极狐GitLab PostgreSQL 数据,并在使用备份命令时排除 PostgreSQL 数据。
在以下情况下,请考虑使用文件系统数据传输或快照作为您的备份策略的一部分:
- 您的极狐GitLab 实例包含大量 Git 存储库数据,而极狐GitLab 备份脚本太慢。
- 您的极狐GitLab 实例有很多分叉项目,常规备份任务会为所有这些项目复制 Git 数据。
- 您的极狐GitLab 实例存在问题,无法使用常规备份和导入 Rake 任务。
Gitaly Cluster 不支持快照备份。
在考虑使用文件系统数据传输或快照时:
- 不要使用这些方法从一个操作系统迁移到另一个操作系统。源和目标的操作系统应尽可能相似。例如,不要使用这些方法从 Ubuntu 迁移到 RHEL。
- 数据一致性非常重要。在进行文件系统传输(例如,使用 rsync)或拍摄快照之前,您应该停止极狐GitLab(sudo gitlab-ctl stop),以确保所有内存中的数据都已刷新到磁盘。极狐GitLab 由多个子系统组成(Gitaly、数据库、文件存储),每个子系统都有自己的缓冲区、队列和存储层。极狐GitLab 事务可以跨越这些子系统,这导致事务的一部分通过不同路径写入磁盘。在活动系统上,文件系统传输和快照运行无法捕获仍在内存中的事务部分。
示例:Amazon Elastic Block Store (EBS)
- 使用 Linux 软件包(Omnibus)托管在 Amazon AWS 上的极狐GitLab 服务器。
- 一个包含 ext4 文件系统的 EBS 驱动器挂载在 /var/opt/gitlab。
- 在这种情况下,您可以通过拍摄 EBS 快照来进行应用程序备份。
- 备份包括所有存储库、上传和 PostgreSQL 数据。
示例:逻辑卷管理器(LVM)快照 + rsync
- 使用 Linux 软件包(Omnibus)的极狐GitLab 服务器,其中一个 LVM 逻辑卷挂载在 /var/opt/gitlab。
- 使用 rsync 复制 /var/opt/gitlab 目录不可靠,因为在 rsync 运行期间会有太多文件发生更改。
- 而不是 rsync-ing /var/opt/gitlab,我们创建一个临时 LVM 快照,将其作为只读文件系统挂载在 /mnt/gitlab_backup。
- 现在我们可以进行较长时间的 rsync 作业,以在远程服务器上创建一致的副本。
- 副本包括所有存储库、上传和 PostgreSQL 数据。
如果您在虚拟化服务器上运行极狐GitLab,您也可以创建整个极狐GitLab 服务器的 VM 快照。然而,VM 快照通常需要关闭服务器,这限制了该解决方案的实际使用。
单独备份存储库数据
首先,确保备份现有极狐GitLab 数据,同时跳过存储库:
shellsudo gitlab-backup create SKIP=repositories
对于磁盘上的 Git 存储库数据手动备份,有多种可能的策略:
- 使用快照,例如前面的 Amazon EBS 驱动器快照或 LVM 快照 + rsync 示例。
- 使用 极狐GitLab Geo 并依赖 Geo 辅助站点上的存储库数据。
- 防止写入并复制 Git 存储库数据。
- 通过将存储库标记为只读来创建在线备份(实验性)。
防止写入并复制 Git 存储库数据
必须以一致的方式复制 Git 存储库。它们不应在并发写入操作期间复制,因为这可能导致不一致或损坏问题。
为了防止写入 Git 存储库数据,有两种可能的方法:
-
使用维护模式将极狐GitLab置于只读状态。
-
在备份存储库之前停止所有 Gitaly 服务以创建明确的停机时间:
shellsudo gitlab-ctl stop gitaly # execute git data copy step sudo gitlab-ctl start gitaly
您可以使用任何方法复制 Git 存储库数据,只要防止对正在复制的数据进行写入(以防止不一致和损坏问题)。按照优先级和安全性顺序,推荐的方法是:
-
使用带有归档模式、删除和校验选项的 rsync,例如:
shellrsync -aR --delete --checksum source destination # be extra safe with the order as it will delete existing data if inverted
-
使用 sftp、scp、cp 或任何其他复制方法。
通过将存储库标记为只读来创建在线备份(实验性)
备份存储库而不需要实例范围的停机的一种方法是通过复制底层数据来编程地将项目标记为只读。
这有一些可能的缺点:
- 存储库在一段时间内是只读的,这个时间随着存储库的大小而变化。
- 由于标记每个项目为只读,备份需要更长的时间来完成,可能导致不一致。例如,备份的第一个项目与备份的最后一个项目之间的最后数据可用日期差异。
- Fork 网络应该在其中的项目被备份时完全只读,以防止对池存储库的潜在更改。