GitLab 官方备份与恢复
此解决方案基于 GitLab 官方的备份与恢复方案。有关详细信息,请参阅 GitLab 官方文档。
适用范围
此解决方案仅适用于运行 17.8 或更高版本且已配置对象存储的 GitLab 实例。
如果您的 GitLab 实例尚未配置对象存储,GitLab 提供了数据迁移方案。您可以先参考此方案迁移数据,然后使用此方案进行备份和恢复。
如何检查是否已配置对象存储
export GITLAB_NAMESPACE=<namespace of the GitLab instance to be backed up>
export GITLAB_NAME=<name of the GitLab instance to be backed up>
kubectl get gitlabofficial ${GITLAB_NAME} -n ${GITLAB_NAMESPACE} -o jsonpath='{.spec.helmValues.global.appConfig.object_store}'
# Output:
# {"connection":{"key":"connection","secret":"gitlab-rails-storage"},"enabled":true}
如果 enabled 字段为 true,且 connection 字段不为空,则表示该实例已配置对象存储。
术语
前提条件
- 部署 MinIO 对象存储:官方备份与恢复方案依赖对象存储来保存备份数据,因此需要预先部署 MinIO 实例。ACP 提供
MinIO Object Storage,用于快速创建 MinIO 实例。
- 安装 mc 命令行工具:mc 是 MinIO 用于管理 MinIO 实例的命令行工具。有关安装说明,请参阅 MinIO 官方文档。
- 安装 kubectl 命令行工具:kubectl 是 Kubernetes 用于管理 Kubernetes 集群的命令行工具。有关安装说明,请参阅 Kubernetes 官方文档。
为便于后续操作,请先设置环境变量:
export MINIO_HOST=<MinIO instance access address> # Example: http://192.168.1.100:32008
export MINIO_ACCESS_KEY=<MinIO instance access key> # Example: minioadmin
export MINIO_SECRET_KEY=<MinIO instance secret key> # Example: minioadminpassword
export MINIO_ALIAS_NAME=<MinIO instance alias name> # Example: myminio
export GITLAB_NAMESPACE=<namespace of the GitLab instance to be backed up>
export GITLAB_NAME=<name of the GitLab instance to be backed up>
执行以下命令配置 mc 命令行工具并测试连接:
mc alias set ${MINIO_ALIAS_NAME} ${MINIO_HOST} ${MINIO_ACCESS_KEY} ${MINIO_SECRET_KEY}
mc ping ${MINIO_ALIAS_NAME}
# Output:
# 1: http://192.168.131.56:32571:32571 min=98.86ms max=98.86ms average=98.86ms errors=0 roundtrip=98.86ms
# 2: http://192.168.131.56:32571:32571 min=29.57ms max=98.86ms average=64.21ms errors=0 roundtrip=29.57ms
# 3: http://192.168.131.56:32571:32571 min=29.57ms max=98.86ms average=52.77ms errors=0 roundtrip=29.88ms
如果能够成功 ping 通 MinIO 实例,则表示 mc 配置正确。
备份
前提条件
创建存储桶
您需要创建两个存储桶:
- 用于存储备份数据的存储桶,名称为:
gitlab-backups
- 用于在备份期间存储临时数据的存储桶,名称为:
gitlab-backups-tmp
执行以下命令创建存储桶:
mc mb ${MINIO_ALIAS_NAME}/gitlab-backups
mc mb ${MINIO_ALIAS_NAME}/gitlab-backups-tmp
# Output:
# Bucket created successfully `myminio/gitlab-backups`.
# Bucket created successfully `myminio/gitlab-backups-tmp`.
执行以下命令,验证存储桶是否创建成功:
mc ls ${MINIO_ALIAS_NAME} | grep gitlab-backups
# Output:
# [2025-06-30 11:58:09 CST] 0B gitlab-backups/
# [2025-06-30 11:58:13 CST] 0B gitlab-backups-tmp/
手动备份
要执行 GitLab 官方备份,您必须在 toolbox pod 中运行备份命令。在此过程中,备份文件将上传到对象存储。因此,您需要提前准备对象存储配置文件。运行以下脚本生成所需的配置文件:
set -e
if [[ -z "${GITLAB_NAMESPACE}" ]]; then
echo "GITLAB_NAMESPACE is not set, please set it and try again"
exit 1
fi
CLEAN_HOST=${MINIO_HOST#http://}
CLEAN_HOST=${CLEAN_HOST#https://}
use_https="False"
if [[ $MINIO_HOST == https://* ]]; then
use_https="True"
fi
CONFIG_DATA=$(cat << EOF
[default]
host_base = ${CLEAN_HOST}
host_bucket = ${CLEAN_HOST}/%(bucket)
access_key = ${MINIO_ACCESS_KEY}
secret_key = ${MINIO_SECRET_KEY}
bucket_location = us-east-1
use_https = ${use_https}
EOF
)
kubectl create secret generic s3cfg \
-n ${GITLAB_NAMESPACE} \
--from-literal=config="$CONFIG_DATA"
# Output:
# secret/s3cfg created
在 GitLab 所在的集群中执行以下命令,编辑 GitLab 实例 CR:
kubectl edit gitlabofficial ${GITLAB_NAME} -n ${GITLAB_NAMESPACE}
请先根据注释编辑以下 yaml 配置,然后将其添加到 CR 中:
spec:
helmValues:
global:
appConfig:
backups:
# These two bucket names must match the bucket names created in previous steps
bucket: gitlab-backups
tmpBucket: gitlab-backups-tmp
gitlab:
toolbox:
backups:
objectStorage:
config:
key: config
# Name of the secret created in the previous step
secret: s3cfg
enabled: true
persistence:
accessMode: ReadWriteMany
enabled: true
# Backup requires packaging all files locally, so sufficient space is needed
# Determine PVC capacity based on instance's used disk space
size: 10Gi
# Storage class name
storageClass: nfs
更新 GitLab CR 后,系统将自动部署新的 Toolbox 组件。使用以下命令检查 Toolbox 组件是否部署成功:
kubectl get pod -n ${GITLAB_NAMESPACE} | grep toolbox
# Output:
# xx-gitlab-toolbox-6f578f6b-f7wlw 1/1 Running 0 4h11m
如果 pod 状态为 Running,则表示 Toolbox 组件已成功部署。
执行备份
使用以下命令进入 Toolbox pod 的终端环境:
export TOOLBOX_POD_NAME=$(kubectl get pod -n ${GITLAB_NAMESPACE} | grep ${GITLAB_NAME}-toolbox | awk '{print $1}')
kubectl exec -it ${TOOLBOX_POD_NAME} -n ${GITLAB_NAMESPACE} -- bash
执行备份:
cd ~/; nohup backup-utility > output.log 2>&1 &
备份过程需要一些时间,请使用以下命令查看备份日志,以确认备份进度:
cd ~/; tail -f output.log
# Output:
# Bucket not found: gitlab-packages. Skipping backup of packages ...
# Bucket not found: gitlab-mr-diffs. Skipping backup of external_diffs ...
# Bucket not found: gitlab-terraform-state. Skipping backup of terraform_state ...
# Bucket not found: gitlab-pages. Skipping backup of pages ...
# Bucket not found: gitlab-ci-secure-files. Skipping backup of ci_secure_files ...
# Packing up backup tar
# WARNING: Module python-magic is not available. Guessing MIME types based on file extensions.
# [DONE] Backup can be found at s3://gitlab-backups/1751272314_2025_06_30_17.11.4_gitlab_backup.tar
程序成功完成后,备份过程结束。
备份 ID
备份文件名根据备份时间和版本信息动态生成,例如 1751272314_2025_06_30_17.11.4_gitlab_backup.tar。1751272314_2025_06_30_17.11.4 是此备份的唯一标识符(备份 ID)。执行恢复操作时,您需要提供相应的备份 ID。
计划备份
GitLab 计划备份通过 Toolbox 组件完成。与手动备份不同,计划备份使用 Crontab 实现定期备份。
在 GitLab 所在的集群中执行以下命令,编辑 GitLab 实例 CR:
kubectl edit gitlabofficial ${GITLAB_NAME} -n ${GITLAB_NAMESPACE}
请先根据注释编辑以下 yaml 配置,然后将其添加到 CR 中:
spec:
helmValues:
global:
appConfig:
backups:
# These two bucket names must match the bucket names created in previous steps
bucket: gitlab-backups
tmpBucket: gitlab-backups-tmp
gitlab:
toolbox:
enabled: true
backups:
cron:
enabled: true
# Configure backup cycle
schedule: "0 1 * * *"
persistence:
enabled: true
accessMode: ReadWriteMany
# Backup requires packaging all files in the toolbox pod, so sufficient space is needed
# Determine PVC capacity based on instance's used disk space
size: 10Gi
# Storage class name
storageClass: nfs
objectStorage:
config:
key: config
# Name of the secret created in the previous step
secret: s3cfg
如何配置备份周期
Crontab 规则由五个时间字段组成,各字段之间以空格分隔,从左到右依次为:
- 分钟(Minute):指定在每小时的第几分钟执行任务,范围为 0-59
- 小时(Hour):指定在每天的第几个小时执行任务,范围为 0-23
- 月中的日期(Day of the month):指定在每月的第几天执行任务,范围为 1-31
- 月份(Month):指定在每年的哪个月份执行任务,范围为 1-12(也可以使用月份的缩写名称,例如 Jan、Feb、Mar 等)
- 星期(Day of the week):指定在每周的哪一天执行任务,范围为 0-7(0 和 7 均表示星期日,1 表示星期一,以此类推。也可以使用星期的缩写名称,例如 Sun、Mon、Tue 等)
示例:
- 每天凌晨 3:00
执行:
0 3 * * *
- 每月 1 日和 15 日凌晨 3:00
执行:
0 3 1,15 * *
- 每 10 分钟执行一次:
*/10 * * * *
等待 GitLab 触发备份,然后您可以验证备份文件。
验证备份文件
执行以下命令,检查备份文件是否已上传到对象存储:
mc ls ${MINIO_ALIAS_NAME}/gitlab-backups
# Output:
# [2025-06-30 16:33:18 CST] 570KiB STANDARD 1751272314_2025_06_30_17.8.5_gitlab_backup.tar
# [2025-06-30 18:19:26 CST] 570KiB STANDARD 1751278684_2025_06_30_17.8.5_gitlab_backup.tar
如果能够成功列出备份文件,则表示备份成功。
恢复
前提条件
选择要恢复的备份
使用 mc 命令获取备份文件列表:
mc ls ${MINIO_ALIAS_NAME}/gitlab-backups
# Output:
# [2025-06-30 16:33:18 CST] 570KiB STANDARD 1751272314_2025_06_30_17.8.5_gitlab_backup.tar
# [2025-06-30 18:19:26 CST] 570KiB STANDARD 1751278684_2025_06_30_17.8.5_gitlab_backup.tar
根据备份文件名中的日期信息,选择要恢复的备份,并从备份文件名中复制备份 ID 以供后续使用,例如 1751272314_2025_06_30_17.11.4。
确定 GitLab 实例恢复方式
恢复有两种选择:
- 直接在源实例上恢复,这将使用备份数据覆盖实例数据
- (推荐)部署新实例以恢复数据,新实例需要满足以下要求:
- 新实例必须启用对象存储
- 新实例应部署 toolbox 组件,并配置与源实例相同的对象存储配置
恢复操作
请先设置以下环境变量:
export NEW_GITLAB_NAMESPACE=<namespace of the new GitLab instance>
export NEW_GITLAB_NAME=<name of the new GitLab instance>
停止工作负载
为确保恢复操作顺利进行,您需要在恢复期间停止 sidekiq 和 webservice 组件。
kubectl annotate deployment -n ${NEW_GITLAB_NAMESPACE} -l release=${NEW_GITLAB_NAME},app=sidekiq skip-sync="true"
kubectl scale deployment -n ${NEW_GITLAB_NAMESPACE} -l release=${NEW_GITLAB_NAME},app=sidekiq --replicas=0
kubectl annotate deployment -n ${NEW_GITLAB_NAMESPACE} -l release=${NEW_GITLAB_NAME},app=webservice skip-sync="true"
kubectl scale deployment -n ${NEW_GITLAB_NAMESPACE} -l release=${NEW_GITLAB_NAME},app=webservice --replicas=0
# Output:
# deployment.apps/xx-gitlab-sidekiq-all-in-1-v2 annotated
# deployment.apps/xx-gitlab-sidekiq-all-in-1-v2 scaled
# deployment.apps/xx-gitlab-webservice-default annotated
# deployment.apps/xx-gitlab-webservice-default scaled
执行恢复
使用以下命令进入 toolbox pod 的终端:
export NEW_TOOLBOX_POD_NAME=$(kubectl get pod -n ${NEW_GITLAB_NAMESPACE} | grep ${NEW_GITLAB_NAME}-toolbox | awk '{print $1}')
kubectl exec -it ${NEW_TOOLBOX_POD_NAME} -n ${NEW_GITLAB_NAMESPACE} -- bash
DANGER
恢复数据库前,将删除所有现有表,以避免后续升级问题。请注意,如果 GitLab 数据库中存在自定义表,这些表及其所有数据都将被删除。
在终端中执行以下命令以进行恢复,其中需要将备份 ID替换为所需的备份 ID,例如 1751272314_2025_06_30_17.11.4:
export BACKUP_ID=<backup ID>
rm -rf /srv/gitlab/tmp/*
backup-utility --restore -t ${BACKUP_ID}
# Output:
# 2025-06-30 15:33:53 UTC -- [DONE]
# 2025-06-30 15:33:53 UTC -- Source backup for the database ci doesn't exist. Skipping the task
# 2025-06-30 15:33:53 UTC -- Restoring database ... done
# 2025-06-30 15:33:53 UTC -- Deleting backup and restore PID file at [/srv/gitlab/tmp/backup_restore.pid] ... done
# 2025-06-30 15:34:12 UTC -- Restoring repositories ...
# 2025-06-30 15:34:12 UTC -- Restoring repositories ... done
# 2025-06-30 15:34:12 UTC -- Deleting backup and restore PID file at [/srv/gitlab/tmp/backup_restore.pid] ... done
程序成功完成后,恢复过程即结束。
从新实例恢复的注意事项
如果是在新部署的实例中进行恢复,完成上述步骤后,还需要执行以下额外步骤:
恢复 Rails Secrets
您需要更新新实例的 Rails Secrets,使其与源实例的 Rails Secrets 一致。
从源实例获取 Rails Secrets 内容:
kubectl get secret ${GITLAB_NAME}-rails-secret -n ${GITLAB_NAMESPACE} -o jsonpath='{.data.secrets\.yml}' | base64 --decode
更新新实例的 Rails Secrets。请参阅如何设置 Rails Secrets。
切换域名
如果源实例使用域名部署,则从新实例恢复后,需要将新实例的域名切换为源实例的域名,以恢复业务访问。请参阅配置实例网络访问以修改实例访问域名。
恢复工作负载
恢复期间已停止 sidekiq 和 webservice 组件,恢复完成后需要重新启动。
kubectl annotate deployment -n ${NEW_GITLAB_NAMESPACE} -l release=${NEW_GITLAB_NAME},app=sidekiq skip-sync-
kubectl scale deployment -n ${NEW_GITLAB_NAMESPACE} -l release=${NEW_GITLAB_NAME},app=sidekiq --replicas=1
kubectl annotate deployment -n ${NEW_GITLAB_NAMESPACE} -l release=${NEW_GITLAB_NAME},app=webservice skip-sync-
kubectl scale deployment -n ${NEW_GITLAB_NAMESPACE} -l release=${NEW_GITLAB_NAME},app=webservice --replicas=1
# Output:
# deployment.apps/xx-gitlab-sidekiq-all-in-1-v2 annotated
# deployment.apps/xx-gitlab-sidekiq-all-in-1-v2 scaled
# deployment.apps/xx-gitlab-webservice-default annotated
# deployment.apps/xx-gitlab-webservice-default scaled
验证恢复
等待实例状态恢复正常后,登录 GitLab 以检查数据是否已成功恢复。检查项包括但不限于:
GitLab 是 GitLab Inc. 的商标。
Alauda 是独立供应商。本产品与 GitLab Inc. 无关联,也未获得其认可或赞助。所有商标均为其各自所有者的财产,此处仅用于标识目的。