Celery + Pytest+ Docker + Gitlab-CI/CD 搭建流水线
其他博文链接
Celery-4.1用户指南: Testing with celery
GitLab集成Docker和K8S完成CI/CD持续集成部署工作
文章目录
一、GitLab CI/CD介绍
首先一张图说明Gitlab CI的工作流程

GitLab CI是 GitLab 提供的持续集成服务,只要在你的仓库根目录 创建一个.gitlab-ci.yml 文件, 并为该项目指派一个Runner,当有合并请求或者 push的时候就会触发build。
这个.gitlab-ci.yml 文件定义GitLab runner要做哪些操作。 默认有3个[stages(阶段)]: build、test、deploy。
当build完成后(返回非零值),你会看到push的 commit或者合并请求前面出现一个绿色的对号。 这个功能很方便的让你检查出来合并请求是否会导致build失败, 免的你去检查代码。
大部分项目用GitLab’s CI服务跑build测试, 开发者会很快得到反馈,知道自己是否写出了BUG。
所以简单的说,要让CI工作可总结为以下几点:
在仓库根目录创建一个名为.gitlab-ci.yml 的文件
为该项目配置一个Runner
完成上面的步骤后,每次push代码到Git仓库, Runner就会自动开始pipeline。
二、配置Runner
详细的使用说明,请阅读官方文档:https://docs.gitlab.com/runner/
安装Gitlab Runner
#在ubuntu server16.04~20.04版本下使用命令即可安装
$ sudo wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
#接着授予可执行权限
$ sudo chmod +x /usr/local/bin/gitlab-runner
#创建一个gitlab-ci用户
$ sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
#安装,并作为服务启动
$ sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
注册Runner(Gitlab管理员权限)
$ sudo gitlab-runner register
需要输入项目的url和Token,查找过程如下
以管理员权限进入仓库->settings->CI/CD,找到Runner Settings这一项,点击Expend,即可在Setup a specific Runner manually这项中找到。如下:

其中的url和Token就是遮起来的内容,只需要在注册过程中填入即可。
命令输入完,点击回车后,会进入注册步骤,共分为以下几步:
- 输入Gitlab实例的URL
可在上图中查看 - 输入要注册的仓库的Token
可在上图中查看 - 输入Runner的描述
这里可以随便输入 - 输入Runner的标签
这里也可以随便输入 - 选择Runner执行器
执行器这里以Docker为示例 - 选择默认镜像(Docker执行器)
默认执行器是当在.gitlab-ci.yml中没有指定镜像(image)是默认的。

这些做完之后就可以启动Runner
$ gitlab-runner start
官方文档说是用gitlab-runner start,有博主说start不生效,用了gitlab-runner run才生效,建议视情况测试。
启动成功后就可以看到,gitlab对应的仓库下(操作:进入仓库->settings->CI/CD,找到Runner Settings这一项,点击Expend,即可在Setup a specific Runner manually)看到注册的runner已经在运行了。

注:如果状态颜色是灰色的表示没有运行成功,也可以选择“Pause”和“Remove Runner”
三、celery+pytest+gitlab-ci 搭建自动化测试
Show me code.
Celery With Pytest.
celery在4.1版本后已经支持Pytest了,并发布了官方文档,更多用法请移步官方文档。
Celery简易Demo
# app.py
from celery import Celery
celery_demo_app = Celery('celery_app',broker='redis://172.18.21.254:6379/1',backend='redis://172.18.21.254:6379/2')
@celery_demo_app.task
def add(x, y):
return x + y
单元测试函数
# test_tasks.py
import pytest
from app import celery_demo_app, add
@pytest.fixture(scope='module')
def celery_app(request):
celery_demo_app.conf.update(CELERY_ALWAYS_EAGER=True)
return celery_demo_app
def test_some_task(celery_app):
assert add.apply_async((1, 2), ).get() == 3
用get()去获得异步任务结果。
这时可以用命令celery -A app worker --loglevel=info启动工作者,然后执行单元测试函数可得到测试结果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wnJ1YxkL-1631586922107)(/home/eden/图片/celery-demo.png)]
创建.gitlab-ci.yml
.gitlab-ci.yml 介绍
.gitlab-ci.yml 用来配置 CI 用你的项目中做哪些操作,这个文件位于仓库的根目录。
当有新内容push到仓库后,GitLab会查找是否有.gitlab-ci.yml文件,如果文件存在, Runners 将会根据该文件的内容开始build 本次commit。
.gitlab-ci.yml 使用YAML语法, 你需要格外注意缩进格式,要用空格来缩进,不能用tabs来缩进。
创建.gitlab-ci.yml
stages:
- test
test:
stage: test
script:
- ls -a
- echo "Building "
- pip3 install -r ./requirements.txt --index-url https://mirrors.aliyun.com/pypi/simple/
- nohup celery worker -A app &
- pip list
- py.test .
tags:
- py3.6
stage翻译为阶段的意思,在构建的过程中,必须要有一个先后顺序。最上面的stages配置意思是,先构建阶段为build的job,然后再构建阶段为test的job,下面build_job和test_job都是job,如果不配置stages,默认为:
stages: - build - test - deploy
这里的tags指明用py3.6标签的gitlab-runner执行test阶段,这里runner用的外壳是docker,默认镜像是python:3.6.
总体来说配置文件的编写较为自由,可以根据实际需要来调整。
推送配置文件
配置好.gitlab-ci.yml文件之后,只要把它加入git后然后推送到远程仓库,CI就会开始自动化集成。这样我们提交代码到GitLab是在每次提交的后面都会有自动测试的结果

