当前位置: 首页 > 科技观察

GitlabCI在Kubernetes中的Docker缓存

时间:2023-03-14 15:00:47 科技观察

在上一篇文章中,我们介绍了如何在Kubernetes集群中使用GitLabCI来实现CI/CD。我们在构建镜像的时候基本都是使用DockerOnDocker模式。是因为Kubernetes集群使用了Docker的containerruntime,所以我们可以将宿主机的docker.sock文件挂载到容器中来构建镜像,而最近我们把containerruntime改成了Containerd,所以没有Docker服务节点上可用。这时候就需要改变构建镜像的方式了。当然,构建镜像的方法有很多种。这里我们还是选择使用Docker来构建我们的Docker镜像,即使用DockerINDocker模式。每次构建镜像时,GitLabRunner都会启动一个包含3个容器的Pod,其中一个是运行Docker守护进程的DockerDIND容器,构建的容器将连接到运行在同一个Pod上的Docker守护进程。由于Pod中的所有容器共享同一个网络命名空间,因此构建镜像的DockerCLI可以直接通过localhost连接到Dockerdaemon进行构建。但是这种方法最大的问题之一是每次构建都会启动一个全新的Docker守护进程,导致没有缓存的Docker层,这会显着增加我们的构建时间。这个问题的解决方案很简单,不是为每个pod运行一个DockerDIND服务的sidecar容器,而是运行一个单独的DockerDIND容器,所有构建容器的DockerCLI都连接到这个Docker守护进程,在那时候我们持久化了Docker层层,也起到了缓存的作用。首先创建一个PVC来存放Docker的持久化数据。出于性能考虑,这里我们使用本地PV:apiVersion:storage.k8s.io/v1kind:StorageClassmetadata:name:local-volumeprovisioner:kubernetes.io/no-provisionerreclaimPolicy:DeletevolumeBindingMode:WaitForFirstConsumer---apiVersion:v1kind:PersistentVolumemetadata:name:docker-pvspec:capacity:storage:5GiaccessModes:-ReadWriteOncepersistentVolumeReclaimPolicy:RetainstorageClassName:local-volumenodelocal:path:/mnt/k8s/dockerredAffinity#数据存储目录:nodeSelectorTerms:-matchExpressions:-key:kubernetes.io/hostnameoperator:Invalues:-node1#Runonnode1node---apiVersion:v1kind:PersistentVolumeClaimmetadata:labels:app:docker-dindname:docker-dind-datanamespace:kube-opsspec:accessModes:-ReadWriteOncestorageClassName:local-volumesources:requests:storage:5Gi然后使用Deployment部署DockerDIND服务:apiVersion:apps/v1kind:Deploymentmetadata:name:docker-dindnamespace:kube-opslabels:app:docker-dindspec:selector:matchLabels:app:docker-dindtemplate:metadata:labels:app:docker-dindspec:containers:-image:docker:dindname:docker-dindargs:---registry-mirror=https://ot2k4d59.mirror.aliyuncs.com/#指定镜像加速器地址env:-name:DOCKER_DRIVERvalue:overlay2-name:DOCKER_HOSTvalue:tcp://0.0.0.0:2375-name:DOCKER_TLS_CERTDIR#DisableTLSvalue:""volumeMounts:-name:docker-dind-data-vol#持久化docker根目录mountPath:/var/lib/docker/ports:-name:daemon-portcontainerPort:2375securityContext:privileged:true#需要设置为特权模式volumes:-name:docker-dind-data-volpersistentVolumeClaim:claimName:docker-dind-data然后创建一个Service方便构建DockerCLI连接上:apiVersion:v1kind:Servicemetadata:name:docker-dindnamespace:kube-opslabels:app:docker-dindspec:ports:-port:2375targetPort:2375selector:app:docker-dind部署DockerDIND服务后,我们可以在GitlabCI中使用这个守护进程来构建镜像,如下图:tags:-imagebuild_image:stage:imageimage:docker:latestvariables:DOCKER_HOST:tcp://docker-dind:2375#通过servicedns脚本连接dockerdind服务:-dockerinfo-dockerbuild-txxxx.-dockerpushxxxxonly:-tags因为我们缓存了Docker层这时候,施工速度会明显提高。最后,随着大量镜像的构建,会产生大量的镜像数据。我们可以写一个Cronjob定时清理缓存:apiVersion:batch/v1kind:CronJobmetadata:name:docker-dind-clear-cachenamespace:kube-opsspec:schedule:00**0#每周清理一次jobTemplate:metadata:labels:app:docker-dindname:docker-dind-clear-cachespec:template:spec:restartPolicy:OnFailurecontainers:-name:clear-cacheimage:docker:latestcommand:-docker-system-prune--afenv:-name:DOCKER_HOSTvalue:tcp://docker-dind:2375