目标

在搭建一个基础的基于GitLab的CI/CD环境之后,还是有很多小伙伴找我沟通、讨论。其中聊的最多的还是如何和真实的开流程、环境结合起来,加强CI/CD,实现一键自动化的打包、测试、上线的过程。之前我也有写一过一篇怼一下GitFlow的文章,补充了一些传统、基于用户本地部署的场景。其实在很多的软件、起步的互联网公司里,单一部署即:测试-预发-生产这个流程还是大多数。甚至更多的小型的团队采取的是单一master分支的方式。那为了让大家更好的做好相应的CI/CD的工作,我下面将给出相应的脚本来实现基于GitLab Runner + K8S实现的GitFlow CI/CD全流程。

目标流程简介

在GitFlow里,将分支分成了以下几种,包括:

Production 分支(Master 分支)/Develop分支/Feature分支/Release分支

/Hotfix分支等,大家有兴趣可以去看一下参考资料里的定义。

f3cf0706c8ab0b8b0868f31b02bff022.png

在本文的流程里,主要是基于master/develop 分支来实现相应的流程,涉及的是需要集成,并在集成测试环境以及预发环境中交由正式的团队进行测试包。其余的分支的一般是开发人员本地处理,可以考虑不在统一的环境中进行CI/CD流程,通过gitlab-ci的配置文件忽略这部分分支的代码提交。当Feature分支, HotFix分支的代码被merge到相应的develop分支和master分支。如果在真实的开发过程中,由于集成测试的周期太长,的确需要Release分支时。可以定义流程为Release分支设置相应的部署环境。但多数情况下,可以认为Develop分支和Release分支所需要的部署环境是二选一的。即,集成测试在哪个分支上测试,就重点为哪个分支分配全套的部署环境。关于HotFix分支,一般极少开发新的功能,而只是为应急的修复某些特殊的需要立即修复的上线的Bug的而设立的。但测试的过程可以是经过代码Review后先直接merge到master分支,上到预发布环境进行测试。

这样可以将代码分支和部署环境用下面的方式进行管理

Feature分支/HotFix分支:merge到develop 和master后部署,之前在开发人员自己的机器上测试。develop分支/release分支:对应到集成测试环境,完全的自动化构建和部署,Docker里的版本号采用SNAPSHOT-PIPELINE-ID的方式命名。

master分支:对应预发布环境和生产环境,建议至少基于TAG进行生成构建,预发布部署和生产部署三个job。分别为:

  1. 在Build job中,编译以及打出 Docker镜象,Docker镜象的版本号和TAG版本号完全一致。

  2. 在预发布环境在TAG后进行自动部署的job

  3.  手工执行生产环境部署的job

集成测试环境,预发布以及生成可以用三个K8S集群,也可以用一个K8S集群里三个不同的namespace来实现。当然更复杂的情形还包括有多个不同的生产环境,甚至是虚拟机,Docker以及K8S混合的环境。这样需要用不同的Job和GitLabRunner,并对GitLab Runner打上不同的TAG来执行。关于生产部署的另一个话题就是灰度部署,或者是蓝绿部署等等。这些在我后面的示例中也暂时没有涉及。 最后,我用下图来描述一下总体的结构和流程

d62317c53eef8ae499e95a3f84b2a215.png

新功能开发流程

  1. 开发人员在Feature分支中完成本地测试,向Develop分支提出Merge      request或者直接向Develop分支提交代码,触发Develop分支上的Piple      line 包括Build/Test/Deply三个Job

  2. Develop分支Build,打出镜像后,对镜上打上 SNAPSHOT-{$JOBID}的TAG,推到镜像服务器

  3. 跑测试脚本

  4. Deploy stage调用TAG为 INT-DEPLOY的Runner,执行部署脚本。部署脚本从yaml模板中替换出SNAPSHOT的版本号,调用用kubectl 对相应的服务进行升级。(注:我下面的实现是个简易版本,直接用 ssh 互信的方式登录到了K8S的master上执行了kubectl操作)

  5. 执行人工测试工作

  6. 测试完成后,将所有的功能Merge到master分支,同时打上对应的TAG,如2.1.0,TAG的规则由团队决定。

  7. Develop分支Build,打出镜像后,对镜上打上的版本的TAG,推到镜像服务器,触发master上的Pipeline,创建出Build/Test/Pre-Product-Deploy/Product-deploy四个Job

  8. 前三个与develop分支的基本一致,最后一个与其他部署也类似,但是为手工执行。

  9. 在预发环境测试完成后,在gitlab界面上点击执行,就可以在生产环境中部署了

Hotfix流程

  1. 在问题相应的master上的TAG上做分支,在开发环境中完成重现、代码修复工作

  2. 将hotfix merge到master (这一步让我很纠结,可能要视具体的项目情况而定)

  3. 在master上打TAG,后面的步骤与新功能开发的4-9步完全一致。

相关的脚本要点

