CI/CD 构建部署

搭建环境

将gitlab镜像拉到服务器上跑起来。

1】拉取镜像

  • 使用docker拉取gitlab/gitlab-ce的镜像
  • docker拉取nginx镜像
js 复制代码
#查看本地镜像

docker images

#从远程仓库拉取gitlab/gitlab-ce的镜像

docker pull gitlab/gitlab-ce

#从远程仓库拉取nginx镜像

docker pull nginx
shell 复制代码
docker images



#REPOSITORY         TAG       IMAGE ID       CREATED      SIZE

#node               latest    8f1b7f0dfc2f   5 days ago   907MB

#nginx              latest    08b152afcfae   5 days ago   133MB

#gitlab/gitlab-ce   latest    75d591b81fd7   6 days ago   2.23GB

2】运行镜像到容器

bash 复制代码
sudo docker run --detach --hostname gitlab.rayhomie.icu --publish 443:443 --publish 80:80 --publish 222:22 --name gitlab --restart always --volume /srv/gitlab/config:/etc/gitlab --volume /srv/gitlab/logs:/var/log/gitlab --volume /srv/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce:latest

3】查看当前运行的容器

shell 复制代码
docker container ls -a



#CONTAINER ID   IMAGE                     COMMAND             CREATED         STATUS    PORTS     NAMES

#df62d4c44c25   gitlab/gitlab-ce:latest   "/assets/wrapper"   3 minutes ago   Created             gitlab

4】查看容器名为gitlab的日志

bash 复制代码
#打印当前运行日志

docker logs gitlab



#实时打印日志

docker logs -f gitlab

5】成功运行gitlab

此时我们就成功地将gitlab镜像跑在了本地的docker容器中,并且可以通过地址来访问gitlab界面。

GitLab CI/CD基础知识

简单理解:但我们把本地代码推到gitlab远程仓库时,会触发一个流程,这个流程会执行一系列的任务,这些任务组装起来就是一个pipeline(流水线)。

  • pipeline(流水线)
  • stage(阶段)
  • job(任务)

如上图可以看出这几个概念之间的关系是:

  • 一个流水线 包含多个阶段
  • 一个阶段 包含多个任务

gitlab只是一个代码仓库(代码管理工具平台),它是不会去跑这些流水线上的任务。所以又要引出一个概念gitlab runner(一个安装在服务器上的软件),所有的我们定义的cicd的操作都是在gitlab runner上去跑。(gitlab runner就是给cicd提供一个环境)

  • .gitlab-ci.yml文件:用来定义流水线、阶段、任务。

docker安装GitLab Runner

1】拉取runner镜像

在docker远程仓库拉取gitlab/gitlab-runner镜像到本地:

bash 复制代码
#拉取镜像到本地

docker pull gitlab/gitlab-runner

2】运行镜像到容器

bash 复制代码
sudo docker run -d --name gitlab-runner --restart always -v /srv/gitlab-runner/config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest

3】注册gitlab runner

要使gitlab runner和gitlab产生联系,需要找到我们gitlab的Token

然后在gitlab runner运行的docker容器中用这个Token去注册一下,脚本具体如下:

arduino 复制代码
docker run --rm -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register --non-interactive --executor "docker" --docker-image alpine:latest --url "http://gitlab.xxxx.com/" --registration-token "vtizNrFzQKFacsSMxsJX" --description "first-register-runner" --tag-list "test-cicd,dockercicd" --run-untagged="true" --locked="false" --access-level="not_protected"
  • url参数是我们gitlab的地址
  • registration-token参数是上图gitlab的token
  • tag-list参数是注册这个runner的标签(后面可用于指定具体哪个runner去执行流水线任务)

.gitlab-ci.yml的编写

基本关键词使用

