使用 FIND 并行运行多个构建作业的问题
我们有一个使用 3 个运行器的本地 gitlab 实例,当我们运行单个构建作业时,它可以正常工作。
遗憾的是,当使用
dind
并行启动 3 个构建作业时,它会失败并出现大量错误:
- 有时无法登录 docker 来拉取缓存的镜像
- 有时登录成功,但构建失败
但在这两种情况下,它都会抱怨证书:
failed to dial gRPC: cannot connect to the Docker daemon. Is 'docker daemon' running on this host?: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "docker:dind CA")
怀疑证书被另一个构建作业崩溃了,我们决定将用于证书的文件夹分开,因此它对于每个运行器都是唯一的,遗憾的是问题仍然存在。
我们还注意到
DOCKER_HOST="tcp://docker:2376"
docker 地址是随机的,并且很多时候返回相同的值,这意味着他们再次使用了相同的资源。
我找到了有关如何手动使用脚本来确保每个作业都连接到其唯一 dind 服务的指南( 此处 ),但由于该文章已有 5 年多历史,我想知道它是否仍然适用,还是我做错了什么。
请分享有关在哪里查看的任何建议或指导。
我也遇到了同样的问题,但在 Jenkins 中通过在 Kubernetes 中运行多个作业。我发现使用 docker-cli 镜像的 dind 镜像每次都会生成证书,因此您必须检查是否没有将
/certs/client
目录从主机挂载到每个构建器,因为在这种情况下,每次运行构建作业时证书都会被覆盖。我也遇到了这样的错误
error during connect: Post "https://localhost:2376/v1.24/auth": x509: certificatesigned by unknown authority (possibly because of "crypto/rsa: validation error" while trying to verify candidates authority certificate "docker:dind CA")
。在 Kubernetes 中,我使用 pod 反亲和性修复了这个问题,防止在同一个节点上安排两个 Jenkins pod:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: jenkins
operator: In
values:
- slave
topologyKey: kubernetes.io/hostname
问题似乎是 dind 破坏了隔离,即在推荐的设置中,所有服务容器都从主机挂载相同的 /cert 文件夹: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#docker-in-docker-with-tls-enabled-in-the-docker-executor
由于 dind 映像似乎也会在启动时重新创建证书,因此在并行运行多个作业时会发生冲突(即在
config.toml
中设置
concurrent = 5
)。
我还没有找到一种方法来确保运行器/服务对共享一个不与其他并发运行器/服务冲突的公共卷对。
就我而言,我在
gitlab-ci.yml
中关闭了 TLS,这解决了该问题。
variables:
# When you use the dind service, you must instruct Docker to talk with
# the daemon started inside of the service. The daemon is available
# with a network connection instead of the default
# /var/run/docker.sock socket. Docker 19.03 does this automatically
# by setting the DOCKER_HOST in
# https://github.com/docker-library/docker/blob/d45051476babc297257df490d22cbd806f1b11e4/19.03/docker-entrypoint.sh#L23-L29
#
# The 'docker' hostname is the alias of the service container as described at
# https://docs.gitlab.com/ee/ci/services/#accessing-the-services.
#
# Specify to Docker where to create the certificates. Docker
# creates them automatically on boot, and creates
# `/certs/client` to share between the service and job
# container, thanks to volume mount from config.toml
# DOCKER_TLS_CERTDIR: "/certs"
DOCKER_TLS_CERTDIR: ""