Pytest + Docker + Gitlab-CICD 搭建流水线

Celery + Pytest+ Docker + Gitlab-CI/CD 搭建流水线

其他博文链接

Ubuntu 搭建Gitlab

Celery-4.1用户指南: Testing with celery

Ubuntu 安装Docker

基于 Python 项目的 GitLab-CI 演示

GitLab集成Docker和K8S完成CI/CD持续集成部署工作

一、GitLab CI/CD介绍

首先一张图说明Gitlab CI的工作流程

Gitlab-CI/CD的工作流程

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/挂起状态

  1. 首先考虑的是不是Runner没有激活
  2. 还可能是tags没有匹配到, Runner注册时是要填写绑定tags的,如果你在YML里面编写Job没有带上tags是不会有自定义Runner来处理。解决方法:给Job加tags。
  3. 最后一种可能:你连续注册了多个Runner,这些Runner冲突了,或者是新注册的Runner和旧Runner使用了同一个token,这时候的解决方法如下:
    先删掉本地其他旧的Runner。
    sudo gitlab-runner unregister --all-runners
    然后重置Token,并使用更新后的Token重新注册一个Runner。

版权声明:本文为abbyinfo原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。