Jenkins Plugin在一个k8 cluster中运行动态的agents.
基于Scaling Docker with Kubernetes,自动调整Jenkins agents的规模。
这个plugin为每一个启动的agent创建k8 pod,在build结束后停掉它。
Agents用jnlp启动,所以预期这个agent可以自动于jenkins master自动连接。
其中一些环境变量会自动注入:
JENKINS_URL: Jenkins web interface url
JENKINS_SECRET: the secret key for authentication
JENKINS_AGENT_NAME: the name of the Jenkins agent
JENKINS_NAME: the name of the Jenkins agent
可以用jenkins/jnlp-slave 进行测试, 查看源代码可见Docker image source code.
Kubernetes Cloud Configuration
‘Jenkins-settings’ -> 'add cloud'-> select 'Kubernetes'-fill the information like Name, Kubernetes URL, Kubernetes server certificate key
如果 Kubernetes URL没有设置,则这个connection项会从server account或者kube config文件中自动配置。
Restricting what jobs can use your configured cloud
clouds可以配置,使其仅允许一些job去用他们。
去enable这些,在cloud的'advanced configuration'勾选'Restrict pipeline support' 去对‘folder box'进行授权。如果后续有新的job想使该云,则可将其加入job folder.
Pipeline support
Nodes可以在pipeline中定义并被使用。然而, 默认执行通常在jnlp container上执行。你必须指定container去执行你的任务
可从下两图进行说明:
可以在examples dir中看到更多的答案。
默认的jnlp agent template如下:
containerTemplate(name:'jnlp',image:'jenkins/jnlp-slave:3.10-1-alpine',args:'${computer.jnlpmac} ${computer.name}'),
也可以用yaml syntax来显示:
如果你想覆盖原来默认的jnlp,保持名字不变,更新其他参数即可。
Container Group Support
我们可以针对agent pod, 基于共享资源例如mounts, 定义多组container。每个container中的ports都可以被K8的pod用localhost连接。
以下段落没有理解:
The container statement allows to execute commands directly into each container. This feature is considered ALPHAas there are still some problems with concurrent execution and pipeline resumption
不知道要结合下图干什么说明什么。
Pod and container template configuration
Pod templates是用来创建agents的pod template.它可以使用user interface去配置,也可以使用pipeline去配置。
但是无论那种方式,我们编辑的都是以下这些fileds:
cloud: Jenkins setting中的cloud name。 defaults: kubernetes
name: the name of the pod
namespace: the namespace of the pod
label: the label of the pod. 必须是唯一值从而防止builds之前的冲突。
yaml: pod的yaml representation, 可以可以任何的values除了这些支持的fileds.
containers: container templates用于创建pod上的containers
serviceAccount: 这个pod的service account
nodeSelector: 这个pod的在哪个node上
nodeUsageMode: NORMAL或者EXCLUSIVE,其控制了Jenkins仅schedule jobs当label匹配还是尽可能多的用这个node.
volumes: pod volumes对所有container有效
envVars: 应用于所有container的环境变量
secretEnvVar: 其值从kubernetes secret中获得
imagePullSecrets: pull secret names的列表
annotation: 部署这个pod的说明
inheritFrom: 一个或多个pod templates的列表可以去继承的
slaveConnectTimeout: 等待一个agent上线的时间
podRetention: keep pods行为的控制器。可以是never(), onFailure(), always(), default(). 如果是空的话,这个pod在‘activeDeadlineSeconds’过后就会被删掉。
activeDeadlineSeconds如果podRentions设为‘never()’或者‘onFailure()’,pod就会在deadline过后删除。
idleMinutes允许pod保留一段时间防止复用直到这个时间过去。因为只有在这个时间过去后,最后一个步骤才会被执行。
和pod template对应的是container template。container template支持用户接口或者pipeline去配置。允许你配置的fields有:
name: container的name
image: container是基于哪个image启动的。
envVars: 配置container的环境变量,也会覆盖在pod level配置的环境变量。也可以在一行内用envVar配置单个环境变量。
secretEnvVar: 一个环境变量。这个环境变量从K8 secret中读取。
command: 这个container可以执行的命令
args: 传给command的参数。
ttyEnabled: 使能tty
livenessProbe: liveness探针。用以在container内部去执行exec liveness probe. 不支持httpGet liveness probes.
ports: 暴露container的端口。
Using yaml to Define Pod Templates
除了上面我们提到的一些fields,我们可以传入yaml的文件去支持任意的值。注意,yaml外所有的配置都会先生效。
下面这是一个container template
def label="mypod-${UUID.randomUUID().toString()}"
podTemplate(label: label, yaml:"""
apiVersion: v1
kind: Pod
metadata:
labels: some-label: some-label-value
spec:
containers:
- name: busybox
image: busybox
command: - cat
tty: true
""") {
node (label) {
container('busybox')
{ sh"hostname"}
}
}
你还可以用readFile或者readTrusted步骤去从文件中load一个yaml。在jenkins console的该plugin的配置panel也可以看到readFile/readTrusted
containerTemplate(
name:'busybox',
image:'busybox',
ttyEnabled:true,
command:'cat',
livenessProbe:
containerLivenessProbe(execArgs:'some --command',initialDelaySeconds:30,timeoutSeconds:1,failureThreshold:3,periodSeconds:10,successThreshold:1))
我们可以从Defining a liveness command中获取更多信息。
Pod template inheritance
一个podTemplate可以从一个已经存在的template中继承也可以不继承。这意味着podTemplate会继承node selector, service account, image pull secrets, containerTemplates和volume
加入到podTemplate的containerTemplae, 会在'parent' template中有一个匹配的containerTemplate, 会从parent containerTemplate中继承配置。如果没有匹配的containerTemplate, 这个模版会被加到parent template中。
volume的继承和container templates一样。Image Pull Secrets也会进行合并(这些证书包括在parent和current)
在以下这个例子中,我们会继承我们创建的podTemplate。
如果你想更改集成的template, 可以如下图所示:
如上图,我们只更换maven container的image,而保留其他参数不变。
需要注意:我们在上图中没有指定golang container,但是实际上它已经集成过来了。
Multiple Pod template inheritance
Field 'inheritFrom'指定从一个podTemplate或者多个以space间隔的podTemplate中继承。
后者覆盖前者,没有找到的则自动忽略。
Nesting Pod templates
‘inheritFrom’可以让我们很好的整合已经预先定义的podTemplates。另外一种整合podTemplate的方法是我们在pipeline中用groovy直接定义和整合,即如直接嵌入podTemplates.
示例如下:
这样,我们就把两个pod template整合成了一个pod template.
这个feature的用处还有, piepline library developers认为它允许你根据功能打包podTemplates, 让用户根据他们的意图嵌套这些功能。
示例如下:
src/com/foo/utils/PodTemplates.groovy:
有了这个库之后,我们就可以如下图所展示,可以很方便的使用了。
Using a different namespace
如果你需要你的pod在不同的namespace下运行,则需要通过ui或者pipeline明确指出。
Specifying a different shell command other than /bin/sh
默认的shell command是'/bin/sh', 如果你想用‘/bin/bash’,则需要明确指出。
By default, the shell command is /bin/sh. In some case, you would like to use another shell command like /bin/bash.
Container Configuration
示例:
Declarative Pipeline
Jenkins 2.66+ 才支持的feature
或者将yamlFile作为一个单独的pod yaml供使用而不是直接定义。如下图所示:
Constraints
我们可以在一个pod里面定义多个containers.其中jnlp是自动创建,运行的是JNLP agent service, 和${computer.jnlpmac}, ${computer.name},会作为Jenkins agent运行。
其他的containers必须是一个长时间的进程。
另外,如果你想提供自己的docker image作为jnlp slave, 你必须命令这个container为jnlp来覆盖the default one。不然的化,就会出现两个slaves同时和master进行交互的情况。