本文来自:
李发富 极狐(GitLab) 高级技术支持工程师

家喻户晓,CI/CD 能够让咱们更快、更高质量、更简略的交付软件。而事实中,你是否常常面临以下难点,导致 CI/CD 并没有真正施展其劣势:

从网络装置我的项目依赖耗时长
前后端我的项目未分离
导致编译、部署及测试效率低?
随着我的项目增多,多任务 Pipeline 运行慢?
不必要 Job 运行占用了资源和工夫?

针对以上问题,我总结了六大招式,心愿帮忙大家在应用极狐GitLab 时候晋升 CI/CD 效率,供参考。

应用 cache

在运行我的项目编译时,可能会装置我的项目依赖,如果每次都从网络装置,会节约很多工夫。这时候能够应用 cache 性能提供缓存,缩小依赖安装时间。

【前提】runner 开启 cache 性能:Advanced configuration | GitLab

python cache

示例:

image: python:3.9.7stages:  - testvariables:  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"  cache:  paths:    - .cache/pip/  # 已我的项目 id 辨别 cache,如果不辨别,就是全局 cache  key: $CI_PROJECT_IDjob1:  stage: test  script:    - pip install ansible==2.9.2

or

image: python:3.9.7stages:  - testcache:  paths:    - pip-cache  # 已我的项目 id 辨别 cache,如果不辨别,就是全局 cache  key: $CI_PROJECT_IDbefore_script:  - export PIP_CACHE_DIR="pip-cache"  - mkdir -p pip-cachejob1:  stage: test  script:    - pip install ansible==2.9.2

nodejs cache

示例:

variables:  NPM_CONFIG_CACHE: npm_cache  NPM_CONFIG_REGISTRY: https://registry.npm.taobao.orgdefault:  cache:    paths:      - ${NPM_CONFIG_CACHE}build:  stage: build  image: node:14-alpine  script:    - node -v    - npm -v    - npm ci    - npm run build  artifacts:    name: "build-package"    paths:      - dist    expire_in: 1 day

jave maven cache

