GitLab平台太单调? 配置Pipeline流水线,装上这个流水线“瀑布灯”!

2023-10-03 15:22:26 浏览数 (3)

博客:https://www.mintimate.cn Mintimate’s Blog,只为与你分享

头图可以少?头图可以少?

在上一篇文章中,我们介绍了如何使用Docker搭建自己的GitLab代码托管平台。

GitLab作为一个成熟的DevOps工具,不仅提供了代码托管的功能,还内置了强大的CI/CD流水线。利用GitLab的CI/CD能力,配置Pipeline来实现自动化的编译、测试和部署。

本文将继续上篇的内容,重点介绍在自己搭建的GitLab平台上,如何配置Pipeline实现CI/CD:

  • 学习Pipeline的基本概念、语法结构;
  • 借助GitLab Runner来执行Pipeline中的job;
  • 配置.gitlab-ci.yml文件,实现代码提交后自动编译、测试、部署到服务器。
Yo~Yo~

其实配置起来,和GitHub Action类似,写法也和Docker Compose也类似。

GitLab Runner

GitLab Runner是GitLab CI/CD的核心组件,用于运行Pipeline中的 jobs。

GitLab CI/CDGitLab CI/CD

它是一个独立的应用程序,需要单独安装。主要有以下几个主要版本:

  1. Shell Runner:最基础的Runner版本,在本地直接调用shell命令来执行jobs。
  2. Docker Runner:使用Docker容器来运行jobs,提供隔离的运行环境。
  3. Kubernetes Runner:在Kubernetes集群上运行jobs,可以动态规模扩展。
  4. Custom Runner:支持使用其他脚本语言如Python、Ruby来自定义Runner,提高扩展性。
  5. Group Runner:顾名思义,是面向特定组织或组内项目统一提供服务的Runner。

工作流程

为什么GitLab使用Pipeline流水线需要另外安装或者激活GitLab Runner呢? 其实GitLab Runner和GitLab基本是相互独立的。官方的流程图:

GitLab Runner和GitLab的联系GitLab Runner和GitLab的联系

简单复述一下:

好的,关于GitLab Runner和GitLab的交互作业流程,可以这样理解:

  1. 开发者提交代码到GitLab,触发一个Pipeline。
  2. GitLab生成一个唯一的token,标识这个job,然后将这个job以及token发送给指定的Runner。
  3. Runner使用这个token来请求增加权限,访问代码仓库和构建工件。
  4. GitLab验证token,授权Runner获得临时访问权限。
  5. Runner利用授权的token,拉取代码,运行scripts,产生构建工件。
  6. 构建完成后,Runner上传工件到GitLab,在工作流中标记job成功或失败。
  7. GitLab使用token验证上传,确保来自授权的Runner,避免非法上传。
  8. GitLab标记job状态为success或failed。

这实现了一个 tokenized 的工作流,保证了job的安全性。

Runner和GitLab之间通过token来验证对方身份和授权,实现了解耦和安全隔离,避免因为Runner的部署影响到GitLab的正常运行。

版本对比

我们参考官方文档:https://docs.gitlab.com/runner/executors/

我这里总结一下:

Runner版本

执行方式

运行环境

优点

缺点

Shell

在本地直接调用shell,如bash、sh和zsh来运行jobs

直接在本地GitLab Runner主机上运行

配置简单,无需其他依赖

无法提供隔离的运行环境,可能影响主机

Docker

在指定的Docker镜像容器内运行jobs

Docker容器内运行,与主机隔离

提供隔离的运行环境,不会影响主机

需要在本地安装Docker环境

Kubernetes

在Kubernetes集群内创建Pod运行jobs

Kubernetes Pod中运行

可以动态扩展,灵活调度资源

需要准备Kubernetes集群环境

Custom

自定义脚本语言,如Python、Ruby来运行jobs

根据脚本语言的运行时

高度灵活,可自定义编程语言

需要自行开发自定义的Runner

Group

针对特定GitLab组织或组项目运行jobs

根据具体组设置

方便组内job共享,统一管理

不如单个项目拥有的Runner灵活

Autoscaling

基于指标自动扩缩容Runner池

不同的云平台

根据负载自动调整Runner数量

需要了解特定云平台API

我们GitLab都是Docker部署的,所以Shell的方式是走不通了;为了方便操作,我这里演示Docker版本。

注册Runner

我们这次演示注册Docker版本的Runner,在服务器上部署Runner之前,我们需要在GitLab的Web控制面板上,创建一个Runner实例,