官方文档

  • script:让gitlab runner去执行shell脚本(所有的任务都需要有script关键字去执行)

  • stages:全局自定义阶段

  • stage :在每个job(任务)中定义 该任务属于哪个stage阶段。stage 是阶段的意思,用于归档一部分的job,按照定义的stage顺序来执行。(默认的stage有.prebuildtestdeploy.post)job执行的顺序不是按照编写的顺序,大体上是按照stage定义的顺序来执行的,注意是大体,也有例外的情况。

  • retry :有可能这个任务会失败,需要有个重试的机制(retry:2指定如果失败重试2次,最多设置为重试2次,也就是最多运行3次)

  • image:指定一个基础Docker镜像作为基础运行环境,经常用到的镜像有node、java、python、docker

  • tagstags 关键词是用于指定Runner,tags的取值范围是在该项目可见的runner tags中

  • only、except:限定当前任务执行的条件(限定分支等)

  • when:when关键词是实现在发生故障或尽管发生故障时仍能运行的作业,比如你要在任务失败后需要出发一个job,或者你需要手动执行任务,或者当你一个任务执行成功后,执行另一个任务。

    • on_success:所有任务执行成功后
    • on_failure:当至少一个任务失败后
    • always:执行作业,而不考虑作业在早期阶段的状态
    • manual:手动执行任务
    • delayed:延迟执行任务
    • never:在rules中不排除执行的任务,在workflow:rules不允许的流水线
  • cache:把一些文件列表保存到缓存中,在各个任务之间互相传递。缓存是将当前工作环境目录中的一些文件,一些文件夹存储起来,用于在各个任务初始化的时候恢复

  • artifacts:成功时附加到作业的文件和目录列表。

  • variables:在.gitlab-ci.yml文件中定义全局变量或者局部变量。(在全局定义即全局变量,在任务中单独定义即局部变量)

  • release:自动化发布包

  • timeout:设置超时时间

  • resource_group:确保一个分支同时只有一个流水线在工作

  • after_script

  • allow_failure

  • before_script

  • coverage

  • dependencies

  • environment

  • extends

  • include

  • interruptible

  • pages

  • parallel

  • rules

  • services

  • trigger

stage

由于buildtest之前所有会先指向job1这个任务,后指向job0任务:(下面👇:)

yaml 复制代码
stages:

  - build

  - test

  - deploy



job 0:

  stage: test

  script: echo 'tets'



job 1:

  stage: build

  script: echo 'build'

下面写了一个默认官方提供stage的案例,含5个jobs属于5个阶段:

官方默认的阶段stages顺序是.prebuildtestdeploy.post

默认的gitlab runner在同一个阶段的任务是按顺序同步执行的(如果需要他每个阶段任务并发执行的话,需要对gitlab runner进行配置)

所以我们任务的执行顺序是:job1 -> job2 -> job4 -> job6 -> job3 -> job5

yaml 复制代码
stages:

  - .pre

  - build

  - test

  - deploy

  - .post



job 1:

  stage: .pre

  script: 

   - echo '.pre job'



job 2:

  stage: build

  script: 

   - echo 'build job'



job 3:

  stage: deploy

  script: 

   - echo 'deploy job'

   

job 4:

  stage: test

  script:

   - echo 'test1 job'

    

job 5:

  stage: .post

  script: 

   - echo '.post job'

   

job 6:

  stage: test

  script:

   - echo 'test2 job'

    

cache

yaml 复制代码
image: 'node:12.6.0'



stages:

  - install

  - build

  - deploy



job_install:

  stage:install

  tags:

    - public-runner001

  script:

    - npm install



job_build:

  stage:build

  tags: 

    - public-runner001

  script:

    - npm run build

  

job_deploy:

  stage:deploy

  tags:

    - public-runner001

  script:

    - echo 'start deploy'

此时跑流水线的话,在build阶段会报错,因为在第一个阶段的任务结束时会将node_modules文件夹删除掉,此时我们就需要使用缓存将node_modules文件夹进行缓存,缓存的文件夹才可以在各个任务中一直被使用。

yml文件中的 "-" 和 ":"之后一定要留下空格

yaml 复制代码
image: 'node:12.6.0'



stages:

  - install

  - build

  - deploy



#缓存node_modules文件夹,并指定唯一标识key

cache:

  key: hello-gitlab-ci

  paths:

    - node_modules

  

job_install:

  stage: install

  tags:

    - public-runner001

  script:

    - npm install



job_build:

  stage: build

  tags: 

    - public-runner001

  script:

    - npm run build

  

job_deploy:

  stage: deploy

  tags:

    - public-runner001

  script:

    - echo 'start deploy'

job_install

job_build

job_deploy

only、when

yaml 复制代码
image: 'node:12.6.0'



stages:

  - install

  - build

  - deploy



#缓存node_modules文件夹,并指定唯一标识key

cache:

  key: hello-gitlab-ci

  paths:

    - node_modules

  

job_install:

  stage: install

  tags:

    - public-runner001

  script:

    - npm install



job_build:

  stage: build

  tags: 

    - public-runner001

  script:

    - npm run build

  only: 

    - release  

  #限定在release分支执行

  

job_deploy:

  stage: deploy

  tags:

    - public-runner001

  script:

    - echo 'start deploy'

  when: manual

  #手动执行任务

docker部署前端项目

任务列表:

  1. 安装node包
  2. 编译
  3. docker镜像部署

使用的关键词有:image,stages,stage,tag,script,cache,docker,build

编写Dockerfile:

sql 复制代码
FROM node:lastest as builder

WORKDIR /app

COPY package.json .

RUN npm install --registry=http://registry.npm.taobao.org

COPY . .

RUN npm run build



