“升级是找死,不升级是等死”,GitLab CE 的痛苦升级之路

news2025/7/19 14:29:25

编者按:本文转载自公众号运维识堂,已经联系作者取得转载授权。

GitLab 在发展的十余年中,在国内积累了大量的 CE 用户,但是很多 CE 用户并不会跟随 GitLab 的发版节奏(月度发版)进行版本升级,在 GitLab 已经发布 16.4 版本的情况下,还有大量的用户使用 10 以下的版本。下面文章的作者就讲述了将使用源码编译安装的 GitLab 9.x 版本进行升级的过程,中间涉及了数据库的切换(从 Mysql 到 Postgres)、数据的备份和恢复、容器的操作等,过程虽然“看似简单”,但是却需要深厚的技术储备以及强大的信心才能完成这些操作,而且从测试验证到上生产历时两个月。对于很多运维人员来讲,下面的升级流程从测试环境到上生产环境都是一个极其大的挑战,如果出现问题,就可能导致企业内部的源代码托管平台不可用,影响公司的软件研发。

从另外一个角度来讲,这也是使用 CE 版带来的技术债,很多 CE 用户,担心升级过程出问题,秉承“不动就不出问题”的原则,一直在使用老旧版本,这样极容易导致产品不仅无法获取到最新的功能特性,还可能由于老旧版本存在的安全漏洞,容易让 GitLab 遭受外部攻击,长此以往,就造成了“升级是找死,不升级是等死”的困境。

其实,企业用户应该尽量使用企业版本(EE),除了能及时获取最新功能,还能享受企业级的服务支持,原厂服务轻松搞定产品升级、安全问题修复等,不仅能够将运维人员从升级恐惧症中解脱出来,还能利用最新的功能特性提升研发效率。

开始之前

从 2019 年开始,SonarQube 和 GitLab 相继宣布不在提供对 MySQL 方式存储数据的支持(Consider removing support for MySQL)。由于 Oracle 和 SQL Server 都是收费的商业数据库,而 PostgreSQL 则是开源的,加之最近几年针对 PostgreSQL 的创新不断和 ChatGPT 的火热,Postgres 再次进入我的 TODO 列表。从云厂 RDS Postgres 插件列表和几个开源项目(比如:Neon: Serverless Postgres:无服务的 Postgres,timescaledb:基于 Postgres 的时序数据库扩展,FerretDB:将 MongoDB 协议转化为 SQL 使用 Postgres 作为存储后端)以及像这种基于 PostgreSQL 构建由 LLM 驱动的专属 ChatBot(其中用到的 pgvector)AI 应用场景。可见 Postgres 的火爆,所以想一探究竟。

因为 Postgres 在未来肯定是必须需要去了解和使用的,因为它已经变成很多开源软件的首选或者说默认数据库,所以到了必须要学习的地步。看完 PostgreSQL 教程,顿时想起之前 GitLab 迁移失败的痛苦经历(因为数据量大,一次测试 3 个小时没了,时间成本太高,以及一次次失败带来的压力让人精神崩溃)。最终在多次失败后不断总结原因,终于找到问题以及可能的解决办法。

破解之谜

因为最开始搭建的代码库是基于 GitLab 9.0.6 源代码部署并且采用外置 RDS MySQL 5.6 搭建,日常维护也就是扩盘或者升级 CPU 和内存,6 年从未升级过 GitLab(主要还是怕升级影响近千人的日常工作,又不是不能用何必自找麻烦呢)。一年前尝试做过升级测试,也咨询过厂商和社区(能搞这方面的人是真的少),最终失败(一个字穷)。现在回过头来看,还是没有认真看官方给的文档,从一开始升级思路就错了(下面给正确的解法)。

因为从 GitLab 12.1 开始不在支持 MySQL 数据库,所以必须完成 MySQL 到 Postgres 的迁移。由于官方给的一体包(Omnibus GitLab Packages)默认就采用的 Postgres 数据库,为了后面版本升级方便,所以需要优先将当前版本的数据库迁移到 Postgres 上,下面主要分享 MySQL 迁移 Postgres 核心流程。

备份当前环境

源代码安装的备份方式
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
# 注意:备份时注意磁盘空间,备份后会在备份目录产生一个带时间戳的 tar 包文件

安装一台新的 Linux 环境

➤ 安装 Docker

➤ 准备 3 个容器(mysql/postgres/pgloader)和 迁移配置文件

file: /data/gitlab/migrate/docker-compose.yml

version: '3'