点击项目CI/CD -> Pipelines可查看所有的流水线。
如果失败了,也可以进入对应的阶段,查找错误原因。gitlab提供了可视化的界面,非常方便。

这里贴一张测试成功的图:

四、celery+pytest+docker+gitlab-ci/cd 搭建完整的CI/CD流程

我们在.gitlab-ci.yml中增加一个delpoy阶段来进行项目的部署,但是我们为了对master进行保护,必须要创建一个dev或者test分支,只有当分支通过了代码检查和单元测试才能合并到master进行部署,因此我们需要进行如下设置
master分支保护
不允许任何人push

分支合并要求
必须pipeline成功通过之后才能合并

- 创建一个dev分支
- 本地拉取分支
创建私有docker registry(可用其他云代替)
- 使用docker启动
$ docker run -d -v ~/registry:/var/lib/registry -p 5001:5000 --restart=always --name registry registry:2
- 配置/etc/hosts
192.168.1.113 http://registry.example.com/
- 因为我们这个是不安全的registry,需要修改gitlab-ci服务器上面的/etc/docker/daemon.json文件
{ "insecure-registries":["registry.example.com"] }
接着,重启这个docker server【docker-ci 服务器上】
- Test [从dockdr hub中拉取任意一个镜像] :
eden@eden-dell7090:~$ sudo docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
8ec32b265e94: Pull complete
Digest: sha256:b37dd066f59a4961024cf4bed74cae5e68ac26b48807292bd12198afa3ecb778
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
eden@eden-dell7090:~$ sudo docker tag busybox registry.example.com:5001/busybox
[sudo] eden 的密码:
eden@eden-dell7090:~$ sudo docker push registry.example.com:5001/busybox
Using default tag: latest
The push refers to repository [registry.example.com:5001/busybox]
0fd05bf2930d: Pushed
latest: digest: sha256:b862520da7361ea093806d292ce355188ae83f21e8e3b2a3ce4dbdba0a230f83 size: 527

修改.gitlab-ci.yml文件
stages:
- test
- deploy
- release
test:
stage: test
script:
- ls -a
- echo "Building "
- pip3 install -r ./requirements.txt --index-url https://mirrors.aliyun.com/pypi/simple/
- nohup celery worker -A app &
- pip list
- py.test .
tags:
- py3.6
except:
- tags
docker-deploy:
stage: deploy
script:
- docker build -t celery-demo .
- if [ $(docker ps -aq --filter name=celery-demo )]; then docker rm -f celery-demo; fi
- docker run -d --name celery-demo celery-demo
tags:
- demo
only:
- main
docker-images-release:
stage: release
script:
- docker build -t registry.example.com:5001/celery-demo:$CI_COMMIT_TAG .
- docker push registry.example.com:5001/celery-demo:$CI_COMMIT_TAG
tags:
- demo
only:
- tags
在.gitlab-ci.yml中加入release阶段,只需要给测试环境部署没有问题的master分支打上一个版本号tags,就会重新构建镜像,然后推送到私有仓库,最终的一个交付物就是一个稳定的镜像版本,实现了版本发布。
- only 代表只在对应的git分支下运行
五、Gitlab-ci/cd + k8s 自动化部署
本小白还没用过k8s,套用一段网络上的配置
#部署到K8S集群并更新
k8s-deploy:
stage: deploy
tags:
- workbei-ec-engine
only:
- dev
#dependencies: []
script:
- /usr/local/bin/kubectl config use-context 211484640430774345-c5b80bf3faeea4ce3a7ca65809e5601b9
- /usr/local/bin/kubectl set image deployment workbei-ec-engine-deploy workbei-ec-engine=$REPOSITORY:$TAG --namespace=dingtalk-auth
填坑日记
1. gitlab-runner 初始化shell外壳失败(无权限问题)
直接设置gitlab-runner为root权限就可以解决
sudo gitlab-runner uninstall #删除gitlab-runner
gitlab-runner install --working-directory /home/gitlab-runner --user root #安装并设置--user(例如我想设置为root)
sudo service gitlab-runner restart #重启gitlab-runner
ps aux|grep gitlab-runner #再次执行会发现--user的用户名已经更换成root了
2. gitlab-runner 未连接
检查gitlab-runner 的状态
$ systemctl status gitlab-runner启动gitlab-runner
$ systemctl status gitlab-runner
3. gitlab-runner 一直处于pending/挂起状态
- 首先考虑的是不是Runner没有激活
- 还可能是tags没有匹配到, Runner注册时是要填写绑定tags的,如果你在YML里面编写Job没有带上tags是不会有自定义Runner来处理。解决方法:给Job加tags。
- 最后一种可能:你连续注册了多个Runner,这些Runner冲突了,或者是新注册的Runner和旧Runner使用了同一个token,这时候的解决方法如下:
先删掉本地其他旧的Runner。
sudo gitlab-runner unregister --all-runners
然后重置Token,并使用更新后的Token重新注册一个Runner。