文章目录
gitlab cicd流水线模型
gitlab cicd模型介绍
gitlab cicd流水线是基于gitops,即所有对流水线的配置都是代码的形式,且保存在当前代码仓的根目录。
文件名也是固定的,为 .gitlab-ci.yml 。
实际项目中,针对流水线会定义多个步骤:编译、构建、部署、测试、发布、上线等。
gitlab 流水线实践
配置gitlab runner
将当前已注册的gitlab runner,添加一个标签,便于后期采用标签调用。
简单流水线
- 编写流水线
[root@gitclient myapp]# vim .gitlab-ci.yml
stages:
- test
test_01:
stage: test
script:
- echo "hello world!"
- hostname
tags:
- study-runner
示例释义:
stages:固定语法,定义流水线的步骤,如上定义了test步骤,所定义的名称是可自定义的。
test_01:任务的名称,在gitlab cicd中也叫job。
test_01.stage:在 test_01 的job中,stage是关键字,用于指定当前job属于stages中所定义步骤中的哪个步骤。
script:关键字,用于在runner上执行的命令。
tags:关键字,用来指定在哪个runner上执行,即具体匹配哪个标签的runner。
提示:若指定的runner不存在与当前环境,则流水线会一直处于等待中。
- 提交流水线
将编写好的流水线提交至仓库。
[root@gitclient myapp]# git add .
[root@gitclient myapp]# git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .gitlab-ci.yml
[root@gitclient myapp]# git commit -m "Add git cicd file"
[main 73e8dd7] Add git cicd file
1 file changed, 10 insertions(+)
create mode 100644 .gitlab-ci.yml
[root@gitclient myapp]# git push origin main
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 417 bytes | 417.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To ssh://gitlab.linuxsb.com:32222/mygroup/myapp.git
284a2d9..73e8dd7 main -> main
提交后能在图形界面查看此流水线。
查看作业。
查看详细任务执行。
CICD流水线本质就是自动将代码下载到runner上进行执行。
实际中,流水线涉及多个步骤,每个步骤涉及多个job。
基本类型流水线
多步骤基本流水线示例一
重新定义一个流水线,增加多个不同阶段和步骤,每个步骤增加一个job。
- 编写流水线
[root@gitclient myapp]# git rm .gitlab-ci.yml #删除旧流水线
[root@gitclient myapp]# vim .gitlab-ci.yml
stages:
- compile
- build
- deploy
- test
- release
compile:
stage: compile
script:
- echo -e "\nbegin to compile\n"
tags:
- study-runner
build:
stage: build
script:
- echo -e "\nbegin to build\n"
tags:
- study-runner
deploy:
stage: deploy
script:
- echo -e "\nbegin to deploy\n"
tags:
- study-runner
test:
stage: test
script:
- echo -e "\nbegin to test\n"
tags:
- study-runner
release:
stage: release
script:
- echo -e "\nbegin to release\n"
tags:
- study-runner
- 提交流水线
[root@gitclient myapp]# git add .gitlab-ci.yml
[root@gitclient myapp]# git commit -m "Add second cicd file"
[root@gitclient myapp]# git push origin main
查看流水线。
查看流水线详情。
查看作业任务。
多步骤基本流水线示例二
在基本类型的流水线中,每个阶段可以设置多个任务,比较编译阶段,通常可能涉及多个编译工作,多个开发语言。
则编译、构建和发布都需要分别操作。
[root@gitclient myapp]# git rm .gitlab-ci.yml
[root@gitclient myapp]# vim .gitlab-ci.yml
stages:
- compile
- build
- deploy
- test
- release
compile_java:
stage: compile
script:
- echo -e "\nbegin to compile java\n"
tags:
- study-runner
compile_c:
stage: compile
script:
- echo -e "\nbegin to compile c\n"
- sleep 5
tags:
- study-runner
compile_node:
stage: compile
script:
- echo -e "\nbegin to compile node\n"
tags:
- study-runner
build_java:
stage: build
script:
- echo -e "\nbegin to build java\n"
tags:
- study-runner
build_c:
stage: build
script:
- echo -e "\nbegin to build c\n"
tags:
- study-runner
build_node:
stage: build
script:
- echo -e "\nbegin to build node\n"
tags:
- study-runner
deploy:
stage: deploy
script:
- echo -e "\nbegin to deploy\n"
tags:
- study-runner
test:
stage: test
script:
- echo -e "\nbegin to test\n"
tags:
- study-runner
release_java:
stage: release
script:
- echo -e "\nbegin to release java\n"
tags:
- study-runner
release_c:
stage: release
script:
- echo -e "\nbegin to release c\n"
tags:
- study-runner
release_node:
stage: release
script:
- echo -e "\nbegin to release node\n"
tags:
- study-runner
- 提交流水线
[root@gitclient myapp]# git add .gitlab-ci.yml
[root@gitclient myapp]# git commit -m "Add second cicd file"
[root@gitclient myapp]# git push origin main
查看流水线。
有向图DAG类型流水线
DAG类型流水线:Directed Acyclic Graph Pipline,无环的有向图类型的流水线。
对于基本类型流水线,通常需要某一个阶段完全执行完,才可执行下一阶段,若某一个阶段存在多个任务,则需要较长时间才可完整走完流程。
但通常存在某一个阶段的核心job执行完,就可以执行下一阶段的任务了,其他上一阶段的非核心job可以并行执行,即下一阶段任务只依赖于上一阶段某一个特定job。
对于这种场景,DGA可以满足。
如下流水线,对简单流水线做了如下优化:
- Java语言的项目构建依赖于java语言的编译
- C语言的项目构建依赖于c语言的编译
- Node语言的项目构建依赖于node语言的编译
采用needs关键字对流水线如下优化:
[root@gitclient myapp]# vim .gitlab-ci.yml
stages:
- compile
- build
- deploy
- test
- release
compile_java:
stage: compile
script:
- echo -e "\nbegin to compile java\n"
tags:
- study-runner
compile_c:
stage: compile
script:
- echo -e "\nbegin to compile c\n"
- sleep 10
tags:
- study-runner
compile_node:
stage: compile
script:
- echo -e "\nbegin to compile node\n"
tags:
- study-runner
build_java:
stage: build
needs:
- compile_java
script:
- echo -e "\nbegin to build java\n"
tags:
- study-runner
build_c:
stage: build
needs:
- compile_c
script:
- echo -e "\nbegin to build c\n"
tags:
- study-runner
build_node:
stage: build
needs:
- compile_node
script:
- echo -e "\nbegin to build node\n"
tags:
- study-runner
deploy:
stage: deploy
script:
- echo -e "\nbegin to deploy\n"
tags:
- study-runner
test:
stage: test
script:
- echo -e "\nbegin to test\n"
tags:
- study-runner
release_java:
stage: release
script:
- echo -e "\nbegin to release java\n"
tags:
- study-runner
release_c:
stage: release
script:
- echo -e "\nbegin to release c\n"
tags:
- study-runner
release_node:
stage: release
script:
- echo -e "\nbegin to release node\n"
tags:
- study-runner
- 提交流水线
[root@gitclient myapp]# git add .gitlab-ci.yml
[root@gitclient myapp]# git commit -m "Add four cicd file"
[root@gitclient myapp]# git push origin main
DAG类型的优势在于比基本类型运行效率提升了很高。
父子类型流水线
父子类型流水线适用于将多个子项目放在一个项目代码仓中的场景。
如上示例中,流水线中存在Java、C、Node三种语言的编译、构建、发布以及集成在一起的测试和部署等。
如果直接使用DAG类型的流水线,当Java开发人员在向Java子项目中提交了代码,而此时流水线同样会将C和Node子项目的编译、构建、发布等任务全部行。
最佳的方式是如果只修改了Java子项目,则只执行和Java子项目相关的流水线任务即可。
这样对流水线的执行效率、配置代码的整洁程度等都有较高的提升。
这种场景可以采用父子类型流水线。
如下流水线为一个前端和后端两个子项目位于同一个代码仓库中的示例。
前段子项目的目录为web,后端子项目的目录为back,组建父子类型的流水线,就是在项目的根目录创建流水线发布文件.gitlab-ci.yml作为父流水线的配置,子项目Web和back目录分别创建一个.gitlab-ci.yml作为子流水线的位置。
- back后端流水线
[root@gitclient myapp]# mkdir back
[root@gitclient myapp]# cd back/
[root@gitclient back]# vi .gitlab-ci.yml
stages:
- compile
- build
- deploy
- test
- release
compile_java:
stage: compile
script:
- echo -e "\nbegin to compile java\n"
tags:
- study-runner
build_java:
stage: build
needs:
- compile_java
script:
- echo -e "\nbegin to build java\n"
tags:
- study-runner
deploy:
stage: deploy
script:
- echo -e "\nbegin to deploy\n"
tags:
- study-runner
test:
stage: test
script:
- echo -e "\nbegin to test\n"
tags:
- study-runner
release_java:
stage: release
script:
- echo -e "\nbegin to release java\n"
tags:
- study-runner
- Web前端流水线
[root@gitclient back]# cd ..
[root@gitclient myapp]# mkdir web
[root@gitclient myapp]# cd web/
[root@gitclient web]# vi .gitlab-ci.yml
stages:
- compile
- build
- deploy
- test
- release
compile_node:
stage: compile
script:
- echo -e "\nbegin to compile node\n"
tags:
- study-runner
build_node:
stage: build
needs:
- compile_node
script:
- echo -e "\nbegin to build node\n"
tags:
- study-runner
deploy:
stage: deploy
script:
- echo -e "\nbegin to deploy\n"
tags:
- study-runner
test:
stage: test
script:
- echo -e "\nbegin to test\n"
tags:
- study-runner
release_node:
stage: release
script:
- echo -e "\nbegin to release node\n"
tags:
- study-runner
- 父流水线
back和web的子流水线不会自动触发,需要项目根目录下的.gitlab-ci.yml文件进行触发。
在父流水线中调用子流水线需要使用关键字 trigger 和 include 。
[root@gitclient back]# cd ..
[root@gitclient myapp]# vim .gitlab-ci.yml
stages:
- trigger
trigger_back:
stage: trigger
trigger:
include: back/.gitlab-ci.yml
rules:
- changes:
- back/*
trigger_web:
stage: trigger
trigger:
include: web/.gitlab-ci.yml
rules:
- changes:
- web/*
如上定义了一个节点, trigger ,然后trigger里定义了两个任务,通过include关键字将子目录下的 .gitlab-ci.yml 引用。
rules和changes关键字是用来控制job触发执行的,指定具体的目录。
如上trigger_back的job指定了检测目录为back,即只有当back目录中的文件或代码发生了变化,back目录中的子流水线才会执行。
- 提交流水线
首次提交后,由于前后端都是第一次生成,因此会自动执行完所有任务。
[root@gitclient myapp]# git status
[root@gitclient myapp]# git add .
[root@gitclient myapp]# git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: .gitlab-ci.yml
new file: back/.gitlab-ci.yml
new file: web/.gitlab-ci.yml
[root@gitclient myapp]# git commit -m "Add fifth cicd file"
[root@gitclient myapp]# git push origin main
- 修改测试
仅修改web目录下的文件,然后再次提交验证是否只执行web子项目的流水线。
[root@gitclient web]# vim .gitlab-ci.yml #修改任意内容,如sleep
stages:
- compile
- build
- deploy
- test
- release
compile_node:
stage: compile
script:
- echo -e "\nbegin to compile node\n"
tags:
- study-runner
build_node:
stage: build
needs:
- compile_node
script:
- echo -e "\nbegin to build node\n"
- sleep 3
tags:
- study-runner
deploy:
stage: deploy
script:
- echo -e "\nbegin to deploy\n"
tags:
- study-runner
test:
stage: test
script:
- echo -e "\nbegin to test\n"
tags:
- study-runner
release_node:
stage: release
script:
- echo -e "\nbegin to release node\n"
tags:
- study-runner
- 提交流水线
[root@gitclient web]# cd ..
[root@gitclient myapp]# git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: web/.gitlab-ci.yml
no changes added to commit (use "git add" and/or "git commit -a")
[root@gitclient myapp]# git add .
[root@gitclient myapp]# git commit -m "Edit web file"
[root@gitclient myapp]# git push origin main
如上所示,仅对前端进行了编译、构建和发布。
多项目类型流水线
随着团队的扩大,项目的不断扩展,产品代码必然会存在多个。
此时存在一个场景,需要一条流水线将所有的代码仓的流水线串联起来,即一条完整的流水线涉及多个项目,一个项目的流水线执行完才触发下一个项目的流水线。
如下流水线,产品和开发的不断完善,对于测试团队已经开发了自动化测试脚本,且需要该测试脚本放在独立的mytests仓库,而不放在产品代码仓库里,产品代码库仍为myapp。
此时需要的多项目流水线是myapp产品代码仓库的流水线执行完成后,触发测试脚本代码仓mytests的流水线,从而实现自动化脚本的自动运行测试,并且测试脚本和产品代码分开存放。
myapp产品项目作为上游项目,mytests测试项目作为下游项目,下游项目mytests流水线还可以分为基准测试、系统测试、兼容性测试和性能测试。
-
创建mytests项目
图形界面gitlab项目管理里新建mytests项目,创建过程参考myapp创建即可。 -
创建mytests流水线
[root@gitclient ~]# git clone git@gitlab.linuxsb.com:mygroup/mytests.git
[root@gitclient ~]# cd mytests/
[root@gitclient mytests]# vim .gitlab-ci.yml
stages:
- baseline
- system
- compatibility
- performance
baseline_test:
stage: baseline
script:
- echo -e "\nrun baseline test script\n"
tags:
- study-runner
system_test:
stage: system
script:
- echo -e "\nrun system test script\n"
tags:
- study-runner
compatibility_test:
stage: compatibility
script:
- echo -e "\nrun compatibility test script\n"
tags:
- study-runner
performance_test:
stage: performance
script:
- echo -e "\nrun performance test script\n"
tags:
- study-runner
- mytests流水线提交
[root@gitclient mytests]# git add .gitlab-ci.yml
[root@gitclient mytests]# git commit -m "downstream git cicd file"
[root@gitclient mytests]# git push origin main
提示:由于首次所有 .gitlab-ci.yml 文件在远程仓库均不存在时:
直接通过 git push 推送文件会触发流水线,因此如果先推送下游项目的 .gitlab-ci.yml:
下游项目会立即运行自己的流水线,因为 GitLab 检测到 .gitlab-ci.yml 文件的首次提交,会触发一次流水线执行。
此时上游项目尚未推送 .gitlab-ci.yml,因此上游项目没有流水线配置,无法触发下游项目。下游流水线的首次运行是由自身的推送事件触发的,与上游无关。
- myapp产品项目流水线
myapp产品代码流水线设计为编译、构建和部署三个阶段。
三个阶段完成后触发下游mytests的流水线。
关键字downstream阶段中的trigger在指定项目的时候需要把所在组mygroup带上。
[root@gitclient myapp]# git rm -r back/
rm 'back/.gitlab-ci.yml'
[root@gitclient myapp]# git rm -r web/
[root@gitclient myapp]# vim .gitlab-ci.yml
stages:
- compile
- build
- deploy
- trigger
compile:
stage: compile
script:
- echo -e "\nbegin to compile code\n"
tags:
- study-runner
build:
stage: build
script:
- echo -e "\nbegin to build job\n"
tags:
- study-runner
deploy:
stage: deploy
script:
- echo -e "\nbegin to deploy job\n"
tags:
- study-runner
downstream:
stage: trigger
trigger:
project: 'mygroup/mytests'
- 提交流水线
由于下游是基于上游触发的,因此仅提交上游流水线即可。
[root@gitclient myapp]# git add .
[root@gitclient myapp]# git commit -m "upstream git cicd file"
[root@gitclient myapp]# git push origin main
提示:下游项目 mytests 会因为首次推送 .gitlab-ci.yml 自动运行一次流水线。
上游项目 myapp 推送后会运行自己的流水线,并在 trigger 阶段触发下游项目的流水线。
下游项目最终会运行两次流水线:一次由自身推送触发,一次由上游触发。
- 查看流水线
分别查看上游和下游流水线情况。
- 流水线优化
若需要设置下游流水线仅能由上游流水线触发,可在下游流水线中添加if字段。
[root@gitclient ~]# cd /root/mytests/
[root@gitclient mytests]# vi .gitlab-ci.yml
stages:
- baseline
- system
- compatibility
- performance
baseline_test:
stage: baseline
script:
- echo -e "\nrun baseline test script\n"
rules:
- if: '$CI_PIPELINE_SOURCE == "pipeline"' # 仅允许由上游流水线触发
tags:
- study-runner
system_test:
stage: system
script:
- echo -e "\nrun system test script\n"
rules:
- if: '$CI_PIPELINE_SOURCE == "pipeline"'
tags:
- study-runner
compatibility_test:
stage: compatibility
script:
- echo -e "\nrun compatibility test script\n"
rules:
- if: '$CI_PIPELINE_SOURCE == "pipeline"'
tags:
- study-runner
performance_test:
stage: performance
script:
- echo -e "\nrun performance test script\n"
rules:
- if: '$CI_PIPELINE_SOURCE == "pipeline"'
tags:
- study-runner
[root@gitclient mytests]# git add .gitlab-ci.yml
[root@gitclient mytests]# git commit -m "Modify trigger condition"
[root@gitclient mytests]# git push origin main
模拟上游修改,重新推送,测试触发。
[root@gitclient ~]# cd /root/myapp/
[root@gitclient myapp]# vi .gitlab-ci.yml
stages:
- compile
- build
- deploy
- trigger
compile:
stage: compile
script:
- echo -e "\nbegin to compile code\n"
- sleep 2
tags:
- study-runner
build:
stage: build
script:
- echo -e "\nbegin to build job\n"
tags:
- study-runner
deploy:
stage: deploy
script:
- echo -e "\nbegin to deploy job\n"
tags:
- study-runner
downstream:
stage: trigger
trigger:
project: 'mygroup/mytests'
[root@gitclient mytests]# cd /root/myapp/
[root@gitclient myapp]# git add .gitlab-ci.yml
[root@gitclient myapp]# git commit -m "Push upstream git cicd again"
[main 3651ca0] Push upstream git cicd again
1 file changed, 1 insertion(+)
[root@gitclient myapp]# git push origin main
再次查看上下游流水线。
如上优化后,下游流水线即使推送后,也会自动触发。