在Kubernetes里使用gradle缓存加速编译和docker in docker例子

简介: 1.我们的代码编译需要用到gradle6.2版本,jdk13版本,docker in docker策略2.因为是在CI环境中使用,所以gradle容器会因为流水线的触发,不停的启动和删除。下载jar包会非常消耗时间,我们需要持久化这些gradle缓存。3.挂载这些gradle缓存文件到机器上,可以用ceph集群和NFS,这里我偷懒,先用NFS做,后期资源充足再换成ceph。4.因为我们有并行流水线的可能,所以gradle容器可能一次不止一个,而gradle的caches一次只能被一个进程占用,为了避免多容器占用同一个gradle的caches,我们需要有策略。

需求

1.我们的代码编译需要用到gradle6.2版本,jdk13版本,docker in docker策略

2.因为是在CI环境中使用,所以gradle容器会因为流水线的触发,不停的启动和删除。下载jar包会非常消耗时间,我们需要持久化这些gradle缓存。

3.挂载这些gradle缓存文件到机器上,可以用ceph集群和NFS,这里我偷懒,先用NFS做,后期资源充足再换成ceph。

4.因为我们有并行流水线的可能,所以gradle容器可能一次不止一个,而gradle的caches一次只能被一个进程占用,为了避免多容器占用同一个gradle的caches,我们需要有策略。


已经踏过的坑

1.不能使用apline来制作gradle容器,因为我们的代码里有用到protoc,他会在gradle里安装protoc-3.10.1-linux-x86_64.exe,但是这个程序并不兼容alpine系统,最终会导致报错。报错信息如下图Image-2-4-1024x196.png2.不要使用adoptopenjdk/openjdk13:latest镜像来制作Dockerfile,这个镜像用的jdk版本是jdk13 ea版本。这个ea版本和正常的jdk13有一些细微的差点,这会导致gradle最后编译失败,报错信息如下图Image-31-1024x288.png3.不要直接把gradle缓存目录直接挂载进去,这会导致多任务时阻塞,同时编译失败,如下图Image-32-1024x344.pngImage-33.png


解决过程

1.创建NFS

NFS的搭建是比较简单的。在网上可以很容易搜索到教程,这里需要注意节点机器上也需要安装NFS工具,apt-get install nfs-common,不然会报错,导致K8S在这个节点上创建不了容器,因为挂载volume就失败了

我们在NFS服务器上创建一个目录,用于存放gradle的缓存

vi /etc/exports 添加 /nfsdata/gradle-cache/ *(rw,sync,no_root_squash,no_subtree_check)

2.创建gradle镜像,用于k8s中编译使用

使用Dockerfile,内容如下

FROM gradle:6.2.0-jdk13
# 因为需要docker in docker 所以这里用阿里云一键安装docker
RUN  curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
# 随意创建一个文件
RUN echo "test" > test.log
# 因为使用了私有仓库,所以之间拷贝docker配置文件进去
COPY daemon.json /etc/docker/daemon.json
# 原来的gradle命令是"jshell"这里我们替换掉,避免容器启动后,程序结束就消失
ENTRYPOINT ["tail","-f","test.log"]

docker build -t gradle_lzw .

3.使用这个gradle镜像运行起来,进行一次编译,把gradle caches拷贝出来,放到NFS中

#运行容器 docker run -d -v /var/run/docker.sock:/var/run/docker.sock gradle_lzw

# 进入容器编译代码, docker exec  -it gradle_lzw gradle XXXXX(gradle编译命令)

# 复制出缓存文件 docker cp gradle:/home/gradle/.gradle /home/temp/local/.gradle

关于gradle的缓存可以看这个https://github.com/keeganwitt/docker-gradle

4.把上一步获得的gradle缓存文件上传到NFS服务器上

scp -r root@{有gradle缓存的机器IP}:/home/temp/local/.gradle /nfsdata/gradle-cache/.

5.为了避免多容器并发占用gradle缓存目录,我们只能绕开直接挂载。我们先把缓存文件挂载到一个无用的目录中,然后再从这个目录复制到gradle指定的缓存目录中l

项目流水线配置

Jenkinsfile内容参考:

