当前位置: 首页 > news >正文

go 持续集成、持续部署之gitlab流水线+docker-compose踩坑之旅

前言

在前面,我们已经能在开发服务器上运行docker-compose.prod.yml,实现在项目代码基础上实现两阶段构建(打包成二进制文件、运行),详见:go docker-compose对比开发环境配置的生产环境配置优化-CSDN博客。接下来,我们期望打包、部署配置在gitlab pipeline中运行,实现持续集成、持续部署。

项目架构

在这里插入图片描述

代码结构

在这里插入图片描述

源码

https://gitlab.zhangluyue.asia/go-web

演示

全流程演示

orm_framework、web_framework作为包依赖

orm_framework pipeline流程

在这里插入图片描述

tag job
  1. 创建zly_robot账号,提供developer权限,用于构建tag
  2. tag构建使用Semver规范
  3. 自动构建tag只构建patch(小版本)tag;如果需要更新major或者minor需要手动构建

创建机器人账号参与pipeline

为了保证项目的自动化和安全性,创建了一个机器人zly_robot账号设置有限的权限(developer)参与pipeline: 自动构建tag。

操作步骤

准备机器人账号邮箱(我用的qq邮箱zly_robot@qq.com) => 创建机器人gitlab账号 => 配置令牌 => 将令牌信息作为变量配置到项目variable中 => 编写pipeline job

创建robot实现自动生成tag

演示

pipeline 构建结果

在这里插入图片描述

business使用演示

在这里插入图片描述

yml模板文件

template-cicd与business、client的.gitlab-ci.yml的关系

在这里插入图片描述

项目构建

什么是构建

在这里插入图片描述

构建包含哪些步骤

在这里插入图片描述

构建报错

在这里插入图片描述

web-framework不需要main.go使用,但构建要求必须提供main.go,不然报错

我的项目构建

构建的具体操作,这里交给了Dockerfile去做;在gitlab pipeline主要需要考虑的就是代码推送镜像仓库,部署至指定服务器。

镜像仓库搭建,详见:docker docker、swarm 全流程执行-CSDN博客

预构建

我本来想创建预构建job,实现node_modules等依赖包的缓存,加快构建速度。但我现在使用Dockerfile参与构建,就可以直接使用docker的层缓存,无需自行编写。

废弃的pre-install-frontend: [jobs/废弃]pre-build-jobs.yml · main · go-web / template-cicd · GitLab

“COPY go.mod go.sum /” 利用docker层缓存

在这里插入图片描述

先拷贝go.mod、go.sum,然后下载依赖,再copy代码。因为依赖项变动的小,所以依赖不变的情况就可以利用go mod download的缓存,无需重新下载依赖

在这里插入图片描述

持续集成、持续部署过程中的问题解决

问题描述:gitlab由于硬盘满了导致频繁挂

页面错误信息:

500: We're sorry, something went wrong on our end
Request ID: 01K5111E0B61GWE8JF8KGZ15SETry refreshing the page, or going back and attempting the action again.
Please contact your GitLab administrator if this problem persists.

推测并确认原因:gitlab 服务器的硬盘满了,导致gitlab运行失败;

排查:gitlab的主要内容都在/dev/sda3上,需要把/dev/sda3扩大

df -h /var/opt/gitlab
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda3        18G   18G   20K 100% /
[root@localhost ~]# df -h /var/log/gitlab
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda3        18G   18G     0 100% /

解决方案:

在这里插入图片描述

# cloud-utils-growpart比fdisk更简单
yum install -y cloud-utils-growpart
# 扩展指定磁盘的分区号
growpart /dev/sda 3

其他:我还删除了历史日志

# 删除7天前的日志
sudo find /var/log/gitlab -type f -mtime +7 -delete
问题描述:磁盘错误挂载导致虚拟机无法启动,进入紧急模式

问题原因:完成上面的图片中的操作,扩展硬盘容量(扩展后效果如下图)后,我不知道如何扩大/dev/sad3(也就是图下面的代码步骤)。我想着怎么把多出来的devtmpfs、tmpfs等和gitlab-data数据link起来。就是说,/dev/sda3满了,我打算把gitlab-data通过link存到其他地方。

在这里插入图片描述

我的操作:(按照问AI)

mkdir /gitlab-data
mount /dev/sdb1 /gitlab-data
# 设置开机自动挂载(添加到/etc/fstab)
echo "/dev/sdb1 /gitlab-data ext4 defaults 0 0" | sudo tee -a /etc/fstab

我以为新增了一个硬盘分区(我一开始不懂,我以为上面多出来的devtmpfs啥的是增加的),我把/gitlab-data挂载到了一个不存在的分区/dev/sdb1上。// 实际上,我是扩展了已有/dev/sda的容量。

计划后面迁移数据,创建软链:

