在企业领域,在容器中运行应用程序已成为一种广为接受的做法,因为 Docker 与 Kubernetes (K8s) 现在提供了一个可扩展、可管理的应用平台。基于容器的方法也适用于 微服务架构,这种架构在过去几年中获得了显著的发展势头。
容器应用平台最重要的优势之一是能够动态启动具有资源限制的隔离容器。让我们来看看这如何改变我们运行持续集成/持续开发 (CI/CD) 任务的方式。
构建和打包应用程序需要一个可以下载源代码、访问依赖项并安装构建工具的环境。作为构建一部分运行单元和组件测试可能会使用本地端口,或者需要第三方应用程序(例如,数据库、消息队列等)正在运行。最后,我们通常有多个预先配置的构建服务器,每个服务器运行特定类型的工作。对于测试,我们维护第三方应用程序的专用实例(或尝试嵌入式运行它们),并避免并行运行可能相互干扰结果的作业。这种 CI/CD 环境的预配置可能很麻烦,并且随着团队在版本和开发平台之间切换,不同作业所需的服务器数量可能会随着时间的推移而发生显着变化。
一旦我们有权访问容器平台(现场或云端),将资源密集型 CI/CD 任务执行转移到动态创建的容器中就变得有意义。在这种情况下,可以为每个作业执行独立启动和配置构建环境。构建期间的测试可以自由地使用这个隔离箱中的可用资源,同时我们还可以在一个仅在此作业生命周期内存在的 sidecar 容器中启动第三方应用程序。
听起来不错…… 让我们看看它在现实生活中是如何工作的。
Red Hat OpenShift v3.7 集群上运行的项目的真实解决方案。OpenShift 是 Kubernetes 的企业就绪版本,因此这些实践也适用于 K8s 集群。要尝试,请下载 Red Hat CDK 并运行 jenkins-ephemeral
或 jenkins-persistent
模板 ,这些模板在 OpenShift 上创建预配置的 Jenkins master。
解决方案概述
在 OpenShift 上在容器中执行 CI/CD 任务(构建、测试等)的解决方案基于 Jenkins 分布式构建,这意味着
- 我们需要一个 Jenkins master;它可以运行在集群内部,但也可以与外部 master 一起工作
- Jenkins 功能/插件像往常一样可用,因此可以使用现有项目
- Jenkins GUI 可用于配置、运行和浏览作业输出
- 如果您喜欢代码,Jenkins Pipeline 也可用
从技术角度来看,运行作业的动态容器是 Jenkins agent 节点。当构建开始时,首先启动一个新节点,并通过 JNLP(端口 5000)向 Jenkins master “报到”。构建排队,直到 agent 节点启动并拾取构建。构建输出被发送回 master——就像使用常规 Jenkins agent 服务器一样——但是 agent 容器在构建完成后关闭。