pipeline {
    agent {
        kubernetes {
            //label使用项目名称,因为不同的项目,build方式是不同的,如果错误的使用了相同的label。Jenkins就不会去读取BuildPod.yaml
            label 'jnlp-项目名称'
            //
            yamlFile 'BuildPod.yaml'
        }
    }
    stages {
        stage('build') {
         //使用gradle容器
     container('gradle'){
     sh '''
         //复制缓存文件
         cp -rf /opt/.gradle/caches /home/gradle/.gradle/caches
         gradle {build 命令}
          '''
          }
    }
  }
}

BuildPod.yaml配置,gradle-cache是缓存目录,dind是docker in docker的必要容器

kind: Pod
metadata:
  labels:
    some-label: some-label-value
spec:
  containers:
  - name: jnlp
    image: jenkins/jnlp-slave
    tty: true
    volumeMounts:
    - name: workspace-volume
      mountPath: /home/jenkins
  - name: gradle
    image: gradle_lzw:latest
    tty: true
    volumeMounts:
    - name: workspace-volume
      mountPath: /home/jenkins
    - name: gradle-cache
      mountPath: /opt/.gradle
    env:
    - name: DOCKER_HOST
      value: tcp://localhost:2375
  - name: dind
    image: docker:18.05-dind
    securityContext:
      privileged: true
    volumeMounts:
      - name: dind-storage
        mountPath: /var/lib/docker
  imagePullSecrets:
    - name: repok8s
  volumes:
  - name: gradle-cache
    nfs:
      server: {NFS服务器IP}
      path: "/nfsdata/gradle-cache/.gradle"
  - name: workspace-volume # pod中有一个volume让其中的多个容器共享
    emptyDir: {}
  - name: dind-storage
    emptyDir: {}
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
8天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
130 77
|
23天前
|
关系型数据库 MySQL Java
【Docker最新版教程】一文带你快速入门Docker常见用法,实现容器编排和自动化部署上线项目
Docker快速入门到项目部署,MySQL部署+Nginx部署+docker自定义镜像+docker网络+DockerCompose项目实战一文搞定!
|
18天前
|
Kubernetes 监控 云计算
Docker与Kubernetes的协同工作
Docker与Kubernetes的协同工作
|
18天前
|
运维 Kubernetes Docker
深入理解容器化技术:Docker与Kubernetes的协同工作
深入理解容器化技术:Docker与Kubernetes的协同工作
41 1
|
26天前
|
运维 Kubernetes Cloud Native
云原生技术入门:Kubernetes和Docker的协同工作
【10月更文挑战第43天】在云计算时代,云原生技术成为推动现代软件部署和运行的关键力量。本篇文章将带你了解云原生的基本概念,重点探讨Kubernetes和Docker如何协同工作以支持容器化应用的生命周期管理。通过实际代码示例,我们将展示如何在Kubernetes集群中部署和管理Docker容器,从而为初学者提供一条清晰的学习路径。
|
18天前
|
Kubernetes 开发者 Docker
Docker与Kubernetes的协同工作
Docker与Kubernetes的协同工作
|
25天前
|
前端开发 Java Docker
使用Docker容器化部署Spring Boot应用程序
使用Docker容器化部署Spring Boot应用程序
|
4月前
|
存储 Kubernetes Linux
在Linux中,如何使用Docker和Kubernetes管理容器?
在Linux中,如何使用Docker和Kubernetes管理容器?
|
6月前
|
运维 Kubernetes 持续交付
Docker与Kubernetes:容器化技术的黄金搭档
【6月更文挑战第10天】Docker和Kubernetes是容器化技术的黄金组合,Docker提供轻量级、可移植的容器引擎,简化应用部署,而Kubernetes作为容器编排系统,实现自动化部署、扩展和管理,确保高可用性和可扩展性。两者的协作使得容器化应用更高效、可靠,共同推动软件开发和运维的创新。
|
Kubernetes 调度 Apache
Docker 编排工具比较:Kubernetes、Docker Swarm 和 Mesos,选择最适合你的容器编排方案
Docker 编排工具比较:Kubernetes、Docker Swarm 和 Mesos,选择最适合你的容器编排方案
377 0