服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - 编程技术 - Gitlab CI 在 Kubernetes 中的 Docker 缓存

Gitlab CI 在 Kubernetes 中的 Docker 缓存

2021-11-10 23:02k8s技术圈阳明 编程技术

我们运行一个独立的 Docker DIND 容器,构建容器的所有 Docker CLI 都连接到这个一个 Docker 守护进程上,这个时候我们将 Docker layer 层进行持久化,也就起到了缓存的作用了。

Gitlab CI 在 Kubernetes 中的 Docker 缓存

前面我们有文章介绍过如何在 Kubernetes 集群中使用 GitLab CI 来实现 CI/CD,在构建镜像的环节我们基本上都是使用的 Docker On Docker 的模式,这是因为 Kubernetes 集群使用的是 Docker 这种容器运行时,所以我们可以将宿主机的 docker.sock 文件挂载到容器中构建镜像,而最近我们在使用 Kubernetes 1.22.X 版本后将容器运行时更改为了 Containerd,这样节点上没有可用的 Docker 服务了,这个时候就需要更改构建镜像的模式了,当然要实现构建镜像的方式有很多,我们这里还是选择使用 Docker 来构建我们的 Docker 镜像,也就是使用 Docker IN Docker 的模式。

在每次构建镜像的时候,GitLab Runner 都会启动一个包含3个容器的 Pod,其中一个就是运行 Docker 守护进程的 Docker DIND 容器,构建的容器会去连接到运行在同一个 Pod 上的 Docker 守护进程,由于 Pod 中的所有容器共享同一个 network namespace,构建镜像的 Docker CLI 能够通过 localhost 直接连接到 Docker 守护进程进行构建。但是这种方式最大的一个问题是每次构建都是启动一个全新的 Docker 守护进程,造成没有缓存 Docker layer 层,这会显著增加我们的构建时间。

这个问题的解决方法非常简单,与其为每个 Pod 运行一个 Docker DIND 服务的 sidecar 容器,不如让我们运行一个独立的 Docker DIND 容器,构建容器的所有 Docker CLI 都连接到这个一个 Docker 守护进程上,这个时候我们将 Docker layer 层进行持久化,也就起到了缓存的作用了。

首先创建一个 PVC 来存储 Docker 的持久化数据,为了性能考虑,这里我们使用的是一个 Local PV:

  1. apiVersion: storage.k8s.io/v1
  2. kind: StorageClass
  3. metadata:
  4. name: local-volume
  5. provisioner: kubernetes.io/no-provisioner
  6. reclaimPolicy: Delete
  7. volumeBindingMode: WaitForFirstConsumer
  8. ---
  9. apiVersion: v1
  10. kind: PersistentVolume
  11. metadata:
  12. name: docker-pv
  13. spec:
  14. capacity:
  15. storage: 5Gi
  16. accessModes:
  17. - ReadWriteOnce
  18. persistentVolumeReclaimPolicy: Retain
  19. storageClassName: local-volume
  20. local:
  21. path: /mnt/k8s/docker # 数据存储的目录
  22. nodeAffinity:
  23. required:
  24. nodeSelectorTerms:
  25. - matchExpressions:
  26. - key: kubernetes.io/hostname
  27. operator: In
  28. values:
  29. - node1 # 运行在node1节点
  30. ---
  31. apiVersion: v1
  32. kind: PersistentVolumeClaim
  33. metadata:
  34. labels:
  35. app: docker-dind
  36. name: docker-dind-data
  37. namespace: kube-ops
  38. spec:
  39. accessModes:
  40. - ReadWriteOnce
  41. storageClassName: local-volume
  42. resources:
  43. requests:
  44. storage: 5Gi

然后使用 Deployment 部署一个 Docker DIND 服务:

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: docker-dind
  5. namespace: kube-ops
  6. labels:
  7. app: docker-dind
  8. spec:
  9. selector:
  10. matchLabels:
  11. app: docker-dind
  12. template:
  13. metadata:
  14. labels:
  15. app: docker-dind
  16. spec:
  17. containers:
  18. - image: docker:dind
  19. name: docker-dind
  20. args:
  21. - --registry-mirror=https://ot2k4d59.mirror.aliyuncs.com/ # 指定一个镜像加速器地址
  22. env:
  23. - name: DOCKER_DRIVER
  24. value: overlay2
  25. - name: DOCKER_HOST
  26. value: tcp://0.0.0.0:2375
  27. - name: DOCKER_TLS_CERTDIR # 禁用 TLS
  28. value: ""
  29. volumeMounts:
  30. - name: docker-dind-data-vol # 持久化docker根目录
  31. mountPath: /var/lib/docker/
  32. ports:
  33. - name: daemon-port
  34. containerPort: 2375
  35. securityContext:
  36. privileged: true # 需要设置成特权模式
  37. volumes:
  38. - name: docker-dind-data-vol
  39. persistentVolumeClaim:
  40. claimName: docker-dind-data