# 迁移数据目录(/var/opt/gitlab)
rsync -av /var/opt/gitlab/ /gitlab-data/var-opt-gitlab/
# 迁移日志目录(/var/log/gitlab)
rsync -av /var/log/gitlab/ /gitlab-data/var-log-gitlab/# 创建软链接:让 GitLab 访问新目录(无需修改配置)
ln -s /gitlab-data/var-opt-gitlab /var/opt/gitlab
ln -s /gitlab-data/var-log-gitlab /var/log/gitlab...

但中途,我重启了虚拟机,就启动失败了进入紧急模式:

在这里插入图片描述

在journalctl -xb日志中没有看到错误信息,通过思考想到是上面的操作步骤引入的错误。由于gitlab配置了开机启动,gitlab启动失败就导致开机失败。

问题修复:

# 将根分区重新挂载为可写模式(默认可能是只读)
mount -o remount,rw /# 删除上面添加的“/dev/sdb1 /gitlab-data ext4 defaults 0 0”
vim /etc/fstab# 删除无用目录
rm -rf /gitlab-data# 重启虚拟机

问题描述:gitlab job中尝试http登录镜像服务器失败

报错信息:

在这里插入图片描述

问题原因:job中使用了docker-in-docker服务,docker默认不支持http访问

在这里插入图片描述

image使用docker(而非alpine)保证环境一致性;内部使用docker-indocker服务原因:因为在docker job中需要使用docker build,不然需要手动安装docker-cli(image: alpine时)。

尝试配置允许http访问镜像服务器(配置无效):

在这里插入图片描述

DOCKER_TLS_CERTDIR:""(禁用TLS加密):

  • docker:dind镜像默认会启动TLS加密,在/certs目录生成证书,要求客户端通过https连接并验证证书。
  • 将该变量设为”“,会禁用TLS加密,允许docker客户端通过未加密的HTTP协议与DinD服务通讯

DOCKER_HOST: tcp://docker:2375(指定DinD服务地址):

  • docker客户端默认连接本地的unix:///var/run/docker.sock套接字,但在DinD模式下,Docker守护进程运行在独立的docker:dind容器下(服务名默认是docker)
  • 该配置告诉Docker客户端:不要连接本地套接字,而是通过TCP连接到docker服务的2375端口(这是DinD服务暴露的非机密端口与DOCKER_TLS_CERTDIR:""配合使用)
解决方案

使用宿主机docker,不使用docker-in-docker方式 // 隔离性差点,但好使

宿主机配置:

修改/etc/docker/daemon.json允许http访问镜像仓库

在这里插入图片描述

修改/etc/gitlab-runner/config.toml:启动特权模式,映射docker.sock;然后重启gitlab runner

在这里插入图片描述

移除dind服务,就能实现使用宿主机的docker配置,能够http访问镜像仓库。

其他解决方案:在镜像仓库中配置https证书,允许https访问。

docker-in-docker相关文章:gitlab-runner 中的 Docker-in-Docker - 莱布尼茨 - 博客园

gitlab job语法和优化

rules: [when:never]不执行不相关template-job

由于模板文件中前后端job放在了同一个文件中,那么比如在前端.gitlab-ci.yml中需要配置一下保证后端template-job虽然引入,但不执行

在这里插入图片描述

if ! docker info > /dev/null 2>&1;含义

if ! docker info > /dev/null 2>&1; 用于检查docker服务是否可用。

> /dev/null 标准输出重定向:docker info会输出大量信息,> /dev/null 将输出内容丢弃(不显示在终端),只关注命令是否执行成功

2>&1 标准错误重定向:2 代表错误输出流,&1代表标准输出流。2>&1表示将错误信息也重定向到/dev/null(与标准输出一起丢弃)

if !... 判断是否成功

模板job需要加.

在这里插入图片描述

不加 . 会单独作为一个job运行,如上图

set -e含义

set -e: 当脚本中任何一条命令执行失败(返回非0的退出码)时,立即终止整个脚本的执行,不再继续运行后续命令。

默认情况下,shell脚本的执行逻辑是:即使某条命令失败,也会继续执行后面的命令

deploy时使用ssh免密登录而不是账号密码登录

账号密码登录问题:

  • 安全性差
  • 易被锁定
  • 自动化障碍:ssh协议默认不支持脚本中直接传递密码
  • 权限粒度粗:密码是用户级别的,无法为特定操作(如部署)创建有限权限的临时凭证
dependencies和needs的区别

dependencies:指定后续Job依赖哪些前序Job,artifacts会自动带过来,可以使用

needs: 如果想跳过阶段顺序直接依赖,可使用needs(更灵活,但需注意依赖关系)

artifacts存放位置注意:

在这里插入图片描述

–password-stdin的含义