services:
  pgloader:
    image: seanly/toolset:pgloader
    tty: true
    volumes:
      - ./:/ws
    restart: always
    security_opt:
      - seccomp:unconfined
  mysql:
    image: seanly/dbextra:mysql-5.7.35
    restart: unless-stopped
    volumes:
      - ./mysql-data:/var/lib/mysql
      - ./:/ws
    environment:
      TZ: Asia/Shanghai
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: 'gitlabhq_production'
    healthcheck:
      test: mysql --user=root --password=$$MYSQL_ROOT_PASSWORD -e "SHOW DATABASES;"
      interval: 3s
      timeout: 1s
      retries: 5
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_general_ci
      - --max_allowed_packet=512M

  postgres:
    image: postgres:11-alpine
    restart: always
    environment:
      - POSTGRES_USER=gitlab
      - POSTGRES_PASSWORD=gitlab123
      - POSTGRES_DB=gitlabhq_production
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
      - ./:/ws
    healthcheck:
      test: pg_isready -U gitlab -h 127.0.0.1
      interval: 5s

file: /data/gitlab/migrate/gitlab.loader

LOAD DATABASE     
  FROM mysql://root:root123@mysql:3306/gitlabhq_production     
  INTO pgsql://gitlab:gitlab123@postgres:5432/gitlabhq_production
  
WITH include no drop, truncate, disable triggers, create no tables,     
     create no indexes, preserve index names, no foreign keys,     
     data only,     
     workers = 8, concurrency = 16,     
     batch rows = 100000, batch size = 512MB, multiple readers per thread, rows per range = 500000
     
     SET MySQL PARAMETERS
     net_read_timeout = '90',
     net_write_timeout = '180'
     
     ALTER SCHEMA 'gitlabhq_production' RENAME TO 'public'
     
     ;

执行命令 docker-compose up -d 启动容器。

获取 MySQL 的备份

# 1. 将备份文件拷贝到新主机,假设存储在 /data/gitlab/backup 目录
# 2. 从 TIMESTAMP_gitlab_backup.tar 包获取 db/database.sql.gz

cd /data/gitlab/backup
tar xf TIMESTAMP_gitlab_backup.tar db
gunzip db/database.sql.gz

# /data/gitlab/backup/db/database.sql 就是 MySQL 的备份
mv /data/gitlab/backup/db/database.sql /data/gitlab/migrate/mysql_database.sql

获取 Postgres 的备份

这一步很关键,为了确保后面的升级成功,所以需要完整的一个空的数据库结构,数据可以通过 MySQL 库迁移。处理方式是通过容器初始化一个版本,然后备份里面的 Postgres。

➤ 启动一个 GitLab CE 9.0.6 实例

file: /data/gitalab/migrate/gitlab/docker-compose.yml

version: '3'
services:  
  gitlab:    
    image: 'gitlab/gitlab-ce:9.0.6-ce.0'    
    restart: always    
    volumes:      
      - './:/ws'    
    shm_size: '256m'

启动容器并备份数据库

cd /data/gitalab/migrate/gitlab
docker-compose up -d
docker-compose exec gitlab bash
# 容器内部
su - gitlab-psql
pg_dump -U gitlab-psql -h /var/opt/gitlab/postgresql -d gitlabhq_production -f /ws/gitlab_backup.sql
exit
# 容器外部
docker-compose down
mv gitlab_backup.sql /data/gitalab/migrate/

迁移 MySQL 到 Postgres

➤ 恢复 MySQL

cd /data/gitalab/migrate/
docker-compose exec mysql bash

# 进入 msyql 容器
mysql -u root -p gitlabhq_production < /ws/mysql_database.sql
# 输入密码 root123

➤ 恢复 Postgres

cd /data/gitalab/migrate/
docker-compose exec postgres bash

# 进入 postgres 容器

psql -U gitlab -d gitlabhq_production -f /ws/gitlab_backup.sql

➤ 迁移 MySQL 到 Postgres

docker-compose exec pgloader pgloader /ws/gitlab.loader

图片

➤ 导出 Postgres

cd /data/gitalab/migrate/
docker-compose exec postgres bash

# 进入容器
pg_dump -U gitlab -d gitlabhq_production -f /ws/database.sql
exit
# 退出容器

➤ 恢复 Postgres 到备份包

mv /data/gitalab/migrate/database.sql /data/gitlab/backup/db/database.sql
cd /data/gitlab/backup/
# 打包 sql 为 sql.gz
gzip db/database.sql
# 更新备份包的 db/database.sql.gz
tar rf TIMESTAMP_gitlab_backup.tar db/database.sql.gz

恢复备份并升级

➤ 安装一个 GitLab CE 9.0.6 容器

file: /data/gitlab/test-upgrade/docker-compose.yml

