开发者问题收集

使用 FIND 并行运行多个构建作业的问题

2023-02-09
798

我们有一个使用 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 年多历史,我想知道它是否仍然适用,还是我做错了什么。

请分享有关在哪里查看的任何建议或指导。

2个回答

我也遇到了同样的问题,但在 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
vladelleus
2023-09-26

问题似乎是 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: ""
ootwch
2023-12-29