echo “ D O C K E R R E G I S T R Y P A S S W O R D " ∣ d o c k e r l o g i n − u " DOCKER_REGISTRY_PASSWORD" | docker login -u " DOCKERREGISTRYPASSWORD"∣dockerloginu"DOCKER_REGISTRY_USER” --password-stdin "$DOCKER_REGISTRY_IP_PORT"中的–password-stdin的含义:从标准输入(stdin)读取密码

docker build -t优化

在这里插入图片描述

–cache-from [镜像地址] 指定“缓存源镜像”,让docker优先使用远程仓库中已有的latest镜像作为构建缓存,避免重复构建相同的层(layer)

-t 构建指定版本,同时更新latest版本

部署服务器相关问题

appuser用户不允许sudo命令

报错信息:sudo docker pull时sudo不被允许

在这里插入图片描述

如果命令,不用sudo就能执行,思考把sudo拿掉:appuser用户添加docker用户组,就可以运行docker命令

usermod -aG docker appuser

如果必须使用sudo命令,注意控制权限范围:配置visudo允许使用sudo命令不配置密码

# 安全边际/etc/sudoers文件(避免语法错误导致权限问题)
visudo# 只需允许特定命令(如docker、sed、docker-compose), 可限制权限范围
appuser ALL=(ALL) NOPASSWD: /user/bin/docker, /usr/bin/sed, /usr/local/bin/docker-compose# 或允许所有命令
appuser ALL=(ALL) NOPASSWD: ALL
sudo dc pull 和dc pull 的区别

dc 命令来源:appuser根目录下存放./.bashrc

在这里插入图片描述

dc pull会在appuser根目录下找,sudo dc pull会在root下找

source ./.bashrc会在当前用户的当前命令行生效,所以sudo dc pull找不到dc命令

在这里插入图片描述

但我尝试在gitlab job中进行下图配置,dc也无法识别,所以我选择用gitlab utils/variable变量而非别名

在这里插入图片描述

问AI得到结论:别名的特性:

  • 只在当前shell会话有效
  • 不会被子进程集成(sudo会创建新的子进程)
  • 只在交互式shell中有效(gitlab job中ssh登录无效)

不使用gitlab utils/variable变量而尝试继续使用别名文件的解决方案(未测试,不保证生效):

将别名定义在/.bash_profile或/.profile中。因为登录shell(如ssh连接)会优先加载/.bash_profile或/.profile

数据卷volumns映射失败

报错信息:

在这里插入图片描述

它没用我的数据卷映射到/data/project/testdata/file

在这里插入图片描述

问题原因:数据卷所有者不是appuser

在这里插入图片描述

解决方案:如上图,调整所有者为appuser // 这部分内容应该在pre-deploy.sh中准备好

为你千千万万遍:pipeline失败次数记录

在这里插入图片描述

http://www.dtcms.com/a/398323.html

相关文章:

  • 声明式事务5
  • 时序数据库选型指南:Apache IoTDB引领数字化转型新时代
  • [Android] apkm安装器 APKMirror Installer v1.10.1
  • spring boot项目使用Torna生成在线接口文档
  • 两学一做教育纪实评价系统网站店铺小程序如何开通
  • 10分钟快速部署PHP+Nginx+MySQL+Redis开发环境
  • 通过智享直播,企业如何实现精准的受众定位与内容分发
  • 【Prompt学习技能树地图】零样本与少样本提示技术实战:原理、应用与调优
  • group_points自定义tensorrt算子编写
  • 20250925问答课题-多标签分类模型
  • 唯品会库存API集成问题与技术方案解析
  • Python开发一个系统
  • 02-教务管理系统(选课管理系统)
  • 从入门到精通:逆向工程完全工具指南与桌面环境搭建
  • 注册网站做推广衡阳网站搜索引擎优化
  • 从零开始学Flink:数据转换的艺术
  • 公司做网站的流程wordpress 放大镜插件
  • 《系统与软件工程 功能规模测量 NESMA方法》(GBT 42588-2023)标准解读
  • React Testing完全指南:Jest、React Testing Library实战
  • python+springboot+django/flask的医院食堂订餐系统 菜单发布 在线订餐 餐品管理与订单统计系统
  • 半导体制造常见检测之拉曼光谱
  • Python 第七节 循环语句for和while使用详解及注意事项
  • 怎么把svg做网站背景谷歌关键词挖掘工具
  • Vue3中的computed属性
  • 7. 临时变量的常量性
  • SNK施努卡有色冶炼自动化解决方案
  • SpringCloud项目阶段七:延迟任务技术选项对比以及接入redis实现延迟队列添加/取消/消费等任务
  • 建站特别慢wordpress网站项目总体设计模板
  • 驱动开发,为什么需要映射?
  • 网站栏目模版确定网站推广目标