【问题标题】:K8s plugin for Jenkins: Always running two separate containers inside a podJenkins 的 K8s 插件:始终在一个 pod 内运行两个单独的容器
【发布时间】:2019-02-06 03:14:16
【问题描述】:

我创建了一个 Dockerfile(用于节点 JNLP 从站,可与 Kubernetes 的 Jenkins 插件 一起使用)。我是从官方图片jenkinsci/jnlp-slave延伸而来的

FROM jenkinsci/jnlp-slave

USER root


MAINTAINER Aryak Sengupta <aryak.sengupta@hyland.com>
LABEL Description="Image for NodeJS slave"

COPY cert.crt /usr/local/share/ca-certificates
RUN update-ca-certificates

RUN curl -sL https://deb.nodesource.com/setup_8.x | bash \
    && apt-get install -y nodejs

ENTRYPOINT ["jenkins-slave"]

我将这张图片保存在我的 Pod 模板中(在 K8s 插件配置中)。现在,当我尝试在这个 slave 上运行构建时,我发现 Pod 内部生成了两个容器(截图证明了这一点。)。

我的 Pod 模板如下所示:

我的 Kubernetes 配置如下所示:

现在如果我做一个简单的docker ps,我发现有两个容器启动了(为什么?):

现在,在 Jenkins 的 Jenkins Job 配置中,无论我在构建步骤中添加什么,这些步骤都会在第一个容器中执行。

即使我在我的PodTemplate 中使用官方的Node 容器,结果仍然是一样的:

我尝试在我的 Jenkins Job 中打印 Node 版本,输出为 "Node not found" 。另外,为了验证我的臀部,我在我的第二个容器中做了一个docker exec 并尝试打印Node 版本。在这种情况下,它工作得非常好。

这是我的构建步骤的样子:

所以,归结为,我有两个主要问题:

  1. 为什么当我启动 Jenkins 作业时会启动两个(一个用于 JNLP,一个用于所有自定义更改)容器?
  2. 为什么我的作业在第一个未安装 Node 的容器上运行?如何使用此配置实现使用 Node 构建项目的预期行为?

我错过了什么?

附: - 如果问题在某些部分不清楚,请告诉我。

编辑:我知道这可以使用 Pipeline Jenkins 插件来完成,我可以在其中明确提及 container 名称,但我需要从 Jenkins UI 执行此操作。有什么方法可以指定容器名称以及我已经这样做的从属名称:

【问题讨论】:

  • 你的 podTemplate 是什么?
  • @DanielWatrous 我已经用 Pod 模板更新了这个问题。谢谢
  • 我还用 Jenkins Job 输出更新了这个问题。想,我应该让你知道。

标签: docker jenkins kubernetes jenkins-plugins


【解决方案1】:

Jenkins kubernetes 插件将始终在为执行构建而创建的 pod 内创建一个 JNLP 从属容器。 podTemplate 是您定义执行构建所需的其他容器的地方。

在这种情况下,您似乎希望将 Node 容器添加到您的 podTemplate。在您的构建中,您将在命名的 Node 容器内进行构建。

您不应该真正关心 Pod 在哪里运行。您需要做的就是确保添加一个包含所需资源的容器(如本例中的 Node)。您可以向 podTemplate 添加任意数量的容器。我有一些包含 10 个或更多容器的容器,用于 PMD、Maven、curl 等步骤。

我使用带有管道的 Jenkinsfile。

podTemplate(cloud: 'k8s-houston', label: 'api-hire-build', 
  containers: [
    containerTemplate(name: 'maven', image: 'maven:3-jdk-8-alpine', ttyEnabled: true, command: 'cat'),
    containerTemplate(name: 'pmd', image: 'stash.company.com:8443/pmd:pmd-bin-5.5.4', alwaysPullImage: false, ttyEnabled: true, command: 'cat')
  ],
  volumes: [
    persistentVolumeClaim(claimName: 'jenkins-pv-claim', mountPath: '/mvn/.m2nrepo')
  ]
)
{
  node('api-hire-build') {
    stage('Maven compile') {
      container('maven') {
        sh "mvn -Dmaven.repo.local=/mvn/.m2nrepo/repository clean compile"
      }
    }
    stage('PMD SCA (docker)') {
      container('pmd') {
        sh 'run.sh pmd -d "$PWD"/src -f xml -reportfile "$PWD"/target/pmd.xml -failOnViolation false -rulesets java-basic,java-design,java-unusedcode -language java'
        sh 'run.sh pmd -d "$PWD"/src -f html -reportfile "$PWD"/target/pmdreport.html -failOnViolation false -rulesets java-basic,java-design,java-unusedcode -language java'
        sh 'run.sh cpd --files "$PWD"/src --minimum-tokens 100 --failOnViolation false --language java --format xml > "$PWD"/target/duplicate-code.xml'
      }
      archive 'target/duplicate-code.xml'
      step([$class: 'PmdPublisher', pattern: 'target/pmd.xml'])
    }
  }
}

【讨论】:

  • Daniel,我的配置一模一样。唯一的区别是我在没有 Jenkinsfile 的情况下这样做。我要为 Job 进行手动配置。在那里,我提到了我在 Pod 模板中提到的相同标签。
  • 现在我在 PodTemplate 中使用官方的Node 容器,仍然得到相同的结果,即 Node: Not found 错误。
  • 我的直觉是您的 Execute shell 命令必须看起来不同才能使用节点容器。我认为 shell 命令正在默认的 JNLP 容器上运行。
  • 我只是尝试创建一个手动作业,但在 Execute Shell 中看不到任何方法来识别运行命令所需的容器。有什么理由不使用管道脚本吗?
  • 天哪,天哪...我花了一整天的时间看教程,这是我发现的第一个真正的配置...非常感谢...
【解决方案2】:

好的,我已经找到了解决方案。 mhang li的回答是线索,但他没有解释。

基本上,您需要修改在here 找到的官方 Jenkins Slave 映像,并对其进行修改以包含对您的从站所做的更改。本质上,您将 JNLP 和 Slave 容器合并为一个并构建组合图像。

修改格式将如下所示(从链接的 Dockerfile 中获取)

FROM jenkins/slave:3.27-1
MAINTAINER Oleg Nenashev <o.v.nenashev@gmail.com>
LABEL Description="This is a base image, which allows connecting Jenkins agents via JNLP protocols" Vendor="Jenkins project" Version="3.27"

COPY jenkins-slave /usr/local/bin/jenkins-slave

**INCLUDE CODE FOR YOUR SLAVE. Eg install node, java, whatever**

ENTRYPOINT ["jenkins-slave"] # Make sure you include this file as well

现在,将从容器命名为 jnlp(原因 - bug)。所以现在,您将拥有一个生成的容器,它将是您的 JNLP + Slave。总而言之,您的 Kubernetes 插件 Pod 模板将如下所示。请注意我输入的 docker 映像的自定义 url。另外,请确保您不包含 Command To Run,除非您需要。

完成!您的构建现在应该在这个容器中运行,并且应该像您编写 Dockerfile 一样运行!

【讨论】:

    【解决方案3】:

    设置容器模板 -> 名称为 jnlp。 https://issues.jenkins-ci.org/browse/JENKINS-40847

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 2020-01-25
      • 2020-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多