CI/CD笔记-gitLab之ci/cdhtml
1、概念普及python
1、概念普及
1. CI/CDmysql
CI(continuous integration):持续集成,即在代码构建过程当中持续地进行代码的集成、构建、以及自动化测试等;有了 CI 工具,咱们能够在代码提交的过程当中经过单元测试等尽早地发现引入的错误。 CD(continuous Deployment):持续交付,在代码构建完毕后,能够方便地将新版本部署上线,这样有利于快速迭代并交付产品。
2. gitlab CI/CDlinux
GitLab CI/CD(后简称 GitLab CI)是一套基于 GitLab 的 CI/CD 系统,可让开发人员经过 .gitlab-ci.yml 在项目中配置 CI/CD 流程,在提交后,系统能够自动/手动地执行任务,完成 CI/CD 操做。并且,它的配置很是简单,CI Runner 由 Go 语言编写,最终打包成单文件,因此只须要一个 Runner 程序、以及一个用于运行 jobs 的执行平台(如裸机+SSH,Docker 或 Kubernetes 等,我推荐用 Docker,由于搭建至关容易)便可运行一套完整的 CI/CD 系统。
3. gitlab-Jobgit
Job 为任务,是 GitLab CI 系统中能够独立控制并运行的最小单位。在提交代码后,开发者能够针对特定的 commit完成一个或多个 job,从而进行 CI/CD 操做。 做业就是运行器(Runner)要执行的指令集合,Job 能够被关联到一个 Stage。当一个 Stage 执行的时候,与其关联的全部 Job 都会被执行。在有足够运行器的前提下,同一阶段的全部做业会并发执行。做业状态与阶段状态是同样的,实际上,阶段的状态就是继承自做业的。 做业必须包含script(由Runner执行的shell脚本),随着项目愈来愈大,Job 愈来愈多,Job 中包含的重复逻辑可能会让配置文件臃肿不堪。.gitlab-ci.yml 中提供了 before_script 和 after_script 两个全局配置项。这两个配置项在全部 Job 的 script 执行前和执行后调用。 Job 的执行过程当中每每会产生一些数据,默认状况下 GitLab Runner 会保存 Job 生成的这些数据,而后在下一个 Job 执行以前(甚至不局限于当次 CI/CD)将这些数据恢复。这样即使是不一样的 Job 运行在不一样的 Runner 上,它也能看到彼今生成的数据。
4. gitlab-Pipelineweb
Pipeline 即流水线,能够像流水线同样执行多个 Job. 在代码提交或 被合并时,GitLab 能够在最新生成的 commit上创建一个 pipeline,在同一个 pipeline 上产生的多个任务中,所用到的代码版本是一致的。
5. gitlab-Stage
通常的流水线一般会分为几段;在 pipeline中,能够将多个任务划分在多个阶段中,只有当前一阶段的全部任务都执行成功后,下一阶段的任务才可被执行。
注:若是某一阶段的任务均被设定为“容许失败”,那这个阶段的任务执行状况,不会影响到下一阶段的执行。sql
CI Pipelinedocker
上图中,整条流水线从左向右依次执行,每一列均为一个阶段,而列中的每一个可操控元素均为任务。左边两个阶段的任务是自动执行的任务,在commit提交后便可自动开始运行,执行成功或失败后,能够点击任务右边的按钮重试;而右边两个是手动触发任务,须要人工点击右边的“播放”按钮来手动运行。shell
6. 什么是.gitlab-ci.yml文件
官方文档:https://docs.gitlab.com/ee/ci/yaml/README.html#parameter-detailsjson
GitLab CI使用YAML文件(.gitlab-ci.yml)来管理项目配置。该文件存放于项目仓库的根目录,而且包含了你的项目如何被编译的描述语句,YAML文件使用一系列约束叙述定义了Job启动时所要作的事情。
Job是.gitlab-ci.yml文件中最基本的元素,由一系列参数定义了任务启动时所要作的事情,用户能够建立任意个任务;每一个任务必须有一个独一无二的名字,但有一些保留keywords不能用于Job名称,image,services,stages,types,before_script,after_script,variables,cache,include。
Job被定义为顶级元素,而且至少包括一条script语句,若是一个 Job 没有显式地关联某个 Stage,则会被默认关联到 test 阶段。
job1: # 关联到bulid阶段 stage: build # 所需执行的脚本 script: - execute-script-for-job1
7. .gitlab-ci.yml文件介绍
variables
用于自定义可用于全部job的全局变量,这个关键字也能够在每一个job中单独定义,相同变量名时,优先级是先job再全局
variables: SERVICE_ENV: R1 APPNAME: AI-DATA
default
全局默认值,即为了简便不用重复设置每一个任务中相同关键字对应的相同的值,如每一个job应用相同的镜像名,就能够在default下配置,则若是job中没有配置本身的镜像则使用default中的,default中支持如下关键字
image,services,before_script,after_script,tags,cache,artifacts,retry,timeout,interruptible
default: image: base-python2:v1 stages: - build - deploy build-app-job: stage: build script: "run build script file" only: - branches build-mysql-job: stage: build image: mysql6:v1 script: "do something" stages
用于定义全部做业job可使用的全局阶段,gitlab-ci.yml容许定义多个阶段,stages元素的顺序定义了做业执行的顺序。Job关联的stage名相同时,该多个Job将并行执行(在拥有足够Runner状况下),下一个阶段的Job将会在前一个阶段的job都完成的状况下执行。
若是没有定义stages,那么默认包含build,test,deploy 三个stage,stage中并不能直接配置任何具体的执行逻辑,具体的执行逻辑应该在Job中配置。
stages: - build - test - deploy
stage
为每一个任务Job指定其属于那个阶段,其依赖stages中定义好的阶段
script
script 是一系列经过Runner来执行的shell脚本,也能够直接执行shell命令
有些时候,script命令须要被单引号或者双引号所包裹。举个例子,命令中包涵冒号的时候,该命令须要被引号所包裹,这样YAML解析器才知道该命令语句不是“key: value”语法的一部分。当命令中包涵如下字符时须要注意打引号:: { } [ ] , & * #? | - < > = ! % @
test-job1: # 每一个任务必须指定阶段(stage)和对应要作的任务(script) stage: test script: - ehco "执行对应写好的须要runner执行的命令或脚本,多个命令这样写" - uname -a - echo "hello,$GITLAB_USER_LOGIN" test-job2: stage: test script: echo "若是只是一条命令能够直接在这个后面写"
这两个关键字定义运行时,docker的镜像名和须要用到的已经存在运行的服务名,前提是注册runner时选择的是docker而不是shell
build-job: image:access-web:v1 services: # 定义构建access-web镜像时能够访问服务名 - mysql:v1
before_script 和after_script
定义一些在全部任务Job执行前或以后须要执行的命令,每一个任务Job中若是定义了,就执行本身的,全局的就不会执行
# 定义全局before_script default: before_script: - global before script # 覆盖全局的before_script test-job1: before_script: - 执行本身的在本任务执行前要作的事 script: - uname -a after_script: - 执行命令等等
only 和 except
更多参考官方文档:https://docs.gitlab.com/ee/ci/yaml/README.html#onlyexcept-basic
若是任务job没有指定only关键字,默认是全部的分支push或标签建立时当作触发条件,except默认为空即不过滤
only和except都是定义job何时会被触发建立,only和except可使用正则,能够指定仓库地址,能够同时用;
only定义了job是以分支仍是标签提交时被触发;
except定义了job在某个分支或标签提交时不会被执行;
only和except可使用的一些关键字:
job1: stage: test script: echo "do something" only: # 仅以开头以issue-的引用的时候被触发,而全部分支均被过跳过 # 经过正则默认区分大小写,若是想不区分须要后面加i,即/^issue-.*$/i - /^issue-.*$/ except: - branches job2: stage: test script: echo "do something" only: # 仅为分支标记了标签、或者经过api请求、或者定时任务时才会运行次job - tags - triggers - schedules job3: stage: test script: echo "do anything" only: # 指定仓库全部的分支都会被触发 - branches@仓库地址 except: # master分支不会被触发本任务 - master@仓库地址 # 以release开头的命名的也不会被触发 - /^release/.*$/@仓库地址
tags
用于指定注册的某个runner来运行任务,注册runner时有为每一个runner设置标签,这里就是匹配那个的
job: tags: # 若是指定多个标签,那么那些标签必须某个running都有关联才会调用 - python-runner
allow_failure
容许某个任务失败不影响CI的其余任务执行结果,默认是false即不容许失败
job1: stage: test script: "本任务执行成功与否不影响job2的执行" allow_failure: true job2: stage: test script: "本人必须运行成功后面的任务才会被执行"
when
用于实现发生故障或发生故障时运行的做业
when支持的值以下:
on_success(默认) 早期全部的做业都成功或者视为成功的all_failure:true
on_failure仅在早期至少一个做业失败时运行
always 不管早期做业结果如何都执行
manual 手动执行
delayed 延迟指定的时间再执行,gitlab11.14中新增
job: stage: deploy script: - make deploy when:manual
gitlab预设变量
官方文档:https://docs.gitlab.com/ee/ci/variables/predefined_variables.html#predefined-environment-variables-reference
用于获取gitlab用于ci/cd 预设的一些环境变量如获取分支名CI_COMMIT_BRANCH
docker build: script: docker build -t my-image:$CI_COMMIT_REF_SLUG . rules: - if: '$CI_COMMIT_BRANCH == "master"' when: delayed start_in: '3 hours' allow_failure: true
gitlab-runner安装在服务部署的机器上,其自动根据你在gitlab-ci.yml中规定的触发条件如某个分支提交后执行,其首先会自动从gitlab仓库上拉取仓库代码到服务器本地,而后根据gitlab-ci文件定义的job执行,如打包文件构建镜像,而后部署服务【多台能够经过创建docker swarm集群的模式,在本地部署一个,会自动分布到多台】
2、实验环境
系统:centos8.0_x64
gitlab: 192.168.0.152:8888
docker-swarm集群:192.168.0.150【master】192.168.0.153【slave】
docker仓库:192.168.0.150:5000
3、前期准备
搭建gitlab:请参考:https://mp.weixin.qq.com/s/amWWG34BXoTAumy1p4SnvA
搭建docker集群请参考:https://mp.weixin.qq.com/s/cIkPOnna9u0h1AMbz4aOjw
搭建docker私有仓库请参考:https://mp.weixin.qq.com/s/4KI3fqyJFv5yJI_H_HK0RA
# 1. 直接重docker-hub上拉取centos系统 docker pull centos # 2. 构建一个容器 docker run --name=genPython -it centos /bin/bash # 3. 换yum仓库 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak && curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-8.repo && yum clean all && yum makecache # 4. 安装python3 yum -y install python38 # 5. 查看Python安装 whereis python python3 --version pip3 list # 6. 退出容器,将刚才改变的容器生成新的镜像`docker commit 容器id 仓库/新的镜像名:标签` docker commit 0426a83fc666 192.168.0.150:5000/python3:v1 # 7. 推送到私有仓库,须要先配置本地docker配置文件指定仓库地址 vim /etc/docker/daemon.json { "registry-mirrors": ["192.168.0.150:5000"], # 加速的地址 "insecure-registries" : ["192.168.0.150:5000"] } systemctl daemon-reload && systemctl restart docker docker push 192.168.0.150:5000/python3:v1 注为了方便也将其推送到dockerhub上 docker login docker tag 192.168.0.150:5000/python3:v1 addmoney2018/python3:v1 docker push addmoney2018/python3:v1
四. 配置Runner
1. 安装runner
官方文档:https://docs.gitlab.com/runner/install/
### 在192.168.0.150上,只有安装在集群管理节点上,才能经过docker swarm集群部署到多台上 # 下载二进制文件并写入文件gitlab-runner # Linux x86-64 curl -L --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64" # 授予其执行权限 chmod +x /usr/local/bin/gitlab-runner # 建立一个GitLab CI用户 useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash # 修改gitlab-runner密码 echo "gitlab-runner" | passwd --stdin gitlab-runner # 安装并做为服务运行 gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner # 将服务添加到开启启动 chkconfig gitlab-runner on # 启动 gitlab-runner start # 通过实践发现runner执行docker命令时会报权限不够,所以须要加权 usermod -aG docker gitlab-runner # 测试下 sudo -u gitlab-runner -H docker info 注:以后想修改上面指定的用户或工做目录 修改这个文件便可:/etc/systemd/system/gitlab-runner.service
2. 获取runner须要的gitlab地址及gitlab之CI的token
登录gitlab---选择对应的仓库---选择仓库的setting---选择CI/CD---选择Runners的expand----复制下图中地址和token
注意:
若是选择的runner执行模式是docker,则runner中的job会在指定的基础镜像中执行,所以须要你指定的镜像里能够执行ci文件中定义的命令,如docker build
若是选择的runner执行模式是shell,即在runner服务安装的物理机执行,所以你若是不是经过容器安装runner,而想经过runner打镜像,建议经过shell模式
# 执行以下命令 gitlab-runner register [root@gitlab bin]# gitlab-runner register Runtime platform arch=amd64 os=linux pid=10254 revision=943fc252 version=13.7.0 Running in system-mode. # 输入gitlab实例地址 Enter the GitLab instance URL (for example, https://gitlab.com/): http://192.168.0.152:8888/ # 输入runner的token Enter the registration token: WecGC7zY9otwQgdss7yZ # 输入这个runner的描述 Enter a description for the runner: [gitlab.example.com]: try to run a python service # 输入这个runner的标签,每一个标签用逗号隔开【用于区分不一样类型的 Runner,使不一样阶段的 job 在不一样的 Runner 中运行】 Enter tags for the runner (comma-separated): Python3-runner Registering runner... succeeded runner=WecGC7zY # 选择执行runner的方式 Enter an executor: docker-ssh, parallels, docker-ssh+machine, custom, shell, ssh, virtualbox, docker+machine, kubernetes, docker: docker Enter the default Docker image (for example, ruby:2.6): # 指定基础镜像,注意本地你须要先下载docker镜像,将其推进到你得私有仓库,由于你本地daemon.json配置了本地仓库,runner就是在指定得镜像中构建得 192.168.0.150:5000/docker Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! # 重启下runner gitlab-runner restart # 注 若是想更改上面得配置 vi /etc/gitlab-runner/config.toml
4. gitlab上查看是否注册成功
5. 写一个测试项目及相关的Dockerfile与gitlabci.yml文件
test-runner
docker-compose.yml
FROM 192.168.0.150:5000/python3:v1 # 建立容器中的服务根目录 RUN mkdir -p /app/code/ # 拷贝代码到容器中 COPY . /app/code/test-gitlab01 # 指定工做目录 WORKDIR /app/code/test-gitlab01 # 安装依赖 RUN pip3 install --no-cache-dir -r /app/code/test-gitlab01/requirements.txt -i http://pypi.douban.com/simple --trusted-host pypi.douban.com # 映射端口 EXPOSE 8100 # 启动 CMD ["python3","main.py"]
variables: SERVICE_ENV: R1 IMAGE_NAME: python-test-app:v3 DOCKER_FILE_PATH: . DOCKER_HUB: 192.168.0.150:5000/ stages: - build - test - deploy build-app: stage: build only: # 仅当什么事件发生就触发本任务: 发生推送 - master script: - echo "开始执行构建app的阶段" - echo "环境为:$SERVICE_ENV" - echo "runner为shell模式就在物理机上执行下面得命令" - echo "当前位置:$(pwd),当前的主机名:$(hostname)" - echo "当前目录下的文件:$(ls -lrt)" - docker build -t $IMAGE_NAME $DOCKER_FILE_PATH - docker tag $IMAGE_NAME $DOCKER_HUB$IMAGE_NAME - docker push $DOCKER_HUB$IMAGE_NAME - echo "构建镜像成功!" tags: # 指定某个runner执行本任务 - python-shell-runner test-app: stage: test only: - master script: - echo "开始测试阶段" - echo "查看镜像是否推送到仓库:$(curl http://192.168.0.150:5000/v2/_catalog)" - export TEST_PORT=$RANDOM - docker run -d -p $TEST_PORT:8100 $DOCKER_HUB$IMAGE_NAME - sleep 3 - curl http://192.168.0.150:$TEST_PORT - echo "测试阶段完成!" tags: - python-shell-runner deploy-app: stage: deploy only: - master script: - echo "开始部署服务阶段" - echo "当前位置:$(pwd)" - echo "当前目录下的文件:$(ls -lrt)" - docker stack deploy -c docker-compose.yml web - sleep 3 - docker service ls - docker service ps web_python-test-web - curl http://192.168.0.150:8100 - echo "部署阶段完成" tags: - python-shell-runner
version: '3' services: python-test-web: image: 192.168.0.150:5000/python-test-app:v3 ports: - 8100:8100 restart: always deploy: replicas: 2 restart_policy: condition: on-failure volumes: - /etc/localtime:/etc/localtime networks: - python-net networks: python-net:
# _*_ coding:utf-8 _*_ # DevVersion: Python3.6.8 # Date: 2021-01-01 18:10 # Author: Sun # PyCharm|main from flask import Flask app = Flask(__name__) @app.route("/") def index(): return {"message": "happy new year 2021"} if __name__ == '__main__': app.run("0.0.0.0", "8100")
click==7.1.2
Flask==1.1.2
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
Werkzeug==1.0.1
     **5、卸载gitlab-runner**
gitlab-runner stop
chkconfig gitlab-runner off
gitlab-runner uninstall
rm -rf /etc/gitlab-runner/rm -rf /usr/local/bin/gitlab-runneruserdel -r gitlab-runner