version: '3'
services:  
  gitlab:    
  image: 'gitlab/gitlab-ce:9.0.6-ce.0'    
  restart: always    
  ports:      
    - '80:80'      
    - '443:443'      
    - '2222:22'    
  volumes:      
    - './config:/etc/gitlab'      
    - './data:/var/opt/gitlab'      
    - '/data/backup:/var/opt/gitlab/backups'    
  shm_size: '256m'

➤ 启动容器并恢复

mkdir -p /data/gitlab/test-upgrade/{data/backup,config}
cp -r /data/gitlab/backup/TIMESTAMP_gitlab_backup.tar /data/gitlab/test-upgrade/backup/

docker-compose up -d 
docker-compose exec gitlab bash 

# 进入容器
gitlab-rake gitlab:backup:restore RAILS_ENV=production BACKUP=${TIMESTAMP}

# 退出容器
docker-compose logs -f

➤ 升级版本

版本升级方式很简单,版本选择请看官方升级路径,通过修改 docker-compose.yml 里面的镜像版本,然后执行 docker-compose up -d 进行版本升级。

最后

虽然升级验证过程痛苦,但是学习到的东西也挺多。现在回看整个过程最关键的地方是只需要将 MySQL 数据通过 pgloader 迁移到 GitLab Postgres 的数据库中,其他都是标准升级流程,再借助容器屏蔽工具对环境的依赖。

关于极狐GitLab

极狐GitLab 是 GitLab 面向国内用户推出的一体化 DevOps 平台。GitLab 作为极狐GitLab 的上游,意味着极狐GitLab 拥有和 GitLab 同等的功能,而且极狐GitLab 还针对国内用户开发了中专门面向国内企业的功能特性,比如和微信、钉钉、飞书的集成等。

极狐GitLab 本土化运营团队能够为国内企业用户提供专业的企业级服务支持,目前已经帮助数百家企业实现了 DevOps 的落地实践。极狐GitLab 专业的服务能力能够帮助企业实现 GitLab/极狐GitLab 的平滑升级。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1102660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于AT89C52+ADC0809+LCD1602的模数转换实验ptoteus仿真设计

一、仿真原理图&#xff1a; 二、仿真效果图&#xff1a; 三、仿真工程&#xff1a; 基于AT89C52ADC0809LCD1602的模数转换实验ptoteus仿真设计资源-CSDN文库

flask实战(问答平台)

问答平台项目结构搭建 先创建一个配置文件config.py&#xff0c;后面有些配置写在这里 #app.py from flask import Flask import configapp Flask(__name__) #绑定配置文件 app.config.from_object(config)app.route(/) def hello_world(): # put applications code herer…

数据结构-----红黑树的删除操作

目录 前言 一、左旋和右旋 左旋&#xff08;Left Rotation&#xff09; 右旋&#xff08;Right Rotation&#xff09; 二、红黑树的查找 三、红黑树的删除 1.删除的是叶子节点 1.1删除节点颜色为红色 1.2删除节点颜色为黑色 1.2-1 要删除节点D为黑色&#xff0c;兄弟节…

git 提交代码

提交代码流程 第一步:git status 第二步&#xff1a;git add . 第三步&#xff1a;git commit -m"xxx" 第四步&#xff1a;git pull origin dev 第五步&#xff1a;git push origin dev

HEIC转jpg

下载imagemagick,安装 https://imagemagick.org/archive/binaries/ImageMagick-7.1.1-20-Q16-HDRI-x64-dll.exe cmd D:\soft\ImageMagick-7.1.1-Q16-HDRI\magick.exe "C:\Users\Gamer\Downloads\iCloud 照片1\iCloud 照片\IMG_3889.HEIC" IMG_3889.jpg

不懂的东西

1、 2、 3、 4、 5、我看到那篇 Peace of mind 论文&#xff0c;有一个疑问&#xff0c;为什么论文里的量表用的频率指标&#xff1f;比如Some of the time&#xff0c; Not at all等&#xff0c;而PANAS用的是程度指标&#xff0c;比如moderately&#xff0c;a little等。…

一、初识 Elasticsearch:概念,安装,设置分词器

文章目录 01、初识 Elasticsearch正向索引和倒排索引索引MySQL与ES的概念映射安装ES分词器分词器的设置 01、初识 Elasticsearch 本次ES基于&#xff1a;7.12.1 版本 学习资源为&#xff1a;https://www.bilibili.com/video/BV1Gh411j7d6 什么是ES&#xff08;Elasticsearch&…

C/C++笔试易错与高频题型图解知识点(二)—— C++部分(持续更新中)

目录 1.构造函数初始化列表 1.1 构造函数初始化列表与函数体内初始化区别 1.2 必须在初始化列表初始化的成员 2 引用&引用与指针的区别 2.1 引用初始化以后不能被改变&#xff0c;指针可以改变所指的对象 2.2 引用和指针的区别 3 构造函数与析构函数系列题 3.1构造函数与析…