build:  image: maven:3.8.5-jdk-11  stage: build  variables:    MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"    MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"  cache:    paths:      - .m2/repository/      - target/    key: $CI_PROJECT_ID  script:    - mvn package    - ls -l target/*

应用 needs 扭转多阶段执行程序

默认状况下,同一阶段作业并行运行,不同阶段按程序执行,存在排队等待时间,以致编译、测试工夫被拉长。

咱们能够应用 needs 参数扭转多阶段执行程序:Pipeline 定义阶段 Stages,如果全局未定 Stages,则按程序运行 Build,Test,Deplo。Job 如果未设置 Stage,默认是 Test 阶段。

示例:

stages:  - build  - test  - deploybuild fontend:  stage: build  script:    - echo 'build fontend job'build backend:  stage: build  script:    - echo 'build backend job'test fontend:  stage: test  script:    - echo 'test fontend job'  needs: ["build fontend"]test backend:  stage: test  script:    - echo 'test backend job'  needs: ["build backend"]    deploy fontend:  stage: deploy  script:    - echo 'deploy fontend job'  needs: ["test fontend"]deploy backend:  stage: deploy  script:    - echo 'deploy backend job'  needs: ["test backend"]

应用 needs 参数后:对于前端工作,build fontend 实现后会立刻执行下一个阶段的 test fontend,不论 build backend 是否实现。后端的 build backend 工作一样相似。

Web 界面中还能够查看 needs 依赖关系:

应用 rules 缩小不必要 Job 运行

很多人会把前后端一起打包和部署,但其实只有前端代码有变动,针对后端的 Job 测试是多余的。因而,能够应用 rules 规定跳过某些不必要 Job。

示例:

stages:  - build  - testbuild job:  stage: build  script:    - echo 'build job'test job:  stage: test  script:     - echo 'test job'  rules:    - changes:        - backend/*
  • 当 backend 中有变动时运行 test job;
  • 也能够应用相似的 only: changes 实现。

装置依赖应用国内源

因为国内网络的起因,如果应用默认源的话,装置依赖可能会很慢甚至失败,这时候能够设置国内或者代理解决。

nodejs

npm install --registry=https://registry.npm.taobao.org

or

yarn config set registry 'https://registry.npm.taobao.org'

python

pip install --trusted-host mirrors.aliyun.com -i https://mirrors.aliyun.com/pypi/simple -r requirements.txt

ruby

gem sources --remove https://rubygems.org/gem sources -a https://gems.ruby-china.comgem sources –l

golang

go env -w GOPROXY=https://goproxy.cn,direct

设置 GOPRIVATE 来跳过公有库,比方罕用的 GitLab,两头应用逗号分隔:

go env -w GOPRIVATE=*.gitlab.com

Docker 镜像优化

Docker 过大,会造成镜像拉取工夫过长,影响 CD 速度。

Docker 镜像体积优化

尽量优化减小 Docker 镜像大小。

1. 应用Alpine Linux

Alpine Linux 是一个基于 BusyBox 和 Musl Libc 的 Linux 发行版,其最大的劣势就是小。一个纯的根底 Alpine Docker 镜像在压缩后仅有 2.67MB。并且不少 Docker 官网镜像都有 Alpine 版本,比方:python:3.9.12-alpine3.15、ruby:2.7.5-alpine3.15 等。

2. 装置起码依赖

如果不是必须,不要装置 vi,wget,curl,ping 等工具。

3. 合并 RUN 指令到一行

Dockerfile 中尽量合并多条指令:

...RUN echo 1 \  && echo 2...

4. 多阶段构建

在 Docker 17.05 版本当前,新引入了 multi-stage builds 这一概念,这将会极大地减小镜像大小。

简略来说,multi-stage builds 反对咱们将 Docker 镜像的编译分成多个 “阶段”。比方常见的软件编译的状况,咱们能够将编译阶段独自提出来,软件编译实现后间接将二进制文件拷贝到一个新的根底镜像中,这样做最大的益处就是,第二个镜像不再蕴含任何编译阶段应用的两头依赖,干干净净明明白白。

具体应用办法:Dockerfile 多阶段构建 - leffss - 博客园 (cnblogs.com) 
更多 Dockerfile 最佳实际参考:Best practices for writing Dockerfiles | Docker Documentation

应用自建 Docker Hub 镜像仓库

默认状况下,Docker 应用 Docker Hub 的镜像,网络传输较慢。能够搭建本地 Hub 仓库:装置 harbor v2.3.4 - leffss - 博客园 (cnblogs.com) ,减速镜像的 pull 与 push。

Pipeline 中应用本地仓库:

stages:  - buildvariables:  PROJECTNAME: "test"  DOCKERHUB: "hub.leffss.com"  DOCKERHUBPROJECT: "library"before_script:  - docker login ${DOCKERHUB} -u "${DOCKERHUBUSER}" -p "${DOCKERHUBPASS}"after_script:  - docker logout ${DOCKERHUB}job1:  stage: build  script:    - docker build --cache-from ${DOCKERHUB}/${DOCKERHUBPROJECT}/${PROJECTNAME}:latest -t ${DOCKERHUB}/${DOCKERHUBPROJECT}/${PROJECTNAME}:${CI_COMMIT_TAG} -t ${DOCKERHUB}/${DOCKERHUBPROJECT}/${PROJECTNAME}:latest .    - docker images    - docker push ${DOCKERHUB}/${DOCKERHUBPROJECT}/${PROJECTNAME}:${CI_COMMIT_TAG}    - docker push ${DOCKERHUB}/${DOCKERHUBPROJECT}/${PROJECTNAME}:latest

在有了本地 Hub 仓库的状况下,还能够依据本章节【Docker 镜像体积优化】的准则自行打包一些我的项目编译须要用到的根底镜像,把我的项目须要用到的根底依赖包或者工具提前打包进去,这样又能够缩小 Pipeline 装置依赖的工夫。

优化 runner

当我的项目较多时,CI/CD 工作也会增多,这时候运行 Pipeline 效率会升高。极狐GitLab 提供共享 runner 给所有我的项目 CI/CD 工作应用,这里分享两种优化形式:

应用 Tag 标记 runner

在 runner 编辑页面设置 Tags,并且不勾选 Run untagged jobs,这时候此 runner 只运行应用 Tag 选择器的 Job,这样优化 runner 占用率.

示例:

stages:  - testjob1:  stage: test  script:     - echo 'job1'  tag:    - "docker"

为我的项目注册专用 runner

点击具体我的项目,而后在 settings -> CI/CD - Expand 中查看我的项目 runner 注册用的地址和 token,而后再依照官网文档注册 runner:Registering runners | GitLab 即可。

注册实现后,这个 runner 只会运行以后我的项目的 Job。

应用 k8s 运行 runner

将 runner 装置到 Kubernetes 集群中来,并且应用 Kubernetes  executor,这样子运行 Job 时能够动静的申请集群资源,能够无效防止资源有余的状况。

装置形式参考:应用 K3s 来装置和运行极狐GitLab runner_哔哩哔哩_bilibili 或者 GitLab Runner Helm Chart | GitLab 。

监控 runner 资源占用

通过集成的 gitlab runner prometheus metrics 监控 runner 状态,确保 runner 的失常稳固运行。

以上,就是我基于实际经验总结的 CI/CD 效率优化六大招式,欢送大家一起交换!