gitlab runner使用docker executor处理缓存 ,工件,构建docker镜像

首先启动一个gitlab runner服务,并注册一个docker executor,这是比较简单的,此处暂不赘述

本文主要讲述使用docker executor,如何处理缓存,工件,构建docker镜像的问题,如何尽可能在保证安全的前提下加速编译过程。

以java项目为例,配置ci/cd文件

stages:
  - package
  - build

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"

mvn:package:
  stage: package
  tags:
    - gr1
  image: maven:3.6.3-jdk-8
  #缓存mvn库
  cache:
    key: mvn_repo
    paths:
      - .m2/repository
  artifacts:
    paths:
    - target/multi-renter.jar
  script:
    - mvn package

缓存:

cache:
key:mvn_repo
paths:
- .m2/repository
这是指定一个缓存,在当前的gr1这个runner中的任何job中有效,缓存会保存在主机的另一个docker container(dockers ps -a 可以看到 gitlab runner helper),并最终挂在到主机的一个位置。为什么不直接挂载到主机上呢,那样效率不是更高吗?当然,直接挂载到主机上,效率更高,但是却让当前的job和主机的某个目录耦合,试想,如果其他人的job也往主机挂载,并且恰好挂载到和你一样的目录了呢?另外,不同的主机类型,比如windows和linux,目录格式不一样,因此你的配置要根据主机os类型而变化。而且你还要关注gitlab-runner服务可读写的目录权限问题。wow,真是太复杂了。但是挂载到另一个容器,gitlab-runner帮你解决了所有的问题。只是牺牲了一点点效率。无非就是增加了压缩和解压缓存的时间。缓存在所属的gitlab-runner(上述例子中所属为:gr1)后续的所有pipeline可见。

工件:

artifacts:
paths:
- target/multi-renter.jar
工件和缓存类似,只不过其往往在一个pipeline中生存工件的后续job中可见。在web ui中也可见,但是在另一个pipeline中不可见。比如,我在mvn:package:这个job中编译了一个jar文件,在编译的下一个stage中想把这个jar复制到docker镜像,就应该用工件去传递这个jar,而不是使用缓存。

构建docker image

构建docker镜像,官方给了几种方式
对于docker executor,每次都是启动一个新的container构建,新的container是一个非常clear的环境,因此上次构建使用到的base image和构建的缓存都无法使用,所以阅读下述方式时,重点关注如何加速构建速度,解决方式是否复杂以及带来的问题。

kaniko

kaniko可以在不使用docker特权模式下构建docker镜像,并且可以利用container registry加速构建。主要过程如下

  1. kaniko在--cache-dir目录下查找base image缓存(即docker file中的from命令)这里需要注意,如果这里没有命中,kaniko会去download image,但是不会写入缓存,因此,即使你通过卷持久化了这个目录,下次执行依然不会命中。因此我们需要提前将镜像缓存到--cache-dir,kanico关于cache base image的讲解。我使用了一下warmer,发现按照官网提供的命令,不加-f,如果缓存没命中,shell返回0,但实际报错了,加上-v debug可以看到,如果缓存命中了,什么都不发生。加上-f,则每次都会强制pull镜像覆盖cache,消耗一定时间。这可能是一个bug。我们要做的就是,先使用warmer下载base image,然后把缓存的目录挂载到kanico容器中使用(配置/srv/gitlab-runner/config/config.toml文件)。我只是想编译而已,为何要我解决如此麻烦的缓存问题?另外注意一下,kanico的executor和warmer都有相同名称的参数,所以这里需要自己体会下其含义,不要搞混了。
  2. kaniko对run命令进行缓存,因此执行run命令前,会到指定的远程registry查看有没有已经缓存的层,命中的话就使用缓存
  3. kaniko将构建好的image提交到registry
    这是个好东西,我简单试用了一下,官方给的示例多是k8s中用,如果不在k8s中用,如何缓存base image是一个问题,我暂时还没有在官方找到一个比较好的方式。
    kaniko拉取base image方式和docker pull不一样,测试使用warmer缓存java:8和使用docker pull java:8一个耗时不到一分钟,一个约3分钟。
docker:build:
  stage: build
  tags:
    - gr1
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]
  script:
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG --insecure

docker in docker

这种方式需要以特权方式执行docker,带来不安全的因素。同时,构建也是非常慢的。因此也需要使用缓存去加速构建。原理是:docker先从registry拉取上次构建的镜像。然后构建的时候指定--cache-from=<last-image>,也就是说以上次的镜像作为缓存构建。构建完毕后,上次镜像,作为下次的构建缓存使用。但是需要注意的是,仍需要花费一部分时间在download image上。如果registry在内网,其实下载和上传都是蛮快的,可以接受。

docker:build:
  stage: build
  tags:
    - gr1
  image: docker:19.03.1
  services:
    - name: docker:19.03.1-dind
      command: ['--insecure-registry=your.registry.com:port']
  variables:
    # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
    #DOCKER_TLS_CERTDIR: "/certs"
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest --build-arg JAR_FILE=target/*.jar .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest

DOCKER_HOST的配置参见docker dockerhub,主要注意一下证书如果配置了,端口号会是2376,否则是2375。
如果使用了不安全的registry,那么需要指定command: ['--insecure-registry=your.registry.com:port']

docker socket binding

由于此方式最终实际上是使用的host的docker daemon,因此,镜像和构建的缓存都是直接使用host中的缓存。当然,有利就有弊,此种方式的缺点有:

  1. 由于共享了主机的docker socket,所以docker命令都是向主机发出的命令,比如docker rm -f $(docker ps -a -q)会把主机上的所有docker容器删除了,包括gitlab-runner容器。
  2. 并发工作可能无法正常执行;创建具有特定名称的容器,则它们可能会相互冲突。
  3. 将源仓库中的文件和目录共享到容器中可能无法正常工作,因为卷安装是在主机而不是构建容器的上下文中完成的。
    你必须时刻注意,你的docker命令是在主机执行的,而不是容器内部。
  4. 需要修改gitlab-runner的配置,挂载主机的docker socket,但是不同的host system的sock文件路径不同,这目前只能在host上配置。
  5. 在k8s中,docker binding脱离了k8s的控制,是非常危险的行为。有的k8s集群通过名称空间做环境隔离,想想一下,开发环境的docker命令删除了线上环境的容器。
如何绑定docker.sock?

修改gitlab-runner服务的配置文件 /srv/gitlab-runner/config/config.toml
volumes = ["/cache","/var/run/docker.sock:/var/run/docker.sock"]

[[runners]]
  name = "gr1"
  url = "http://gitlab.lbl.com"
  token = "mJJWevdY42sJQ84syyN9"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.docker]
    tls_verify = false
    image = "ruby:2.6"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache","/var/run/docker.sock:/var/run/docker.sock"]
    shm_size = 0
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]

ci/cd文件配置

docker:build:
  stage: build
  tags:
    - gr1
  image:
    name: docker:19.03.1
#  before_script:
    #登录到gitlab集成的注册表
#    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest --build-arg JAR_FILE=target/*.jar .
    #推送到gitlab集成的注册表
#    - docker push $CI_REGISTRY_IMAGE:latest

接下来,让我们看看,如果使用k8s执行器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容