Please enable Javascript to view the contents

Jenkins 中的构建产物与缓存

 ·  ☕ 3 分钟

在 CICD 的流程中,需要保存的产物主要有两类,构建产物和缓存。构建产物是最终的执行结果,缓存是为了优化下一次的构建速度。本篇主要描述的是在 Jenkins 中如何对构建产物和缓存进行归档,并结合对象存储进行实践。有部分示例使用的是 在 Kubernetes 上动态创建 Jenkins Slave 进行构建,配置过程可以参考超链接文档。

1. 部署 Minio 及 S3cmd 使用

1.1 部署 Minio

这里使用 docker-compose 编排 Minio 进行部署。

  • 安装 Docker-compose
1
2
3
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
  • 部署 Minio
1
2
3
wget https://raw.githubusercontent.com/minio/minio/master/docs/orchestration/docker-compose/docker-compose.yaml
wget https://raw.githubusercontent.com/minio/minio/master/docs/orchestration/docker-compose/nginx.conf
docker-compose up -d
  • 查看 Minio 页面

选择 9001-9004 任意端口,可以看到 Minio 的页面,使用 minioadmin:minioadmin 账户登陆。

1.2 安装使用 S3cmd

  • 安装
1
pip3 install s3cmd
  • 配置

编辑 ~/.s3cfg 文件,增加如下内容:

host_base = 1.1.1.1:9001
host_bucket = 1.1.1.1:9001
use_https = False

access_key =  minioadmin
secret_key = minioadmin

signature_v2 = False

这里仅用于测试,host_bucket 直接指向部署的服务器。在生产环境中, Bucket 有两种风格:DNS-style 和 Path-style ,可以支持超大规模的分布式存储。

  • 日常操作

列出全部 Bucket

1
2
3
s3cmd ls

2020-06-20 21:07  s3://newbucket

创建 Bucket

1
s3cmd mb s3://newbucketname/

上传文件

1
s3cmd put file.txt s3://newbucketname/

上传文件夹

1
s3cmd put -r backup s3://newbucketname/

列出 Bucket 中的数据

1
s3cmd ls s3://newbucketname/

下载 Bucket 中的文件

1
s3cmd get s3://newbucketname/file.txt

删除 Bucket 中的文件

1
s3cmd del s3://newbucketname/file.txt

删除 Bucket

1
s3cmd rb s3://newbucketname

2. Jenkins 构建归档

2.1 本地归档

新建流水线,内容如下:

pipeline {
  agent {
    kubernetes {
      yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: maven
    image: maven:3.6.3-jdk-8-openj9
    command:
    - cat
    tty: true
"""
   }}
   stages {
      stage('Hello') {
         steps {
            container('maven') {
              sh "echo `date` >> newfile.txt"
            }
         }
      }
   }
   post {
    success {
        archiveArtifacts 'newfile.txt'
    }
  }
}

查看构建日志,可以看到构建产物成功归档。

在当次构建的 UI 中,也可以直接查看到归档文件。

在服务器上,可以查找到归档文件, /var/jenkins_home/jobs/test/builds/43/archive/newfile.txt 。这里 Jenkins 直接将归档的文件保存在 /var/jenkins_home/jobs 文件夹中。

2.2 对象存储归档

在 Jenkins 中大部分对象存储插件面向的是 AWS ,而不是 S3 协议。当然,也有云厂商,如 Qiniu ,提供了 Jenkins 存储插件。这里主要使用的是一款开源的对象存储组件 - Minio 。

  • 在插件市场搜索并安装插件 minio

  • 在 Jenkins 配置中,设置 Minio 相关的配置

  • 新建一条自由风格的流水线

编辑需要执行的 Step ,然后设置构建后需要归档的文件

  • 在构建日志中,可以看到已经归档成功

与 Jenkins 本地归档不同的是,此时的归档在当次构建页面上,不会展示。

  • 在 Minio 中,查看构建归档的结果

3. 缓存

Jenkins 中的缓存主要有两种实践方式,全部流水线共用缓存,每条流水线单独缓存。

由于采用的是 Kubernetes 动态提供的 Agent ,可以将主机上的 Docker Volume 挂载到 Pod ,提供 Node 级别的缓存,这样全部 Pod 就会共用一个缓存目录。这样处理比较简单,但同时共用一个依赖库文件夹会带来潜在的并发问题。下图是相关的配置:

另外一种方式是每条流水线一个缓存,这样够精细,但也增加了存储和执行时间的开销。下面主要介绍如何使用 jobcacher 进行缓存。

  • 搜索并安装插件 jobcacher

  • 查看 jobcacher 插件配置

在 Jenkins 配置中,可以看到 jobcacher 默认使用的是内置的存储,也就是 /var/jenkins_home 下的文件存储。

如下图,下拉框中,还有另外一个 AWS 的 S3 存储可选。这里仅查看,不做设置和测试。

  • 新建流水线

新建流水线,内容如下:

pipeline {
  agent {
    kubernetes {
      yaml """
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: nodejs
    image: node:10-alpine
    command:
    - cat
    tty: true
"""
   }}
   stages {
      stage('checkout') {
         steps {
            git branch: 'master', url: "https://github.com/vuejs/vue"
         }
      }
      stage('install') {
         steps {
            container('nodejs') {
               cache(caches: [[$class: 'ArbitraryFileCache', excludes: '', includes: '**/*', path: 'node_modules']], maxCacheSize: 512) {
                     sh "npm install"
               }
            }
         }
      }
   }
}
  • 首次构建

可以看到 Jenkins 将设置的目录进行了缓存。在 Jenkins 目录 /var/jenkins_home/jobs/test/cache/3ec03583f8eaec275cb2183db769ff47 中,可以看到相关文件。

1
2
3
4
5
ls /var/jenkins_home/jobs/test/cache/3ec03583f8eaec275cb2183db769ff47

abbrev                                                colors                             flow-remove-types-no-whitespace  lodash._baseclone          require-relative
accepts                                               combined-stream                    
...
  • 带缓存构建

缓存归档之后,再次构建时,下载依赖包的耗时会明显减少。从 31 秒 减少到 7 秒,但增加了拉取缓存、解压等操作的时间。

  • 使用对象存储进行缓存

由于大部分插件支持的是 AWS ,如果能直接使用 AWS 也是一个不错的选择。使用其他存储,需要厂商插件的支持,或者 fork AWS 的 Jenkins 插件进行二次开发。

另外一个方向是,提供 s3cmd 命令行,通过 credential 注入秘钥,使用命令行进行上传和下载的管理。下面是简单的流程:

1
2
3
4
5
6
7
8
s3cmd get s3://newbucketname/node_modules.tar.gz
tar xf ${HOME}/node_modules.tar.gz

# install and build

tar cvfz ${HOME}/node_modules.tar.gz node_modules
s3cmd del s3://newbucketname/node_modules.tar.gz
s3cmd put node_modules.tar.gz s3://newbucketname/

4. 参考


微信公众号
作者
微信公众号