在2023年4月24日,我收到了GitLab的升级通知,于是开始了升级操作,然而,这次例行升级引发了一个严重的问题,导致GitLab数据库丢失。这篇文章将记录我是如何修复GitLab的,同时也会提及一些我在这个过程中犯下的错误。虽然中途有一些操作没有及时记录截图,但我会尽量用备份的一些场景来还原过程。
基本情况
- 当前版本:GitLab-CE 15.9.5
- 升级版本:GitLab-CE 15.11.0
- 操作系统:Linux Debian 10
- 硬件配置:2核8GB内存50GB硬盘
- 500+仓库和13个GitLab Runner用于执行任务
问题出现
一切都开始于一次升级操作,我执行了升级命令,但不幸的是,一旦升级完成,问题就接踵而至。这是我犯下的第一个错误,没有在升级前对虚拟机进行快照备份,而是直接升级了内部应用。以前的升级都没有问题,因此我没有太多的警觉性。此外,由于我使用Docker部署GitLab已经有5年之久,每次更新都是按照相同的步骤进行,所以我没有过多地考虑到备份的必要性。以下是我执行的命令:
docker rm -f docker && docker pull gitlab/gitlab-ce:latest && docker run -it --log-opt max-size=10m --log-opt max-file=3 -p 443:443 --name gitlab --restart always -v /root/gitlab/config:/etc/gitlab -v /root/gitlab/logs:/var/log/gitlab -v /root/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce:latest
第一次报错
然而,升级命令执行后,我遇到了第一个错误,错误信息如下:
SELECT COUNT(*) FROM container_repositories WHERE migration_state = 'import_skipped'
ERROR: column "migration_state" does not exist at character 51
错误信息明确指出了解决方法,它建议我添加一个参数 -e GITLAB_SKIP_UNMIGRATED_DATA_CHECK=true
来重新启动实例,以绕过升级检查。于是我添加了这个参数,重新启动了GitLab实例。
第二次报错
然而,第二次启动后,又出现了问题,错误信息如下:
Starting the database
Error starting the database. Please fix the error before continuing
Expected process to exit with [0], but received '1'
这次的错误是关于数据库启动的问题,GitLab试图升级PostgreSQL版本,但出现了问题。它提供了另一个解决方案,要求我添加 -e GITLAB_SKIP_PG_UPGRADE=true
参数来跳过数据库升级。于是我使用了GitLab之前的版本 gitlab/gitlab-ce:15.9.5-ce.0
来重新启动。
第三次报错
第三次启动后,我遇到了文件权限的问题,错误信息如下:
failed to read meta.json for a block during repair process; skipping" dir=/var/opt/gitlab/prometheus/data/01GYSNK1JKD2X5125MP0ZRPKFH err="open /var/opt/gitlab/prometheus/data/01GYSNK1JKD2X5125MP0ZRPKFH/meta.json: permission denied"
通过分析日志,我发现只是一个权限问题,于是我毫不犹豫地将相关目录的权限设置为777:
chmod -R 777 /root/gitlab/config
chmod -R 777 /root/gitlab/logs
chmod -R 777 /root/gitlab/data
然后进行了第三次重启。
第四次报错
第四次启动后,我遇到了与邮件
通知相关的错误,错误信息如下:
Could not determine email for job (please check DB for incomplete objects)
这个错误并没有提供直接的解决方案,但它暗示了可能存在数据库问题。在这一点上,我开始感到紧张,因为我没有数据库备份。但我决定尝试一个解决方案,我执行了以下命令:
sudo gitlab-rake gitlab:db:bootstrap
这个命令似乎修复了一些数据库问题,然后我进行了第四次重启。
第五次报错
第五次启动后,终于没有再次报错,GitLab看起来正常运行了。我尝试登录,并确保所有存储库和项目都存在。但是,当我尝试访问一个项目时,我遇到了一个新的问题,即无法获取存储库的内容,错误信息如下:
The repository could not be found.
这个问题让我感到非常焦虑,因为我拥有的存储库非常重要。我开始寻找解决方法,但在这个过程中,我再次犯了一个错误,没有停止GitLab容器,而是继续尝试解决问题。这导致了我在一次数据恢复尝试中误删除了存储库数据。
数据恢复
在数据丢失之后,我感到非常沮丧,但我没有放弃。我开始尝试从GitLab备份文件中恢复数据。幸运的是,我之前有一个定期备份GitLab数据的任务,这些备份文件位于 /root/gitlab/backups
目录下。我决定尝试从这些备份中恢复数据。
恢复备份
首先,我列出了可用的备份文件,使用以下命令:
ls /root/gitlab/backups
然后,我选择了最近的一个备份文件,执行了以下命令来恢复数据:
docker exec -t gitlab gitlab-backup restore BACKUP=xxx
在这里,xxx
是我选择的备份文件名。恢复过程可能需要一些时间,因为它涉及到将数据从备份文件还原到数据库中。
恢复存储库
一旦数据恢复完成,我还需要恢复存储库的数据。由于我之前误删了存储库数据,我只能尝试从GitLab Runner的备份中恢复存储库。这是我犯下的又一个错误,因为我应该在执行任何操作之前停止GitLab容器以防止进一步的数据丢失。
我列出了GitLab Runner的备份文件,使用以下命令:
ls /root/gitlab/data/gitlab-runner/data
然后,我选择了最近的一个备份文件,执行了以下命令来恢复数据:
docker run --rm -v /root/gitlab/data/gitlab-runner/data:/data ubuntu cp -R /backup /data
这将备份文件从Runner容器复制到了宿主机的Runner数据目录中。
修复存储库
然而,这还不够,因为存储库数据仍然无法访问。我需要执行以下命令来修复存储库数据:
docker exec -t gitlab gitlab-rake gitlab:storage:rollback ORIG_STORAGE=/var/opt/gitlab/git-data/backups/
这个命令将存储库数据从备份中还原到正确的位置。
结论
经过多次尝试和一些错误,我终于成功地修复了GitLab数据库丢失的问题,并且成功恢复了存储库数据。这次经历教训深刻,我意识到了数据备份的重要性,以及在遇到问题时要及时停止容器以防止进一步的损失。同时,我也学到了如何从GitLab备份中恢复数据,以及如何修复存储库数据。希望这篇文章对其他遇到类似问题的人有所帮助。
下一步计划
在修复了GitLab的问题后,我计划进一步改进我的GitLab部署策略,确保数据的安全性和可恢复性。我还会继续学习并提升自己的技术能力,以更好地应对类似问题。同时,我也会分享这次经历和教训,希望能够帮助其他人避免类似的困境。