1. GitLab Runner安装与配置。在之前的文章里已经写过相应的安装配置方法,这里就不再重复了。但要特别说明的是,不同的GitLab也是用tag来区分不同的组的。因此要特别注意本文中所说的tag是指代码库上的 tag还是GitLab Runner的TAG。在本文中,我只有一个GitLab Runner来跑部署,所以暂时没有用TAG来标识不同的GitLab-Runner。在GitLab Runner和K8S之间,我直接采用了ssh互信的方式。

2. 创建相应的 K8S namespace

3. 在相应的k8S namespace下创建相应的ConfigMap,int-application.properties.yaml     对应于测试环境,pre-product   对应于预发环境,production-application.properties.yaml  对应于生产环境。我的程序里没有用数据库之类的,因此没有配置国文件。

4. 在yaml目录下放相应的k8s部署模板文件,其中镜像的版本号字段用来占位。我这里命名为 yaml/hello_world_template.yaml ,这个文件名后续的脚本里都有用到。

apiVersion: v1kind: Podmetadata:  name: garyhelloworld  labels:     app: helloappspec:  containers:    - name: helloappc      image: uhub.ucloud.cn/gary/hello-image:      ports:      - containerPort: 8080        protocol: TCP

5. 修改.gitlab-ci.yaml,《YAML文件内容请在公众号后台留言》

 build部分

buildToDeploy:  stage: build  only:    - tags  script:    - mvn $MAVEN_CLI_OPTS package    - sudo docker build -t uhub.ucloud.cn/gary/hello-image:$CI_COMMIT_TAG .    - sudo docker push uhub.ucloud.cn/gary/hello-image:$CI_COMMIT_TAG

部分Deploy,其余可以依样来写

deployToPre:  only:    - tags  stage: deploy  script:    - cat  yaml/hello_world_template.yaml |sed "s//$CI_COMMIT_TAG/"  > /tmp/hello_world_$CI_COMMIT_TAG.yaml    - scp /tmp/hello_world_$CI_COMMIT_TAG.yaml root@k8s:/tmp/hello_world_$CI_COMMIT_TAG.yaml    - ssh root@k8s kubectl apply -f /tmp/hello_world_$CI_COMMIT_TAG.yaml -n preproduction

结果展示

Develop分支流程

(注:截图并非一次commit所截,前后略有不同)

在develop分支上提交代码,改一行显示 后,Commit,然后push后到看一下gitlab里的pipeline 和jobs

7c2a78fe838b1630eb456fb15d8df929.png

412080a6f202dd909f99b7587fb7e36a.png

看一下docker images list

2f41d256420bebbf81ac142f61ab80da.png

看一下Kubenutes  里的POD

a3a0d1cbb5055f7179c24369a182bc63.png

试一下业务

f48b3c5633b2f6140c9227cddb68aa00.png

Develop流程完成

再看一下Master上的流程

将原来的代码merge到master之后在再给master打个TAG,静等几分钟,可以看到build /test /pre-product都执行了,product的任务等待手工执行

32daaadabffa1cd92b07580577a2bf37.png

ed606351d1b0ba4717e0fea79126ac7a.png

看一下pre-product上的结果 

edfd2f272dc8054db6978ccffa91f72a.png

一切OK。那么在预发布的测试完成后,如果我们执行生产环境的部署,只需要在相应的Job后点一下执行就好了

b4bce82c53caca7a95c99be7d72e9693.png

看一下生产环境

b025eba4e5651e833516f7e876603f4a.png

新版本也OK

总结

这样我们一个极简版本的全流程的CI/CD就OK了,虽然比较简单,但已经覆盖了一个小型团队所需要的场景,也可以支持GitLab flow,可以基本满足日常工作所需。如果大家有问题的话,可以在公众号后台给我留言。

参考资料

1. https://nvie.com/posts/a-successful-git-branching-model/ 英文原文 2010-1-5

2. https://blog.csdn.net/shuzheng520/article/details/84906515 基于gitflow的开发上线流程 

3. https://blog.csdn.net/liubenlong007/article/details/69372348 Git 在团队中的最佳实践--如何正确使用Git Flow

4.  DevOps: 项目多环境配置和健康检查

5. https://blog.csdn.net/master_yao/article/details/78622648 使用gitlab做git flow及代码审查

6. Kubernetes如何加速UCloud内部代码部署的CI/CD流程   UCloud技术

精彩回顾:

《捭阖第一》-2 同气相求,与啵啵一起学《鬼谷子》 之四

OKR简介

在K8S里用JMeter进行性能测试

怼一下GitFlow吧

把SpringBoot的微服务放到K8S里(一)

把SpringBoot的微服务放到K8S里(二) - 微服务,装箱启航!

把SpringBoot的微服务放到K8S里(三) - ZipKin微服务链路跟踪

Hello World, DevOps. 第一部分:DEMO环境安装

Hello World, DevOps 第二部分:代码码起来,CI/CD跑起来

Hello World, DevOps 第三部分:在K8S中启航

GitLab CI/CD 简介

聊聊性能测试(六)- 集群怎么测

IT人员画像 - PM私董会201906次公益场会后知识点回顾

96fbac3a3e096fa0d98e47121951b836.png

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