创建Runner实例创建Runner实例

我的服务器是腾讯云的轻量应用服务器,使用Debian的Linux镜像,所以我这里选择Linux:

选择Linux选择Linux

重要的来了,出现了配置命令:

配置命令配置命令

这个时候,我们需要记下:

  • url: 你GitLab的直连域名/IP;
  • token: 用于权限和交互的token,只会出现一次

假设,url为example.gitlab,com,token为helloworld

Docker部署Runner

在一台安装好Docker的服务器设备上,我们运行GitLab Runner的镜像拉取:

代码语言:shell复制
sudo docker run -d --name gitlab-runner --restart always 
  -v /dockerData/gitlab-runner:/etc/gitlab-runner 
  -v /var/run/docker.sock:/var/run/docker.sock 
  gitlab/gitlab-runner:latest

其中:

  • -v /dockerData/gitlab-runner:/etc/gitlab-runner: 将/dockerData/gitlab-runner目录挂载到容器内的/etc/gitlab-runner,用于保存runner的配置文件
  • -v /var/run/docker.sock:/var/run/docker.sock: 将docker宿主机的docker.sock挂载到容器内,这样runner容器可以访问宿主机的docker服务。
拉取的服务拉取的服务

查看日志,如果报的是找不到配置文件,那么是无需担心的:

找不到配置文件找不到配置文件

接下来,我们需要关联到GitLab平台上。

关联到GitLab

刚刚,我们已经新建了应该runner的注册信息:

url为example.gitlab.com,token为helloworld

这个时候,我们需要在部署了GitLab Runner的Docker服务器上,关联上:

代码语言:txt复制
sudo docker run --rm -it -v /dockerData/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register
关联注册关联注册

依次填写我们的url和token:

填写的结果填写的结果

后面的配置,依次为:别名、executor 类型、默认的镜像。

这里只是默认镜像,.gitlab-ci.yml没有为某个 job 指定镜像,会使用默认镜像。比如这里设置默认的镜像为node:20.8.0-bullseye

到此,我们的Runner就应该关联和注册好了:

Runner注册和关联好Runner注册和关联好

Pipeline流水线

接下来,我们编写一个流水线。这里简单介绍一下,具体可以参考官网:

  • https://docs.gitlab.com/ee/ci/pipelines/

简单概括一下GitLab Pipeline的主要步骤: 在每次的Git Push后,GitLab会读取根目录.gitlab-ci.yml文件进行构建、测试和打包等操作。

gitlab-ci.yaml语法

.gitlab-ci.yml 使用 YAML 格式,主要包含以下几类语法:

全局定义

配置执行器,指令等全局信息。例如:

代码语言:yaml复制
image: ruby:2.6
services:
    - mysql

作业定义

每个作业至少包含 script 定义。例如:

代码语言:yaml复制
build:
    script:
    - gem install bundler
    - bundle install

阶段定义

用 stage 指定作业执行阶段。例如:

代码语言:yaml复制
stages:
    - build
    - test
    - deploy

build_job:
    stage: build 

作业规则

定义作业的规则、环境等信息。例如:

代码语言:yaml复制
rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
environment: production

定义作业间依赖关系。例如:

代码语言:yaml复制
deploy:
    needs: [build, test]

我们可以组合这些语法构建完整的管道配置。

环境变量

有时候,我们需要设置一下服务器的密钥、服务器的IP,直接在.gitlab-ci.yaml内写肯定是不安全的。我们可以设置环境变量:

环境变量环境变量

之后,在编写时候调用:

部署阶段调用部署阶段调用

Demo: 部署VitePress

接下来,我们演示一下如何在Pipeline部署我们的VitePress。是一款不错的文档框架,改天有机会和大家介绍一下:

部署效果部署效果

我们写一个.gitlab-ci.yaml

代码语言:txt复制
image: node:lts-buster

cache:           # 设置缓存
  paths:
    - .vitepress/dist/   # 缓存生成出来的文件目录

stages:          # 全部的步骤
  - build
  - deploy

build-job:       # 打包阶段
  stage: build
  script:
    - echo "设置国内更新源"
    - npm config set registry http://mirrors.cloud.tencent.com/npm/ # 设置国内源
    - echo "执行依赖的更新"
    - npm install
    - echo "执行打包操作"
    - npm run build

