1

我有一个带有Docker 插件(1.1.9)和一个 docker 云 API的Jenkins 服务器(2.204.1) 。

我与 Jenkins docker 代理(奴隶)一起工作,并且我在容器和主机之间映射了 docker slave 构建工作区,以便能够将 Artifacts 引导到下游作业。

在 Jenkins 配置 - Docker 云详细信息 - 容器设置中:

Volumes /var/lib/jenkins:/var/lib/jenkins

这适用于单个构建,当我运行并发构建时问题就开始了,它们都映射到 Docker 主机上的同一个工作区并相互干扰。使用 docker slaves 并将工作空间映射为卷时,最佳实践是什么?

我不想在构建期间使用 $CustomWorkspace 或应对工件,因为这很难管理和清除。我更喜欢将 @2 添加到第二个并发构建的 Jenkins 常规从属方法,但这不是在 docker slaves 上运行并发构建时的行为

4

1 回答 1

0

一个远程 Jenkins 代理无法知道给定的工作区目录是否正在被同一台机器上运行的另一个代理使用。对于通过卷挂载共享公共目录的基于 docker 的代理也是如此。理想情况下,在同一台机器上工作的所有代理都可以通过某种方式相互交谈,以防止踩到对方的脚趾(例如,工作区中的锁定文件在工作终止时被删除),但目前情况并非如此。

解决方案 #1:独特的构建工作区

如果我们使用 Jenkins 管道,我们可以在每个构建的基础上将一个唯一的子目录附加到工作区目录。该解决方案干净、简单且易于实施。

agent {
    node {
        customWorkspace "${env.BUILD_NUMBER}"
    }
}

参考:https ://www.jenkins.io/doc/book/pipeline/syntax/#agent

解决方案 #2:独特的代理工作区

如果这是不可能或不可取的,另一个可能的解决方案是更改 Jenkins 代理本身的根工作目录,这可以通过向代理的启动命令提供一个附加参数来完成:

-workDir FILE : Declares the working directory of the
                remoting instance (stores cache and logs by
                default)

资源:java -jar agent.jar -help

当在同一台机器上动态启动多个代理时,我们可以将此-workDir值设置为更具唯一性的值,以便为每个代理提供自己的工作目录,从而有效地减少工作空间冲突。像这样的东西应该很好用:

java -classpath agent.jar hudson.remoting.jnlp.Main -headless \
     -workDir /var/lib/jenkins/workspace/$(date +%3N) ...

神奇之处在于$(date +%3N),它将系统时钟纳秒返回到三位数的精度。我们可能希望使用更多或更少的数字,因为有一个折衷:更高的精度将导致更高的工作空间目录的最大数量,但会降低工作空间冲突的风险;较低的精度会产生相反的效果 - 更少的目录,增加的碰撞风险。

此命令的配置方式将根据您的 Jenkins 设置而有所不同。例如,我们在 Jenkins 2.249.3 上使用Docker Swarm 插件(v1.9)。我们的代理命令可在管理 Jenkins >> 管理节点和云 >> 配置云 >> Docker Swarm 云配置 >> Docker 代理模板 >> 命令进行配置。

参考:https ://man7.org/linux/man-pages/man1/date.1.html

于 2021-05-20T19:12:05.070 回答