如何将已有的docker服务迁移至Kubernetes集群中

问题描述

在接触到Kubernetes集群之前,我所需要的服务都是以docker的形式部署在三台不同的服务器上的,由于docker服务数量越来越多,我有时分不清某个服务部署在哪台服务器上,或者我想将一个服务由A服务器迁移至B服务器就很麻烦,还有一个就是我想接入promethese来做监控
综上原因,我打算将这三台服务器组成一个Kubernetes集群,并且将所有的docker服务都迁移至Kubernetes集群中
目前我已有的服务有gitlab、nextcloud、verdaccio还有一些个人打包镜像定制的服务,这里就以这gitlab服务为代表来描述整个迁移过程

迁移思路

我的迁移思路就是:

  1. 先准备好一个跟原来服务使用相同版本镜像的环境
  2. 将这个空白环境的服务启动
  3. 将原来docker服务的数据进行打包或者说备份
  4. 将备份的压缩文件复制到现在的集群环境中来
  5. 执行恢复操作
  6. 检查恢复后的数据是否异常,恢复后的服务是否都可用

准备工作

在正式迁移前,你需要准备如下:

  1. 一个已经部署好并且能够正常运行的Kubernetes集群(包括Kubernetes的网络组件、ingress controller等都需安装好)
  2. 已经具备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:  gitlab
  labels:
    name: "gitlab"  
spec:
  capacity:
      storage: 2Gi
  accessModes: ["ReadWriteMany"]
  volumeMode: Filesystem
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data/gitlab
    server: 172.16.10.21
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gitlab-pvc
  namespace: app
spec:
  accessModes: ["ReadWriteMany"]
  resources:
    requests:
      storage: 2Gi
  selector:
    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: gitlab
  namespace: app
  labels:
    name: gitlab
spec:
  selector:
    matchLabels:
      name: gitlab
  replicas: 1
  template:
    metadata:
      labels:
        name: gitlab
    spec:
      containers:
      - name: gitlab
        image: gitlab/gitlab-ce:13.9.2-ce.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: http
        - containerPort: 22
          name: ssh
        - containerPort: 5005
          name: intel
        volumeMounts:
        - name: pvc-data
          mountPath: /etc/gitlab
          subPath: config
        - name: pvc-data
          mountPath: /var/log/gitlab
          subPath: logs
        - name: pvc-data
          mountPath: /var/opt/gitlab
          subPath: data
      volumes:
      - name: pvc-data
        persistentVolumeClaim:
          claimName: gitlab-pvc
      restartPolicy: 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: gitlab
  namespace: app
  labels:
    name: gitlab
spec:
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: http
  - name: ssh
    port: 22
    targetPort: ssh
  - name: intel
    port: 5005
    targetPort: intel
  selector:
    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-com
  namespace: app
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.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.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: gitlab
            port: 
              number: 80
  - host: registry.test.com
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: gitlab
            port: 
              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/bash

    cd /var/opt/gitlab/backups/
    
    chmod 777 1680684662_2024_04_05_15.4.0_gitlab_backup.tar
    
    chown git.git 1680684662_2024_04_05_15.4.0_gitlab_backup.tar
    
    gitlab-ctl stop puma
    
    gitlab-ctl stop sidekiq
    
    # 然后修改postgresql的权限,具体方法参考下面报错记录的第2点
    
    # restore的时间会比较久
    gitlab-backup restore BACKUP=1680684662_2024_04_05_15.4.0
    
    gitlab-ctl reconfigure 
    
    gitlab-ctl restart puma
    
    gitlab-ctl restart sidekiq
    
    gitlab-ctl restart
    
    exit

然后退出容器,进入到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) FOSS
 GitLab Shell: 14.10.0
 PostgreSQL:   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,那么我可以提供一个排查思路

  1. 直接curl这个gitlab的pod的clusterip,看是否能正常访问,如果这里也是报错502,那就是你恢复数据的过程中出错了
  2. 清空PV对应目录下的所有数据,等一会儿后重新起gitlab服务后,正常访问,访问成功,无异常,并将此时gitlab自己的配置文件备份在一边
  3. 将原来docker上正在运行的gitlab的配置文件拷贝过来,拷贝过来之后,修改gitlab.rb中的两个URL(访问的URL以及registey的URL),都修改为现在的域名,然后进入容器内重新加载配置,重启gitlab,再进行访问,访问正常
  4. 进行数据恢复,操作如gitlab迁移文档所示,这一次数据恢复后没有访问异常的现象

如果你恢复后的gitlab无法下载镜像,你可以从下列几个方面排查

  1. 检查你服务器的docker的daemon.json是否将新的registry的域名添加到了insecure-registries中
  2. 检查你的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'] = true

registry_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服务,然后再去访问,就已经可以了

如果你在迁移过程中还有其他问题,欢迎留言一起讨论

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-13 11:48:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-13 11:48:02       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-13 11:48:02       58 阅读
  4. Python语言-面向对象

    2024-07-13 11:48:02       69 阅读

热门阅读

  1. 【Go系列】 函数与方法

    2024-07-13 11:48:02       20 阅读
  2. Mysql索引、执行计划、体系架构

    2024-07-13 11:48:02       25 阅读
  3. php计算两张照片的相似度,范围:0-100

    2024-07-13 11:48:02       24 阅读
  4. 打工人如何应对AI对工作岗位的风险

    2024-07-13 11:48:02       24 阅读
  5. AM243-IPC

    AM243-IPC

    2024-07-13 11:48:02      22 阅读
  6. 【2024暑期实习】接到新需求该如何做?

    2024-07-13 11:48:02       22 阅读
  7. MATLAB中Simulink.exportToTemplate用法

    2024-07-13 11:48:02       22 阅读