deploy-job:      # 部署阶段
  stage: deploy
  script:
    - echo "开始部署……"
    - cp /etc/apt/sources.list /etc/apt/sources.list.bak
    - echo "设置更新源"
    - bash -c 'echo "deb http://mirrors.cloud.tencent.com/debian/ buster main non-free contrib" > /etc/apt/sources.list'
    - bash -c 'echo "deb-src http://mirrors.cloud.tencent.com/debian/ buster main non-free contrib" >> /etc/apt/sources.list' 
    - bash -c 'echo "deb http://mirrors.cloud.tencent.com/debian/ buster-updates main non-free contrib" >> /etc/apt/sources.list'
    - bash -c 'echo "deb-src http://mirrors.cloud.tencent.com/debian/ buster-updates main non-free contrib" >> /etc/apt/sources.list'
    - bash -c 'echo "deb http://mirrors.cloud.tencent.com/debian/ buster-backports main non-free contrib" >> /etc/apt/sources.list'  
    - bash -c 'echo "deb-src http://mirrors.cloud.tencent.com/debian/ buster-backports main non-free contrib" >> /etc/apt/sources.list'
    - bash -c 'echo "deb http://security.debian.org/ buster/updates main contrib non-free" >> /etc/apt/sources.list'
    - bash -c 'echo "deb-src http://security.debian.org/ buster/updates main contrib non-free" >> /etc/apt/sources.list'
    - apt update
    - echo "安装rsync"
    - apt install rsync -y
    - echo "设置SSH无感验证"
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - mkdir -p ~/.ssh
    - eval $(ssh-agent -s)
    - '[[ -f /.dockerenv ]] && echo -e "Host *ntStrictHostKeyChecking nonn" > ~/.ssh/config'
    - echo "SCP传输"
    - ssh-add <(echo "$MINE_SERVER_KEY")
    - rsync -r --delete .vitepress/dist/ ${MINE_SERVER_USER}@${MINE_SERVER_IP}:${MINE_SERER_PATH}
    - echo "应用部署完成"

主要分为两个阶段:

  • 打包阶段: 把VitePress打包为静态文件,用于部署到Nginx服务器上;
  • 部署阶段: 将打包出来的静态文件,使用rsync部署到远程服务器上的Ngixn目录。

打包阶段

  1. 使用node LTS buster系统镜像,提供构建环境
  2. 设置npm国内源,加速下载依赖
  3. 安装依赖
  4. 执行打包构建,生成结果存放在缓存目录
  5. 缓存目录可重复利用,加速后续构建

部署阶段

  1. 替换apt源,安装rsync,提高部署效率
  2. 配置SSH免密登录,实现无感部署
  3. 使用rsync将打包结果同步到服务器
  4. 环境变量隐藏服务器信息,保证安全
  5. 完成结果部署到服务器指定目录

这样通过打包和部署两个阶段,使用脚本自动化执行,利用缓存、环境配置等特性,可以高效、安全的实现持续集成和持续部署。

最后在一次的Git提交后,可以触发打包和部署:

GitLab部署状况GitLab部署状况

其实点进去也可以看到具体的日志:

日志日志

说实话,比较难的是SSH的密钥添加部分,需要在GitLab CI作业中配置 SSH 免密登录,主要步骤:

代码语言:shell复制
# 检查是否存在 ssh-agent,如果不存在则安装 openssh-client
'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'

# 创建 .ssh 目录
mkdir -p ~/.ssh 

# 启动 ssh-agent 管理私钥
eval $(ssh-agent -s)

# 如果在 Docker 中运行,配置 SSH 免密登录
# [[ -f /.dockerenv ]] 检查是否存在 Docker 环境标志文件
# echo -e "Host *ntStrictHostKeyChecking nonn" 
# 向 ~/.ssh/config 写入禁用 StrictHostKeyChecking 的配置 
[[ -f /.dockerenv ]] && echo -e "Host *ntStrictHostKeyChecking nonn" > ~/.ssh/config

实现了无需输入密码就能 SSH 登录到 GitLab Runner 中,从而自动化部署到服务器。

当然,流水线的其他配置还可以很多,有时间,我们单独起一篇文章为大家讲解~~

END

文章演示了如何通过Docker来部署Runner,并与GitLab项目实例关联注册,使其可以运行流水线作业。

一系列操作,让我们的GitLab更加丰富多彩。当然,有机会,教大家更详细的书写Pipeline的流水线脚本,让大家像写GitHub Action一样能熟练地书写脚本。

什么? 你还没用过GitHub Action? 改天有机会,也教大家如何进行书写~~

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

1 人点赞