然后创建一个 Service 以方便构建的 Docker CLI 与其连接:

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: docker-dind
  5. namespace: kube-ops
  6. labels:
  7. app: docker-dind
  8. spec:
  9. ports:
  10. - port: 2375
  11. targetPort: 2375
  12. selector:
  13. app: docker-dind

将 Docker DIND 服务部署完成后,我们就可以在 Gitlab CI 中使用这个守护程序来构建镜像了,如下所示:

  1. tages:
  2. - image
  3. build_image:
  4. stage: image
  5. image: docker:latest
  6. variables:
  7. DOCKER_HOST: tcp://docker-dind:2375 # 通过 service dns 形式连接 docker dind 服务
  8. script:
  9. - docker info
  10. - docker build -t xxxx .
  11. - docker push xxxx
  12. only:
  13. - tags

由于我们缓存了 Docker layer 层,这个时候构建的速度会明显提升。最后随着镜像的大量构建会产生很多镜像数据,我们可以写一个 Cronjob 用来定时清除缓存:

  1. apiVersion: batch/v1
  2. kind: CronJob
  3. metadata:
  4. name: docker-dind-clear-cache
  5. namespace: kube-ops
  6. spec:
  7. schedule: 0 0 * * 0 # 每周清理一次
  8. jobTemplate:
  9. metadata:
  10. labels:
  11. app: docker-dind
  12. name: docker-dind-clear-cache
  13. spec:
  14. template:
  15. spec:
  16. restartPolicy: OnFailure
  17. containers:
  18. - name: clear-cache
  19. image: docker:latest
  20. command:
  21. - docker
  22. - system
  23. - prune
  24. - -af
  25. env:
  26. - name: DOCKER_HOST
  27. value: tcp://docker-dind:2375

原文链接:https://mp.weixin.qq.com/s/rn2xm8YMCW_6JoPljyto9g

延伸 · 阅读

精彩推荐
  • 编程技术用户态 Tcpdump 如何实现抓到内核网络包的?

    用户态 Tcpdump 如何实现抓到内核网络包的?

    在网络包的发送和接收过程中,绝大部分的工作都是在内核态完成的。那么问题来了,我们常用的运行在用户态的程序 tcpdump 是那如何实现抓到内核态的包...

    开发内功修炼11612021-09-08
  • 编程技术从Context源码实现谈React性能优化

    从Context源码实现谈React性能优化

    这篇文章主要介绍Context的实现原理,源码层面掌握React组件的render时机,从而写出高性能的React组件,源码层面了解shouldComponentUpdate、React.memo、PureComponen...

    魔术师卡颂5312020-12-20
  • 编程技术让开发效率倍增的 VS Code 插件

    让开发效率倍增的 VS Code 插件

    今天来分享一些提升开发效率的实用 VS Code 插件!Better Comments 扩展可以帮助我们在代码中创建更人性化的注释,有不同形式和颜色的注释供我们选择。 ...

    前端充电宝7132022-04-21
  • 编程技术简单、好懂的Svelte实现原理

    简单、好懂的Svelte实现原理

    本文会围绕一张流程图和两个Demo讲解,正确的食用方式是用电脑打开本文,跟着流程图、Demo一边看、一边敲、一边学...

    魔术师卡颂4822021-11-10
  • 编程技术2021年值得关注的React PDF 库

    2021年值得关注的React PDF 库

    今天,许多网络应用程序为其用户提供内置的PDF浏览选项。然而,选择一个并不容易,因为它们的功能远远超过显示PDF。在这篇文章中,我将评估5个React的...

    TianTianUp5232021-06-21
  • 编程技术Delphi - Indy idMessage和idSMTP实现邮件的发送

    Delphi - Indy idMessage和idSMTP实现邮件的发送

    这篇文章主要介绍了Delphi - Indy idMessage和idSMTP实现邮件的发送,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...

    JJ_JeremyWu6592020-09-22
  • 编程技术AIOps,SRE工程师手中的利器

    AIOps,SRE工程师手中的利器

    AIOps开始成为一种极为重要的站点可靠性工程工具。它能够高效吸纳观察数据、参与数据以及来自第三方工具的数据,判断系统运行状态并保证其处于最佳...

    至顶网5972021-03-08
  • 编程技术真正聪明的程序员,总有办法不加班

    真正聪明的程序员,总有办法不加班

    工作效率提升了,就可以少加班了,聪明的程序员,总会有一堆可以提升编码效率的工具?当一种工具满足不了工作需求,就去探索新的,今天纬小创就给...

    今日头条12482021-03-04