如何将已有的docker服务迁移至Kubernetes集群中
- 问题描述
- 迁移思路
- 准备工作
- 迁移gitlab过程
- 1. 创建namespace
- 2. 创建gitlab需要的pv跟pvc
- 3.创建gitlab的deployment
- 4.创建gitlab的service
- 5.创建gitlab的ingress
- 6.将原来的gitlab容器中的数据打包
- 7.恢复配置文件数据
- 8.正式恢复数据
- 报错记录
- 1.gitlab管理员账号初始化无法登录
- 2.gitlab恢复数据时postgresql报错
- 3.恢复后的gitlab无法访问
问题描述
在接触到Kubernetes集群之前,我所需要的服务都是以docker的形式部署在三台不同的服务器上的,由于docker服务数量越来越多,我有时分不清某个服务部署在哪台服务器上,或者我想将一个服务由A服务器迁移至B服务器就很麻烦,还有一个就是我想接入promethese来做监控
综上原因,我打算将这三台服务器组成一个Kubernetes集群,并且将所有的docker服务都迁移至Kubernetes集群中
目前我已有的服务有gitlab、nextcloud、verdaccio还有一些个人打包镜像定制的服务,这里就以这gitlab服务为代表来描述整个迁移过程
迁移思路
我的迁移思路就是:
- 先准备好一个跟原来服务使用相同版本镜像的环境
- 将这个空白环境的服务启动
- 将原来docker服务的数据进行打包或者说备份
- 将备份的压缩文件复制到现在的集群环境中来
- 执行恢复操作
- 检查恢复后的数据是否异常,恢复后的服务是否都可用
准备工作
在正式迁移前,你需要准备如下:
- 一个已经部署好并且能够正常运行的Kubernetes集群(包括Kubernetes的网络组件、ingress controller等都需安装好)
- 已经具备Kubernetes的基础知识,包括如何编写资源对象的yaml文件、创建pv/pvc等
迁移gitlab过程
我的gitlab打算迁移到Kubernetes集群中,不指定分配在哪个节点,但是要求要将gitlab的配置文件、数据、日志映射出来并保存
我这里是先创建一个空的gitlab,也就是提前讲gitlab所需要的资源对象都迁移过来,然后再执行恢复数据的步骤
数据持久化保存可以使用storageclass可以自己创建pv并且绑定pvc,这里我是自己创建pv跟pvc的
正式开始迁移前,请将三台服务器上部署nfs,并且将一个统一保存数据的目录挂载到node节点上(我这里是将master的/volume目录挂载到两个node节点上)
1. 创建namespace
创建一个namespace,将gitlab相关的资源对象都部署在这个namespace里面
#创建namespace app
kubectl create namespace app
2. 创建gitlab需要的pv跟pvc
这里通过nfs的方式进行数据卷挂载,gitlab的相关数据都挂载到master的/data/gitlab目录下
root@master:/deployment/pvc# cat gitlab-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: gitlablabels:name: "gitlab"
spec:capacity:storage: 2GiaccessModes: ["ReadWriteMany"]volumeMode: FilesystempersistentVolumeReclaimPolicy: Retainnfs:path: /data/gitlabserver: 172.16.10.21
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: gitlab-pvcnamespace: app
spec:accessModes: ["ReadWriteMany"]resources:requests:storage: 2Giselector:matchLabels:name: "gitlab"
创建这个pv跟pvc
kubectl apply -f gitlab-pv.yaml
3.创建gitlab的deployment
root@master:/deployment/deployment# cat gitlab-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: gitlabnamespace: applabels:name: gitlab
spec:selector:matchLabels:name: gitlabreplicas: 1template:metadata:labels:name: gitlabspec:containers:- name: gitlabimage: gitlab/gitlab-ce:13.9.2-ce.0imagePullPolicy: IfNotPresentports:- containerPort: 80name: http- containerPort: 22name: ssh- containerPort: 5005name: intelvolumeMounts:- name: pvc-datamountPath: /etc/gitlabsubPath: config- name: pvc-datamountPath: /var/log/gitlabsubPath: logs- name: pvc-datamountPath: /var/opt/gitlabsubPath: datavolumes:- name: pvc-datapersistentVolumeClaim:claimName: gitlab-pvcrestartPolicy: Always
创建这个deployment
kubectl apply -f gitlab-deployment.yaml
此时可以在Kubernetes集群上看到这个gitlab的pod
root@master:/deployment/deployment# kubectl get pod -n app
NAME READY STATUS RESTARTS AGE
gitlab-64d45fc967-7hmlg 1/1 Running 0 3m3s
4.创建gitlab的service
root@master:/deployment/svc# cat gitlab-svc.yaml
apiVersion: v1
kind: Service
metadata:name: gitlabnamespace: applabels:name: gitlab
spec:ports:- name: httpprotocol: TCPport: 80targetPort: http- name: sshport: 22targetPort: ssh- name: intelport: 5005targetPort: intelselector:name: gitlab
创建这个service
kubectl apply -f gitlab-svc.yaml
查看创建的service
master:/deployment/svc# kubectl get svc -n app
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
gitlab ClusterIP 10.101.41.44 <none> 80/TCP,22/TCP,5005/TCP 7s
5.创建gitlab的ingress
原来我的gitlab的访问是直接IP+端口或者说再防火墙上做了域名转发,现在我希望直接通过一个域名来访问我的gitlab服务,所以需要配置ingress规则
root@master:/deployment/Ingress# cat ingress-gitlab.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: gitlab-test-comnamespace: appannotations:kubernetes.io/ingress.class: nginxnginx.ingress.kubernetes.io/proxy-body-size: "10240M"nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"nginx.ingress.kubernetes.io/proxy-read-timeout: "300"nginx.ingress.kubernetes.io/proxy-send-timeout: "300"nginx.ingress.kubernetes.io/ssl-redirect: "true"spec:rules:- host: gitlab.test.comhttp:paths:- pathType: Prefixpath: /backend:service:name: gitlabport: number: 80- host: registry.test.comhttp:paths:- pathType: Prefixpath: /backend:service:name: gitlabport: number: 5005
创建这个ingress规则
kubectl apply -f ingress-gitlab.yaml
查看创建的ingress
root@master:/deployment/Ingress# kubectl get ingress -n app
NAME CLASS HOSTS ADDRESS PORTS AGE
gitlab-test-com <none> gitlab.test.com,registry.test.com 10.109.131.26 80 7s
执行完上述操作,那么应该已经启动了一个全新的gitlab容器,可以在浏览器中访问这个gitlab的域名以及通过kubectl logs检查这个pod是否有报错,如果都没有,就可以开始恢复数据了
6.将原来的gitlab容器中的数据打包
假如我原来的gitlab的容器名为gitlab_web,恢复数据前,我需要将这个容器中的数据都打包,相当于做一次全量备份
(更多关于gitlab备份与恢复的知识,可查看gitlab的备份与恢复
#这里备份的时长取决于你数据的多少,数据量越多,备份时间越久
docker exec -t docker_web gitlab-backup create
备份完产生的数据会放在gitlab容器内部的/var/opt/gitlab/backups/目录下,然后将这个产生的备份文件拷贝出来,放到现在Kubernetes集群的master的/data/gitlab/data/backups目录下去,方便后续恢复
7.恢复配置文件数据
恢复配置文件,将原来docker容器使用的配置文件config目录下的所有内容传到master的/volume/gitlab/config下去(可提前将现在kubernetes集群下的这个目录备份),然后将里面需要修改的url和端口修改好
8.正式恢复数据
恢复数据需要进入容器内部
kubectl exec -it gitlab-68799bbc4d-dvcc6 -n app -- /bin/bashcd /var/opt/gitlab/backups/chmod 777 1680684662_2024_04_05_15.4.0_gitlab_backup.tarchown git.git 1680684662_2024_04_05_15.4.0_gitlab_backup.targitlab-ctl stop pumagitlab-ctl stop sidekiq# 然后修改postgresql的权限,具体方法参考下面报错记录的第2点# restore的时间会比较久gitlab-backup restore BACKUP=1680684662_2024_04_05_15.4.0gitlab-ctl reconfigure gitlab-ctl restart pumagitlab-ctl restart sidekiqgitlab-ctl restartexit
然后退出容器,进入到web界面去访问,去检查现在的gitlab的数据是否跟原来一直,查看相关的package和images等是否存在,如果都有,那么迁移至此便成功了
报错记录
1.gitlab管理员账号初始化无法登录
刚刚创建好的gitlab首次通过web登陆的时候无法正常登陆,他的init passwd存放在放配置文件的config目录下,如果你没有找到这个存放初始密码的文件,可通过下面方式重置管理员密码
root@master:~# kubectl exec -it gitlab-68799bbc4d-g5vld -n app -- bash
root@gitlab-68799bbc4d-g5vld:/# gitlab-rails console -e production #启动Ruby on Rails控制台
--------------------------------------------------------------------------------Ruby: ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-linux]GitLab: 15.4.0 (70d9f335be4) FOSSGitLab Shell: 14.10.0PostgreSQL: 13.6
------------------------------------------------------------[ booted in 14.60s ]
Loading production environment (Rails 6.1.6.1)
irb(main):001:0> user = User.where(id: 1).first
=> #<User id:1 @root>
irb(main):002:0> user.password = 'Eacomp@2203'
=> "Eacomp@2203"
irb(main):003:0> user.password_confirmation = 'Eacomp@2203'
=> "Eacomp@2203"
irb(main):004:0> user.save
=> true
irb(main):005:0>
2.gitlab恢复数据时postgresql报错
gitlab在restore数据的过程中,会提示错误信息:都是说必须要XXX的owner(和 superuser)才能成功
Restoring PostgreSQL database gitlabhq_production ... ERROR: must be owner of extension pg_trgm
ERROR: must be owner of extension btree_gist
ERROR: must be owner of extension btree_gist
ERROR: must be owner of extension pg_trgm
解决方法:
1.修改postgresql配置
$ vi /var/opt/gitlab/postgresql/data/postgresql.conf # 将这个文件中的listen_addresses修改如下
listen_addresses = '*'
$ vi /var/opt/gitlab/postgresql/data/pg_hba.conf # 将这个文件的末尾新增下列两行
local all all trust
host all all 127.0.0.1/32 trust
2.重启gitlab服务
$ gitlab-ctl restart
3.修改gitlab账号为超级用户
$ su - gitlab-psql$ /opt/gitlab/embedded/bin/psql -h 127.0.0.1 gitlabhq_production
psql (9.2.8)Type "help" for help.gitlabhq_production=# ALTER USER gitlab WITH SUPERUSER;ALTER ROLE
gitlabhq_production-# \q
$ exit
然后再恢复数据就可以了
3.恢复后的gitlab无法访问
恢复过程中,你还可能遇到其他报错,包括但恢复后的gitlab无法访问
如果恢复后你的gitlab服务无法访问,报错502,那么我可以提供一个排查思路
- 直接curl这个gitlab的pod的clusterip,看是否能正常访问,如果这里也是报错502,那就是你恢复数据的过程中出错了
- 清空PV对应目录下的所有数据,等一会儿后重新起gitlab服务后,正常访问,访问成功,无异常,并将此时gitlab自己的配置文件备份在一边
- 将原来docker上正在运行的gitlab的配置文件拷贝过来,拷贝过来之后,修改gitlab.rb中的两个URL(访问的URL以及registey的URL),都修改为现在的域名,然后进入容器内重新加载配置,重启gitlab,再进行访问,访问正常
- 进行数据恢复,操作如gitlab迁移文档所示,这一次数据恢复后没有访问异常的现象
如果你恢复后的gitlab无法下载镜像,你可以从下列几个方面排查
- 检查你服务器的docker的daemon.json是否将新的registry的域名添加到了insecure-registries中
- 检查你的gitlab的配置文件,registry相关的配置是否打开并且正常配置
# registry_external_url 'https://registry.example.com'
registry_external_url 'http://registry.test.com:5005'### Settings used by GitLab application
gitlab_rails['registry_enabled'] = trueregistry_nginx['enable'] = true
registry_nginx['listen_port'] = 5005
#下面这个配置需要打开,否则会导致无法上传镜像到gitlab的container registry里面,会报错说unauthorized: authentication required(即使你login成功了)
registry_nginx['proxy_set_headers'] = {"Host" => "$http_host","X-Real-IP" => "$remote_addr","X-Forwarded-For" => "$proxy_add_x_forwarded_for","X-Forwarded-Proto" => "https","X-Forwarded-Ssl" => "on"}
然后再重新加载gitlab的配置,以及重启gitlab服务,然后再去访问,就已经可以了
如果你在迁移过程中还有其他问题,欢迎留言一起讨论