任务
接到任务,公司的gitlab服务器要做迁移。gitlab服务器原先部署在一台虚拟服务器上(服务器A),采用Docker方式部署。由于宿主机磁盘无法扩展了,几次出现磁盘用满的情况,每次都是删除gitlab日志文件才能坚持一段时间。这次领导决定gitlab服务器迁移到另一台服务器上(服务器B)。
思路
之前的gitlab容器的镜像是经过修改的,负责之前gitlab服务部署的人已经离职很久了,改了哪里没人知道。为了避免麻烦,还是基于修改过的镜像来部署新的gitlab容器比较稳妥。
所以我的思路是:
-
基于现有镜像迁移。从之前的服务器A上把修改过的gitlab镜像导出、拷贝、导入到目标服务器B的docker中;
-
拷贝服务器A现有gitlab服务的配置文件(目录)和数据文件(目录)到目标服务器B。
-
基于原镜像和配置及数据文件启动gitlab容器。
这个方案会有坑,一般是文件和目录权限问题,但好在已经有前人替我们踩过了。说干就干,开始验证。
迁移gitlab镜像
简单讲就是导出现有镜像 --> 复制到目标服务器上 --> 在目标服务器的docker中导入镜像。
这里提一下,Docker导出/导入镜像的方式有两种:
-
export/import
-
save/load
两种方式的差别是:
-
save/load 操作的是镜像(image),docker save 用来将一个或多个镜像保存到文件,然后拷贝到目标服务器上使用 docker load 载入;export/import 操作的是容器(container)。docker export 主要用于基于容器来制作镜像,比如基于一个基础镜像启动一个容器,然后安装一些软件、进行一些设置后,使用 docker export 保存为一个镜像。然后,把这个镜像分发出去;
-
docker import 可以为镜像指定新名称,docker load 不能对载入的镜像重命名;
-
docker export 不支持将多个镜像打包到一个文件中,docker save 支持将多个镜像打包到一个文件中;
这里采用 save/load 方式做镜像的迁移。
-
在服务器A的docker上导出gitlab镜像
docker save -o gitlab-xxx.tar gitlab-xxx:latest
-
拷贝到目标服务器B后,在docker中加载镜像
docker load -i gitlab-xxx.tar
在目标服务器B查看镜像列表,确认镜像成功导入。
迁移gitlab数据
服务器A的gitlab容器将配置文件目录、数据文件目录、日志文件目录挂载到宿主机的本地目录
- /srv/gitlab/config
- /srv/gitlab/data
- /srv/gitlab/logs
为避免麻烦,直接在服务器B上建立同样的目录,将/srv/gitlab/config 目录 和 /srv/gitlab/data 目录拷贝过来。/srv/gitlab/logs可以不用拷贝。这样服务器B的现场基本和服务器A的现场就一致了。
编写docker run的脚本
日常在使用docker时,个人习惯是写一个docker run的脚本文件。这样方便保存容器创建时的一些配置参数,虽然这些参数在docker inspect中大多能找到,但还是觉得脚本来得更直观。当然docker-compose.yml可能更符合大多数人的习惯吧,我还是习惯写个bash脚本。
docker run --detach \
--hostname a8dc5c31ddf7 \
--publish 8443:443 --publish 8080:80 --publish 8022:22 \
--name gitlab \
--restart always \
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
gitlab-xxx:latest
说明:
--hostname a8dc5c31ddf7
容器内的hostname。但为了避免麻烦还是设置成服务器A上的gitlab容器的hostname
--publish 8443:443 --publish 8080:80 --publish 8022:22
暴露的端口,和之前保持一致
--volume $GITLAB_HOME/config:/etc/gitlab
gitlab的配置目录
--volume $GITLAB_HOME/logs:/var/log/gitlab
gitlab的日志目录
--volume $GITLAB_HOME/data:/var/opt/gitlab
gitlab的数据目录
$GITLAB_HOME:为了方便,在docker的宿主机上配置环境变量export $GITLAB_HOME=/srv/gitlab
遇到的第一个坑
按以上脚本启动容器。查看容器日志 docker logs -f gitlab,会发现gitlab容器反复重启。这是遇到的第一个坑。查看容器日志,如下
If this container fails to start due to permission problems try to fix it by executing:
docker exec -it gitlab update-permissions
docker restart gitlab
Installing gitlab.rb config...
cp: cannot create regular file '/etc/gitlab/gitlab.rb': Permission denied
从日志上看是权限问题。可以按照日志提示信息做如下两个操作。注意,在容器重启过程中也是可以执行的,由于容器可能正在重启的过程中,所以一次执行可能不会成功,可以执行多次。或者docker stop gitlab在docker start gitlab,立即执行下面这两个操作。
docker exec -it gitlab update-permissions
docker restart gitlab
但在我的环境中即便能够执行update-permissions,也没什么作用,还是会反复重启。于是尝试第二个办法。gitlab-ctl reconfigure
docker stop gitlab ,然后 docker start gitlab ,立即进入容器 docker exec -it gitlab bash,在容器中,执行gitlab-ctl reconfigure 。实践证明,这个方法是有效的。执行gitlab-ctl reconfigure成功后,可正常访问gitlab了,可以看到之前的项目和数据都完好无损。
等等,以为这就可以了?再查看一下gitlab容器日志。
遇到的第二个坑
现在虽然gitlab可以正常访问了,但是容器日志中频繁输出如下错误:
caller=main.go:226 err="open /var/opt/gitlab/alertmanager/data/nflog: permission denied"
查看gitlab各服务状态:docker exec gitlab gitlab-ctl status
[root@localhost data]# docker exec gitlab gitlab-ctl status
down: alertmanager: (pid 8502) 366s; run: log: (pid 489) 1206s
run: gitaly: (pid 473) 1206s; run: log: (pid 472) 1206s
run: gitlab-monitor: (pid 478) 1206s; run: log: (pid 477) 1206s
...
alertmanager是down状态。所幸,其余服务都是run的状态。参考这里 https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/2691
alertmanager由于文件路径权限问题导致无法启动,这是gitlab早期版本的一个bug,我用的gitlab刚好就是那个早期版本。在容器内处理一下吧。手动修改目录权限,在容器内修改权限。
进入容器:docker exec -it gitlab bash
在容器内看目录 /var/opt/gitlab/alertmanager/data 权限
root@a8dc5c31ddf7:/var/opt/gitlab/alertmanager# ll
total 8
drwxr-x---. 3 gitlab-prometheus root 42 Mar 5 03:45 ./
drwxr-xr-x. 20 root root 4096 Mar 5 03:45 ../
-rw-r--r--. 1 gitlab-prometheus root 132 Mar 5 03:29 alertmanager.yml
drwx------. 2 root root 98 Mar 5 08:30 data/
可以看到,/var/opt/gitlab/alertmanager/data/ 目录的owner是root
修改容器内路径/var/opt/gitlab/alertmanager/data 的 owner 为 gitlab-prometheus
chown -R gitlab-prometheus:gitlab-prometheus data/
修改后
root@a8dc5c31ddf7:/var/opt/gitlab/alertmanager# ll
total 8
drwxr-x---. 3 gitlab-prometheus root 42 Mar 5 03:45 ./
drwxr-xr-x. 20 root root 4096 Mar 5 03:45 ../
-rw-r--r--. 1 gitlab-prometheus root 132 Mar 5 03:29 alertmanager.yml
drwx------. 2 gitlab-prometheus gitlab-prometheus 98 Mar 5 08:30 data/
再次查看容器内gitlab各服务状态
[root@localhost data]# docker exec gitlab gitlab-ctl status
run: alertmanager: (pid 8502) 366s; run: log: (pid 489) 1206s
run: gitaly: (pid 473) 1206s; run: log: (pid 472) 1206s
run: gitlab-monitor: (pid 478) 1206s; run: log: (pid 477) 1206s
...
alertmanager已经由之前的down变成了run。
以上两个问题都解决了,如果还有问题,再次执行 gitlab-ctl reconfigure 试试,或者重启gitlab容器试试。
总结
- 基于docker部署的gitlab服务迁移,直接复制配置和数据目录,使用同版本镜像启动容器的方式是可行的,也并不麻烦。一般会遇到权限问题,通过执行 gitlab-ctl reconfigure 来解决;
- 第二个坑那种bug问题,可以手动改owner来解决权限问题。
- 在没有做配置修改的情况下,执行 “gitlab-ctl reconfigure” 和 “重启容器”(restart或者stop+start)管用。解决问题就是好的。
以上是我的一次gitlab容器迁移经历。未必完全适合您的情况,在没有备份又不明就里的情况下,不可盲目照搬操作。以上遇到的问题和解决办法仅供参考。