opensource.com
不同类型的构建(例如,Java、NodeJS、Python 等)需要不同的 agent 节点。这没什么新鲜的——以前可以使用标签来限制哪些 agent 节点应该运行构建。为了定义为每个作业启动的这些 Jenkins agent 容器的配置,我们需要设置以下内容
- 要启动的 Docker 镜像
- 资源限制
- 环境变量
- 挂载的卷
这里的核心组件是 Jenkins Kubernetes 插件。此插件与 K8s 集群(通过使用 ServiceAccount)交互,并启动/停止 agent 节点。可以将多种 agent 类型定义为插件配置下的Kubernetes pod 模板(在项目中通过标签引用它们)。
这些 agent 镜像是开箱即用的(也在 CentOS7 上提供)
- jenkins-slave-base-rhel7:启动连接到 Jenkins master 的 agent 的基础镜像;Java 堆根据容器内存设置
- jenkins-slave-maven-rhel7:用于 Maven 和 Gradle 构建的镜像(扩展自基础镜像)
- jenkins-slave-nodejs-rhel7:带有 NodeJS4 工具的镜像(扩展自基础镜像)
注意:此解决方案与 OpenShift 的 Source-to-Image (S2I) 构建无关,后者也可用于某些 CI/CD 任务。
背景学习材料
关于 OpenShift 上 Jenkins 构建的博客和文档有很多。以下是一些不错的入门资料
- OpenShift Jenkins 镜像文档和 源代码
- OpenShift 的 CI/CD 网络广播
- 外部 Jenkins 集成 剧本
查看它们以了解整体解决方案。在本文中,我们将研究应用这些实践时出现的不同问题。
构建我的应用程序
对于我们的 示例,我们假设一个 Java 项目,其构建步骤如下
- 来源:从 Git 仓库拉取项目源代码
- 使用 Maven 构建:依赖项来自内部仓库(我们使用 Apache Nexus)镜像外部 Maven 仓库
- 部署工件:构建的 JAR 上传到仓库
在 CI/CD 过程中,我们需要与 Git 和 Nexus 交互,因此 Jenkins 作业必须能够访问这些系统。这需要可以在不同位置管理的配置和存储的凭据
- 在 Jenkins 中:我们可以将凭据添加到 Jenkins,Git 插件可以使用这些凭据并将文件添加到项目中(使用容器不会改变任何内容)。
- 在 OpenShift 中:使用 ConfigMap 和 secret 对象,这些对象作为文件或环境变量添加到 Jenkins agent 容器中。
- 在完全自定义的 Docker 镜像中:这些镜像预先配置了运行某种类型作业所需的一切;只需扩展其中一个 agent 镜像即可。
您使用哪种方法是一个品味问题,您的最终解决方案可能是混合使用。下面我们将研究第二种选择,其中配置主要在 OpenShift 中管理。通过设置环境变量和挂载文件,自定义 Maven agent 容器(通过 Kubernetes 插件配置)。
注意:由于 错误,通过 UI 添加环境变量不适用于 Kubernetes 插件 v1.0。可以更新插件,或者(作为一种解决方法)直接编辑 config.xml
并重启 Jenkins。
从 Git 拉取源代码
拉取公共 Git 很简单。对于私有 Git 仓库,需要身份验证,并且客户端还需要信任服务器以进行安全连接。Git 拉取通常可以通过两种协议完成
- HTTPS:使用用户名/密码进行身份验证。服务器的 SSL 证书必须受到作业的信任,如果它是由自定义 CA 签名的,则会很棘手。
git clone https://git.mycompany.com:443/myapplication.git
- SSH:使用私钥进行身份验证。当在
known_hosts
文件中找到其公钥的指纹时,服务器将被信任。
git clone ssh://git@git.mycompany.com:22/myapplication.git
手动完成时,通过 HTTP 使用用户名/密码下载源代码是可以的;对于自动化构建,SSH 更好。
使用 SSH 的 Git
对于 SSH 下载,我们需要确保 agent 容器和 Git 的 SSH 端口之间的 SSH 连接正常工作。首先,我们需要一个私钥-公钥对。要生成一个,请运行
ssh keygen -t rsa -b 2048 -f my-git-ssh -N ''
它在 my-git-ssh
中生成一个私钥(空密码),并在 my-git-ssh.pub
中生成匹配的公钥。将公钥添加到 Git 服务器上的用户(最好是 ServiceAccount);Web UI 通常支持上传。为了使 SSH 连接正常工作,我们需要 agent 容器上的两个文件
- 位于
~/.ssh/id_rsa
的私钥 - 位于
~/.ssh/known_hosts
中的服务器公钥。要获取此公钥,请尝试ssh git.mycompany.com
并接受指纹;这将在known_hosts
文件中创建一个新行。使用它。
将私钥存储为 id_rsa
,将服务器的公钥存储为 OpenShift secret(或 config map)中的 known_hosts
。
apiVersion: v1
kind: Secret
metadata:
name: mygit-ssh
stringData:
id_rsa: |-
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
known_hosts: |-
git.mycompany.com ecdsa-sha2-nistp256 AAA...
然后将其配置为 Kubernetes 插件中 Maven pod 的卷,挂载点为 /home/jenkins/.ssh/
。secret 中的每个项目都将是与挂载目录下的键名匹配的文件。我们可以使用 UI(Manage Jenkins / Configure / Cloud / Kubernetes
),或编辑 Jenkins 配置 /var/lib/jenkins/config.xml
<org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
<name>maven</name>
...
<volumes>
<org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>
<mountPath>/home/jenkins/.ssh</mountPath>
<secretName>mygit-ssh</secretName>
</org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>
</volumes>
现在,在此 agent 上运行的作业中,通过 SSH 拉取 Git 源代码应该可以正常工作。
注意:也可以在 ~/.ssh/config
中自定义 SSH 连接,例如,如果我们不想费心处理 known_hosts
,或者私钥挂载到不同的位置:
Host git.mycompany.com
StrictHostKeyChecking no
IdentityFile /home/jenkins/.config/git-secret/ssh-privatekey
使用 HTTP 的 Git
如果您喜欢 HTTP 下载,请将用户名/密码添加到某个位置的 Git 凭据存储 文件中
- 例如,来自 OpenShift secret 的
/home/jenkins/.config/git-secret/credentials
,每行一个站点
https://username:password@git.mycompany.com
https://user:pass@github.com
- 在 git-config 中启用它,该文件应位于
/home/jenkins/.config/git/config
[credential]
helper = store --file=/home/jenkins/.config/git-secret/credentials
如果 Git 服务具有由自定义证书颁发机构 (CA) 签名的证书,则最快的 hack 方法是将 GIT_SSL_NO_VERIFY=true
环境变量 (EnvVar) 设置为 agent。正确的解决方案需要两件事
- 从 config map 将自定义 CA 的公共证书添加到 agent 容器的路径(例如
/usr/ca/myTrustedCA.pem
)。 - 在 EnvVar
GIT_SSL_CAINFO=/usr/ca/myTrustedCA.pem
或上面提到的git-config
文件中,告诉 Git 此证书的路径
[http "https://git.mycompany.com"]
sslCAInfo = /usr/ca/myTrustedCA.pem
注意:在 OpenShift v3.7(及更早版本)中,config map 和 secret 挂载点 不得重叠,因此我们不能同时映射到 /home/jenkins
和 /home/jenkins/dir
。这就是为什么我们没有使用上面众所周知的文件位置的原因。OpenShift v3.9 中预计会修复此问题。
Maven
为了使 Maven 构建正常工作,通常需要做两件事
- 应设置企业 Maven 仓库(例如,Apache Nexus)以充当外部仓库的代理。将其用作镜像。
- 此内部仓库可能具有 HTTPS 端点,其证书由自定义 CA 签名。
如果构建在容器中运行,则拥有内部 Maven 仓库实际上是必不可少的,因为它们从空的本地仓库(缓存)开始,因此 Maven 每次都会下载所有 JAR。从本地网络上的内部代理仓库下载显然比从互联网下载更快。
Maven Jenkins agent 镜像支持环境变量,可用于设置此代理的 URL。在 Kubernetes 插件容器模板中设置以下内容
MAVEN_MIRROR_URL=https://nexus.mycompany.com/repository/maven-public
构建工件 (JAR) 也应存档在仓库中,该仓库可能是也可能不是充当上述依赖项镜像的仓库。Maven deploy
需要在 pom.xml
中的 Distribution management 下提供仓库 URL(这与 agent 镜像无关)
<project ...>
<distributionManagement>
<snapshotRepository>
<id>mynexus</id>
<url>https://nexus.mycompany.com/repository/maven-snapshots/</url>
</snapshotRepository>
<repository>
<id>mynexus</id>
<url>https://nexus.mycompany.com/repository/maven-releases/</url>
</repository>
</distributionManagement>
上传工件可能需要身份验证。在这种情况下,必须在 settings.xml
中服务器 ID 下设置用户名/密码,该服务器 ID 与 pom.xml
中的服务器 ID 匹配。我们需要从 OpenShift secret 将包含 URL、用户名和密码的整个 settings.xml
挂载到 Maven Jenkins agent 容器上。我们也可以使用如下环境变量
- 从 secret 向容器添加环境变量
MAVEN_SERVER_USERNAME=admin
MAVEN_SERVER_PASSWORD=admin123
- 从 config map 将
settings.xml
挂载到/home/jenkins/.m2/settings.xml
<settings ...>
<mirrors>
<mirror>
<mirrorOf>external:*</mirrorOf>
<url>${env.MAVEN_MIRROR_URL}</url>
<id>mirror</id>
</mirror>
</mirrors>
<servers>
<server>
<id>mynexus</id>
<username>${env.MAVEN_SERVER_USERNAME}</username>
<password>${env.MAVEN_SERVER_PASSWORD}</password>
</server>
</servers>
</settings>
禁用交互模式(使用批处理模式)以跳过下载日志,方法是在 Maven 命令中使用 -B
或在 settings.xml
中添加 <interactiveMode>false</interactiveMode>
。
如果 Maven 仓库的 HTTPS 端点使用由自定义 CA 签名的证书,我们需要使用 keytool 创建一个 Java KeyStore,其中包含作为受信任的 CA 证书。此 KeyStore 应作为 config map 上传到 OpenShift。使用 oc
命令从文件创建 config map
oc create configmap maven-settings --from-file=settings.xml=settings.xml --from-
file=myTruststore.jks=myTruststore.jks
将 config map 挂载到 Jenkins agent 上的某个位置。在此示例中,我们使用 /home/jenkins/.m2
,但这仅仅是因为我们在同一个 config map 中有 settings.xml
。KeyStore 可以放在任何路径下。
然后通过在容器的 MAVEN_OPTS
环境变量中设置 Java 参数,使 Maven Java 进程使用此文件作为信任存储
MAVEN_OPTS=
-Djavax.net.ssl.trustStore=/home/jenkins/.m2/myTruststore.jks
-Djavax.net.ssl.trustStorePassword=changeit
内存使用
这可能是最重要的部分——如果我们没有正确设置最大内存,在一切似乎都正常工作之后,我们将遇到间歇性构建失败。
如果在 Java 命令行中没有设置堆,则在容器中运行 Java 可能会导致高内存使用错误。JVM 看到主机机器的总内存 而不是容器的内存限制,并相应地设置 默认最大堆。这通常远大于容器的内存限制,当 Java 进程为堆分配更多内存时,OpenShift 会简单地杀死容器。
尽管 jenkins
-slave-base
镜像具有内置的 脚本来将最大堆设置为容器内存的一半 (可以通过 EnvVar CONTAINER_HEAP_PERCENT=0.50
修改),但它仅适用于 Jenkins agent Java 进程。在 Maven 构建中,我们还有重要的其他 Java 进程正在运行
mvn
命令本身就是一个 Java 工具。- Maven Surefire 插件 默认情况下在 fork 的 JVM 中执行单元测试。
最终,我们将有三个 Java 进程同时在容器中运行,重要的是估计它们的内存使用情况,以避免意外杀死 pod。每个进程都有不同的方法来设置 JVM 选项
- Jenkins agent 堆的计算如上所述,但我们绝对不应该让 agent 拥有如此大的堆。其他两个 JVM 需要内存。设置
JAVA_OPTS
适用于 Jenkins agent。 mvn
工具由 Jenkins 作业调用。设置MAVEN_OPTS
以自定义此 Java 进程。- Maven
surefire
插件为单元测试生成的 JVM 可以通过 argLine Maven 属性进行自定义。它可以在pom.xml
中、settings.xml
中的配置文件中设置,或者只需在MAVEN_OPTS
中的mvn
命令中添加-DargLine=… to mvn
。
以下是如何为 Maven agent 容器设置这些环境变量的示例
JAVA_OPTS=-Xms64m -Xmx64m
MAVEN_OPTS=-Xms128m -Xmx128m -DargLine=${env.SUREFIRE_OPTS}
SUREFIRE_OPTS=-Xms256m -Xmx256m
这些数字在我们的测试中有效,其中 1024Mi agent 容器内存限制用于构建和运行 SpringBoot 应用程序的单元测试。这些数字相对较低,堆大小也较小;对于复杂的 Maven 项目和单元测试,可能需要更高的限制。
注意:Java8 进程的实际内存使用量类似于 HeapSize + MetaSpace + OffHeapMemory
, 这可能明显大于设置的最大堆大小。使用上述设置,在我们的例子中,这三个 Java 进程占用了超过 900Mi 内存。请参阅容器内进程的 RSS 内存:ps -e -o
pid
,user
,
rss
,comm
,args
Jenkins agent 镜像同时安装了 JDK 64 位和 32 位版本。对于 mvn
和 surefire
,默认使用 64 位 JVM。为了降低内存使用量,只要 -Xmx
小于 1.5 GB,强制使用 32 位 JVM 就有意义
JAVA_HOME=/usr/lib/jvm/Java-1.8.0-openjdk-1.8.0.161–0.b14.el7_4.i386
请注意,也可以在 JAVA_TOOL_OPTIONS
EnvVar 中设置 Java 参数,任何启动的 JVM 都会拾取这些参数。JAVA_OPTS
和 MAVEN_OPTS
中的参数会覆盖 JAVA_TOOL_OPTIONS
中的参数,因此我们可以为我们的 Java 进程实现与上述相同的堆配置,而无需使用 argLine
JAVA_OPTS=-Xms64m -Xmx64m
MAVEN_OPTS=-Xms128m -Xmx128m
JAVA_TOOL_OPTIONS=-Xms256m -Xmx256m
这仍然有点令人困惑,因为所有 JVM 都记录了 Picked up JAVA_TOOL_OPTIONS:
Jenkins Pipeline
按照上述设置,我们应该准备好一切来运行成功的构建。我们可以拉取代码、下载依赖项、运行单元测试并将工件上传到我们的仓库。让我们创建一个 Jenkins Pipeline 项目来完成此操作
pipeline {
/* Which container to bring up for the build. Pick one of the templates configured in Kubernetes plugin. */
agent {
label 'maven'
}
stages {
stage('Pull Source') {
steps {
git url: 'ssh://git@git.mycompany.com:22/myapplication.git', branch: 'master'
}
}
stage('Unit Tests') {
steps {
sh 'mvn test'
}
}
stage('Deploy to Nexus') {
steps {
sh 'mvn deploy -DskipTests'
}
}
}
}
对于真实的项目,当然,CI/CD 管道应该做的不仅仅是 Maven 构建;它可以部署到开发环境、运行集成测试、提升到更高的环境等。上面链接的学习文章展示了如何完成这些事情的示例。
多个容器
一个 pod 可以运行多个容器,每个容器都有自己的资源限制。它们共享相同的网络接口,因此我们可以在 localhost
上访问启动的服务,但我们需要考虑端口冲突。环境变量是单独设置的,但挂载的卷对于在一个 Kubernetes pod 模板中配置的所有容器都是相同的。
当单元测试需要外部服务且嵌入式解决方案不起作用时(例如,数据库、消息队列等),启动多个容器很有用。在这种情况下,第二个容器也会随着 Jenkins agent 一起启动和停止。
请参阅 Jenkins config.xml
代码片段,我们在其中为 Maven 构建在 sidecar 中启动了一个 httpbin
服务
<org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
<name>maven</name>
<volumes>
...
</volumes>
<containers>
<org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
<name>jnlp</name>
<image>registry.access.redhat.com/openshift3/jenkins-slave-maven-rhel7:v3.7</image>
<resourceLimitCpu>500m</resourceLimitCpu>
<resourceLimitMemory>1024Mi</resourceLimitMemory>
<envVars>
...
</envVars>
...
</org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
<org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
<name>httpbin</name>
<image>citizenstig/httpbin</image>
<resourceLimitCpu></resourceLimitCpu>
<resourceLimitMemory>256Mi</resourceLimitMemory>
<envVars/>
...
</org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
</containers>
<envVars/>
</org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
总结
对于摘要,请参阅上面描述的配置创建的 OpenShift 资源和来自 Jenkins config.xml
的 Kubernetes 插件配置。
apiVersion: v1
kind: List
metadata: {}
items:
- apiVersion: v1
kind: ConfigMap
metadata:
name: git-config
data:
config: |
[credential]
helper = store --file=/home/jenkins/.config/git-secret/credentials
[http "http://git.mycompany.com"]
sslCAInfo = /home/jenkins/.config/git/myTrustedCA.pem
myTrustedCA.pem: |-
-----BEGIN CERTIFICATE-----
MIIDVzCCAj+gAwIBAgIJAN0sC...
-----END CERTIFICATE-----
- apiVersion: v1
kind: Secret
metadata:
name: git-secret
stringData:
ssh-privatekey: |-
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
credentials: |-
https://username:password@git.mycompany.com
https://user:pass@github.com
- apiVersion: v1
kind: ConfigMap
metadata:
name: git-ssh
data:
config: |-
Host git.mycompany.com
StrictHostKeyChecking yes
IdentityFile /home/jenkins/.config/git-secret/ssh-privatekey
known_hosts: '[git.mycompany.com]:22 ecdsa-sha2-nistp256 AAAdn7...'
- apiVersion: v1
kind: Secret
metadata:
name: maven-secret
stringData:
username: admin
password: admin123
从文件创建了一个额外的 config map
oc create configmap maven-settings --from-file=settings.xml=settings.xml
--from-file=myTruststore.jks=myTruststore.jks
Kubernetes 插件配置
<?xml version='1.0' encoding='UTF-8'?>
<hudson>
...
<clouds>
<org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud plugin="kubernetes@1.0">
<name>openshift</name>
<defaultsProviderTemplate></defaultsProviderTemplate>
<templates>
<org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
<inheritFrom></inheritFrom>
<name>maven</name>
<namespace></namespace>
<privileged>false</privileged>
<alwaysPullImage>false</alwaysPullImage>
<instanceCap>2147483647</instanceCap>
<slaveConnectTimeout>100</slaveConnectTimeout>
<idleMinutes>0</idleMinutes>
<label>maven</label>
<serviceAccount>jenkins37</serviceAccount>
<nodeSelector></nodeSelector>
<nodeUsageMode>NORMAL</nodeUsageMode>
<customWorkspaceVolumeEnabled>false</customWorkspaceVolumeEnabled>
<workspaceVolume class="org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume">
<memory>false</memory>
</workspaceVolume>
<volumes>
<org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>
<mountPath>/home/jenkins/.config/git-secret</mountPath>
<secretName>git-secret</secretName>
</org.csanchez.jenkins.plugins.kubernetes.volumes.SecretVolume>
<org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume>
<mountPath>/home/jenkins/.ssh</mountPath>
<configMapName>git-ssh</configMapName>
</org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume>
<org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume>
<mountPath>/home/jenkins/.config/git</mountPath>
<configMapName>git-config</configMapName>
</org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume>
<org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume>
<mountPath>/home/jenkins/.m2</mountPath>
<configMapName>maven-settings</configMapName>
</org.csanchez.jenkins.plugins.kubernetes.volumes.ConfigMapVolume>
</volumes>
<containers>
<org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
<name>jnlp</name>
<image>registry.access.redhat.com/openshift3/jenkins-slave-maven-rhel7:v3.7</image>
<privileged>false</privileged>
<alwaysPullImage>false</alwaysPullImage>
<workingDir>/tmp</workingDir>
<command></command>
<args>${computer.jnlpmac} ${computer.name}</args>
<ttyEnabled>false</ttyEnabled>
<resourceRequestCpu>500m</resourceRequestCpu>
<resourceRequestMemory>1024Mi</resourceRequestMemory>
<resourceLimitCpu>500m</resourceLimitCpu>
<resourceLimitMemory>1024Mi</resourceLimitMemory>
<envVars>
<org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<key>JAVA_HOME</key>
<value>/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.161-0.b14.el7_4.i386</value>
</org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<key>JAVA_OPTS</key>
<value>-Xms64m -Xmx64m</value>
</org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<key>MAVEN_OPTS</key>
<value>-Xms128m -Xmx128m -DargLine=${env.SUREFIRE_OPTS} -Djavax.net.ssl.trustStore=/home/jenkins/.m2/myTruststore.jks -Djavax.net.ssl.trustStorePassword=changeit</value>
</org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<key>SUREFIRE_OPTS</key>
<value>-Xms256m -Xmx256m</value>
</org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<key>MAVEN_MIRROR_URL</key>
<value>https://nexus.mycompany.com/repository/maven-public</value>
</org.csanchez.jenkins.plugins.kubernetes.ContainerEnvVar>
<org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar>
<key>MAVEN_SERVER_USERNAME</key>
<secretName>maven-secret</secretName>
<secretKey>username</secretKey>
</org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar>
<org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar>
<key>MAVEN_SERVER_PASSWORD</key>
<secretName>maven-secret</secretName>
<secretKey>password</secretKey>
</org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar>
</envVars>
<ports/>
<livenessProbe>
<execArgs></execArgs>
<timeoutSeconds>0</timeoutSeconds>
<initialDelaySeconds>0</initialDelaySeconds>
<failureThreshold>0</failureThreshold>
<periodSeconds>0</periodSeconds>
<successThreshold>0</successThreshold>
</livenessProbe>
</org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
<org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
<name>httpbin</name>
<image>citizenstig/httpbin</image>
<privileged>false</privileged>
<alwaysPullImage>false</alwaysPullImage>
<workingDir></workingDir>
<command>/run.sh</command>
<args></args>
<ttyEnabled>false</ttyEnabled>
<resourceRequestCpu></resourceRequestCpu>
<resourceRequestMemory>256Mi</resourceRequestMemory>
<resourceLimitCpu></resourceLimitCpu>
<resourceLimitMemory>256Mi</resourceLimitMemory>
<envVars/>
<ports/>
<livenessProbe>
<execArgs></execArgs>
<timeoutSeconds>0</timeoutSeconds>
<initialDelaySeconds>0</initialDelaySeconds>
<failureThreshold>0</failureThreshold>
<periodSeconds>0</periodSeconds>
<successThreshold>0</successThreshold>
</livenessProbe>
</org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
</containers>
<envVars/>
<annotations/>
<imagePullSecrets/>
</org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
</templates>
<serverUrl>https://172.30.0.1:443</serverUrl>
<serverCertificate>-----BEGIN CERTIFICATE-----
MIIC6jCC...
-----END CERTIFICATE-----</serverCertificate>
<skipTlsVerify>false</skipTlsVerify>
<namespace>first</namespace>
<jenkinsUrl>http://jenkins.cicd.svc:80</jenkinsUrl>
<jenkinsTunnel>jenkins-jnlp.cicd.svc:50000</jenkinsTunnel>
<credentialsId>1a12dfa4-7fc5-47a7-aa17-cc56572a41c7</credentialsId>
<containerCap>10</containerCap>
<retentionTimeout>5</retentionTimeout>
<connectTimeout>0</connectTimeout>
<readTimeout>0</readTimeout>
<maxRequestsPerHost>32</maxRequestsPerHost>
</org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud>
</clouds>
</hudson>
构建愉快!
本文最初发表于 ITNext,并经许可转载。
评论已关闭。