力扣环形链表(1)进阶环形链表(2)及环形链表的约瑟夫问题

为了加深对环形链表的理解和掌握&#xff0c;这两道题是很不错的选择。 这里所说环形链表不是一个圈圈的结构&#xff0c;而是带环链表。 链接&#xff1a;环形链表&#xff08;1&#xff09; 注意这里链表的长度 所以要注意链表是否为空 第一种方法&#xff0c;应该是比较容易…

竞赛选题 深度学习中文汉字识别

文章目录 0 前言1 数据集合2 网络构建3 模型训练4 模型性能评估5 文字预测6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习中文汉字识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xf…

影响多用户商城系统价格的因素有哪些?

多用户商城系统作为电商行业不可或缺的重要工具&#xff0c;其价格是众多商家关注的焦点。下面就影响多用户商城系统价格的因素有哪些作一些简单的介绍&#xff0c;希望对大家有所帮助(仅供参考)。 一、系统规模和功能 多用户商城系统的价格首先由其规模和功能决定。规模包括用…

如何使用RockPlus MES系统帮助SMT行业实现降本增效

SMT&#xff08;Surface Mount Technology&#xff09;是现代电子行业中主要的组装技术&#xff0c;广泛应用于电子产品的生产。SMT工艺涵盖了锡膏印刷、元器件贴装和回流焊接。经过这些关键工序&#xff0c;元器件被精确固定在电路板上&#xff0c;完成一个电子产品组装。 SM…

Java并发面试题:(五)volatile关键字

volatile 是什么 一旦一个共享变量&#xff08;类的成员变量、类的静态成员变量&#xff09;被volatile修饰之后&#xff0c;那么就具备了两层语义&#xff1a; 1&#xff09;保证了不同线程对这个变量进行操作时的可见性&#xff0c;即一个线程修改了某个变量的值&#xff0c…

网工内推 | 南天软件,base北京,需持有CCIE认证,最高25k

01 北京南天软件有限公司 招聘岗位&#xff1a;IPT运维工程师 职责描述&#xff1a; 负责客户Cisco语音网络IPT ,CUCM的日常运维&#xff0c;扩容和项目支持&#xff0c;支持路由交换&#xff0c;无线等项目&#xff0c;实施工作以及相关实施文档。 任职要求&#xff1a; 1、…

css 特别样式记录

一、 这段代码神奇的地方在于&#xff0c; 本来容器的宽度只有1200px&#xff0c;如果不给img赋予宽度100%&#xff0c;那么图片 会超出盒子&#xff0c;如果给了img赋予了宽度100%&#xff0c;多个图片会根据自己图片大小的比例&#xff0c;去分完那1200px&#xff0c;如图二。…

【LeetCode热题100】--75.颜色分类

75.颜色分类 方法一&#xff1a;使用单指针 class Solution {public void sortColors(int[] nums) {int n nums.length;int ptr 0;for(int i 0;i<n;i){if(nums[i] 0){int tmp nums[i];nums[i] nums[ptr];nums[ptr] tmp;ptr;}}for(int i ptr;i<n;i){if(nums[i] …

Linux:mongodb数据逻辑备份与恢复(3.4.5版本)

我在数据库aaa的里创建了一个名为tarro的集合&#xff0c;其中有三条数据 备份语法 mongodump –h server_ip –d database_name –o dbdirectory 恢复语法 mongorestore -d database_name --dirdbdirectory 备份 现在我要将aaa.tarro进行备份 mongodump --host 192.168.254…

剑指Offer || 038.每日温度

题目 请根据每日 气温 列表 temperatures &#xff0c;重新生成一个列表&#xff0c;要求其对应位置的输出为&#xff1a;要想观测到更高的气温&#xff0c;至少需要等待的天数。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 示例 1: 输入: temperatures…

Dubbo服务发布与消费过程概述

Dubbo服务发布与消费过程概述如下所示&#xff1a; &#xff08;1&#xff09;Dubbo服务发布 ServiceConfig引用服务提供类并通过ProxyFactory 生成invoker&#xff1b; 然后通过Protocol 将invoker转为Exporter&#xff0c;在这个过程中会先启动Netty Server监听服务连接&am…

什么是NetApp的DQP和如何安装DQP?

首先看看什么是DQP&#xff0c;DQPDisk Qualification Package&#xff0c;文字翻译就是磁盘验证包。按照NetApp的最佳实践&#xff0c;要定期升级DQP包&#xff0c;保证对最新磁盘和磁盘扩展柜的兼容。 本文主要介绍7-mode下如何升级DQP&#xff0c;至于cluster mode另外文章…