FROM nginx:lastest

COPY --from=builder /app/dist /usr/share/nginx/html

编写.gitlab-ci.yml:

yaml 复制代码
#设置node为基础环境镜像

image: node:alpine



#声明阶段

stages: 

  - install

  - lint-code

  - build 

  - deploy



#设置缓存

cache: 

  key: xd-log-platform

  paths: 

    - node_modules



#定义install任务(1.选定阶段、2.runner的tags、3.脚本)

job_install: 

  stage: install

  tags: 

    - dev-runner-001

  script: 

    - npm install



#定义build任务(artifacts是将dist目录存储起来,让其他任务中也能使用到。因为每个任务之间都是隔离的,任务开始时都会重置环境,因此就需要使用cache、artifacts等关键字)

job_build:

  stage: build

  tags: 

    - dev-runner-001

  script: 

    - npm run build 

  artifacts: 

  	paths:

  		- dist/



#定义deploy任务(1.使用docker基础镜像,2.通过dockerfile构建镜像,3.如果环境中有容器则删除该容器并起动运行一个容器,4.且设置为手动执行任务)

job_deploy:

  image: docker

  stage: deploy

  tags: 

    - dev-runner-001

  script: 

    - docker build -t xd_log_platform_images .

    - if [ $(docker ps -aq --filter name=xd_log_platform_container) ];then docker rm -f xd_log_platform_container;

    - docker run -d -p 8001:80 --name xd_log_platform_container xd_log_platform_images

    - echo 'deploy docker image success. visit http://123.23.23.13:8001 '

  when: manual

如果发现报错,可能是gitlab-runner的配置有问题:

bash 复制代码
#进入gitlab-runner的配置目录

cd /srv/gitlab-runner/config

#编辑配置文件

vim config.toml

打开编辑页面后你会发现有很多配置项:

ini 复制代码
#允许当前阶段几个任务并行执行

concurrent = 1 

#代码提交后多久检测一次代码变更,执行gitlab-ci

check_interval = 0



#下面就是该机器上的所有gitlab-runner的配置

[[runners]]

 name = "dev-runner-001"

 url = "xxxxxx"

 token = "xxxxxxxxxx"

 executor = "docker"

 [runners.custom_build_dir]

 [runners.cache]

   [runners.cache.s3]

   [runners.cache.gcs]

   [runners.cache.azure]

 [runners.docker]

 		tls_verify = false

 		image = "alpine:latest"

 		privileged = false

 		disable_entrypoint_overwrite = false

 		oom_kill_disable = false

 		disable_cache = false

 		#映射

 		volumes = ["/cache"]

 		#如果docker执行有问题需要设置一下官方提供的目录映射

 		#volumes = ["/cache","/usr/bin/docker:/usr/bin/docker","/var/run/docker.sock:/var/run/docker.sock"]

 		shm_size = 0

oss部署前端项目

任务列表:

  1. 开题oss
  2. 创建bucket
  3. 创建ack密钥
  4. 使用ossutil
  5. 隐秘信息变量存储
bash 复制代码
#...



job_deploy_oss:

	stage: deploy

  tags: 

    - dev-runner-001

  script: 

    - wget http://gosspublic.alicdn.com/ossutil/1.6.18/ossutil64

    - chomd 755 ossutil64

    - ./ossutil64 config -e ${endPoint} -i ${accessKeyID} -k ${accessKeySecret} -L CH --loglevel debug -c ~/.ossutilconfig

    - ./ossutil64 -c ~/.ossutilconfig cp -r -f dist oss://bucket_name/

    when: manual

指定oss配置文件,递归强制上传dist文件夹下的文件到指定的oss的bucket上。

ci环境变量的使用:

通过这样设置了的环境变量值,就可以在**.gitlab-ci.yml**文件中通过${variables}的形式进行使用变量。

变量的注入与使用

但我们.gitlab.yml文件中有很多地方使用到了相同的值,我们就可以将这些值提取成变量来使用。

三种变量的使用:

  • 在.gitlab-ci.yml中自己定义(variables关键字)
  • pipeline中预定义的变量(提交的commit的哈希值,当前的分支,当前的任务名称等)
  • 自己在项目中设置变量(在可视化页面中进行设置)

变量的类型:

  • k-v变量
  • 文件(签名证书,密钥等)

变量能在哪些关键字中使用:

  • environment:url
  • environment:name
  • resource_group
  • include
  • variables
  • image
  • services:[]
  • services:[]:name
  • cache:key
  • artifacts:name
  • script,before_script,after_script
  • only:variables:[],export:variables:[],rules:if

如何使用:

variables关键字定义及使用

yaml 复制代码
#是一个全局的变量,任何一个任务中都可以使用。

variables: 

	TEST_VAR: "All jobs can use this variable's value"



#在任务中执行打印变量(直接用$符号+变量名即可)

log_var: 

	script:

	  - echo $TEST_VAR



#这是我们刚才使用docker部署前端项目中的任务,我们想要把当前任务中的镜像名称和容器名称定义成局部变量:

job_deploy:

	variables:

		IMAGE_NAME: "xd_log_platform_images"

		CONTAINER_NAME: "xd_log_platform_container"

  image: docker

  stage: deploy

  tags: 

    - dev-runner-001

  script: 

    - docker build -t $IMAGE_NAME .

    - if [ $(docker ps -aq --filter name=$CONTAINER_NAME) ];then docker rm -f $CONTAINER_NAME;

    - docker run -d -p 8001:80 --name $CONTAINER_NAME $IMAGE_NAME

    - echo 'deploy docker image success. visit http://123.23.23.13:8001 '

  when: manual

在可视化页面设置变量并使用

bash 复制代码
#打印我们上面👆设置的NAME变量

log_project_var:

	script:

		- echo $NAME

勾选mask variable时的打印效果如下:

pipeline中预定义的变量

可在官网去查看预定义的变量名,但是我们怎么去查看到这些预定义变量呢?👇

yaml 复制代码
#我们可以使用该任务去导出所有的变量(即打印出来)

get_all_var:

	script: 

		- export



#当前任务就是使用预设变量的例子

test_variable:

  stage: test

  script:

    - echo $CI_JOB_STAGE

流水线的类型以及流水线的触发方式

流水线类型:

  • 基本流水线
  • DAG流水线 (一个项目同时部署多个平台,多条流水线并行执行)
  • 多项目流水线
  • 父子流水线
  • 合并请求流水线

流水线的触发:

  • 推送代码
  • 定时触发
  • url触发
  • 手动触发

定时触发

url触发

流水线最佳实践及调试

使用关键词:

  • interruptible:设置为true,标记该任务可被阻断。
  • release
  • timeout
  • resource_group

涉及功能:

  • 自动取消旧的流水线
  • 创建一个release
  • 设置超时时间
  • 保证安全部署,一个分支只允许有一个部署任务
  • 流水线的调试
  • 设置部署冻结
  • 流水线内置的调试

1】自动取消旧的流水线

在同一个分支,短时间内只对最新的提交进行ci,取消未执行完的流水线。

bash 复制代码
install_job:

	stage: install

	script: 

	  - echo 'start install'

	  - sleep 60

	  - echo  'end install'

	interruptible: true

	  

build_job:

 	stage: build

 	script:

 	  - echo 'start build'

 	  - sleep 120

 	  - echo 'end build'

  interruptible: true  

 	

第一次提交:

紧接着提交第二次:(上一次的ci就被取消了

2】创建一个release

自动创建一个release:(release就是包,流水线中使用release关键词)

  • 使用gitlab提供的镜像进行打release
  • only指定触发任务的方式,当打tag时就会创建release
yaml 复制代码
create_release:

	image: registry.gitlab.com/gitlab-org/release-cli:latest

	stage: build

	script: echo 'start create release'

	release:

		tag_name: $CI_COMMIT_TAG

		description: 'my release'

	only:

		- tags

3】设置超时时间

官方默认的超时时间是一个小时(如果需要自定义的话需要使用timeout关键字)

yaml 复制代码
build:

	script: build.sh

	timeout: 3 hours 30 minutes

	

test: 

	script: rspec

	timeout: 3h 30m

4】限定并发任务

保证安全部署,一个分支只允许有一个部署任务(流水线)

markdown 复制代码
deploy:

	stage: deploy

	environment:

		name: staging

	script: 

		- echo 'start deploy'

		- sleep 120

	resource_group: prod
相关推荐
bug_kada2 小时前
深入理解 JavaScript 可选链操作符
前端·javascript
_AaronWong2 小时前
视频加载Loading指令:基于Element Plus的优雅封装
前端·electron
KallkaGo2 小时前
threejs复刻原神渲染(三)
前端·webgl·three.js
IT_陈寒4 小时前
Vue3性能优化:掌握这5个Composition API技巧让你的应用快30%
前端·人工智能·后端
excel13 小时前
在 Node.js 中用 C++ 插件模拟 JavaScript 原始值包装对象机制
前端
excel16 小时前
应用程序协议注册的原理与示例
前端·后端
我是天龙_绍18 小时前
浏览器指纹,一个挺实用的知识点
前端
theshy18 小时前
前端自制接口抓取工具:一键收集并导出接口列表
前端
wayne21418 小时前
跨平台开发框架全景分析:Flutter、RN、KMM 与腾讯 Kuikly 谁更值得选择?
前端