Agents, directed by controllers, handle and complete the tasks of running builds. Selecting the right agent according to your target platform, operating system, tools, and architecture, is essential when running the build.
You can connect and use different types of agents as described in Setting up agents on CloudBees CI.
By using agent
or
node
, you select the agent you desire for your build or one stage within your build.
The examples provided in the previous document page, Creating your first Pipeline
, work if you have the right agents for the labels used. However, the syntax for using Kubernetes pods or Docker
containers as ephemeral agents is different as you need to use additional directives, like the container
directive.
Ephemeral agents are provisioned, used for the build, and deprovisioned later. For information on how to select and use these types of agents, see the following sections.
Using Kubernetes pods as agents
If you plan to use Kubernetes to provide ephemeral agents, you need the following:
-
A Kubernetes cloud connected to your CloudBees CI instance.
-
The Kubernetes plugin installed in your CloudBees CI instance.
The Kubernetes cloud is provided out-of-the-box in CloudBees CI on modern cloud platforms, but must be added and connected for CloudBees CI on traditional platforms. You can find detailed instructions for that in the Shared cloud configuration documentation page and also in the Kubernetes plugin for Jenkins website.
Once the Kubernetes shared cloud and the Kubernetes plugin are installed, ephemeral agents for the builds are provided as pods according to pod templates defined using the UI or in the Pipeline definitions. The plugin provisions, uses, and deprovisions the pod when the build is finished.
For additional information about pod templates, how to create and use them, and pod template inheritance, refer to Understanding Pod Template Inheritance Knowledge Base article, and Kubernetes plugin for Jenkins. |
Agents are launched as inbound agents in a Pod container named jnlp
to manage the connection between the controller and the pod.
By default, the jnlp
container is automatically injected in the pod template by the Kubernetes plugin in addition to any container templates defined in the pod template.
By default, commands during the build process are executed in the jnlp
container.
If you want to run commands in another container of the pod template definition (for example, the container with the build tools) you must wrap the sh
steps into a container
step.
To launch these sh
commands in the container, the controller sends requests to the Kubernetes API. Other tasks, like streaming logs, publishing test results, and so on, are performed by the jnlp
container.
-
The controller asks Kubernetes for a cloud agent.
-
The Kubernetes shared cloud provides the ephemeral agent as a pod template. This pod template has two containers, the
jnlp
container injected by the Kubernetes plugin, and the container with the tools needed for tasks like building or testing your application. -
The controller sends commands to the container with the build tools using the Kubernetes API requests.
-
The
jnlp
container streams the logs, test results, and so on, to the controller.
In the following examples, we will assume that there is a pod template with the linux
label and, within that pod,
there is a container with the name maven
.
pipeline { agent { label 'linux'} (1) stages { stage('Build') { steps { container('maven') { (2) sh 'java --version' sh 'mvn --version' } } } } }
1 | Selects the agent for the build. The pod template has the label linux . |
2 | Sets the container to execute the commands. The container has the name maven . This container must be
part of the linux pod template definition. |
node('linux') { (1) stage('Build') { container('maven') { (2) sh 'java --version' sh 'mvn --version' } } }
1 | Selects the agent for the build. The pod template has the label linux . |
2 | Sets the container to execute the commands. The container has the name maven . This container must be
part of the linux pod template definition. |
If the |
Pod template definition embedded in the Pipeline definition
The previous examples rely on the existance of a pod template with the label linux
and a maven
container
inside this template. You can also embed the pod template description in the Pipeline as it is described in
the examples below.
pipeline { agent { kubernetes { (1) yaml ''' apiVersion: v1 kind: Pod spec: containers: - name: mymaven image: maven command: (2) - sleep args: - infinity ''' } } stages { stage('Build') { steps { container('mymaven') { (3) sh 'java --version' sh 'mvn --version' } } } } }
1 | Define the pod template. |
2 | Execute the sleep command to keep the container alive and make the connection between the controller
and the agent. |
3 | Set the container to execute the commands. The container has the name mymaven and is part of the pod template
YAML definition. |
podTemplate(containers: [ containerTemplate(name: 'mymaven', image: 'maven', command: 'sleep', args: 'infinity'), (1) ]) { node(POD_LABEL) { (2) stage('Build') { container('mymaven') { (3) sh 'java --version' sh 'mvn --version' } } } }
1 | Pod template definition that contains the container description and supports the node step. |
2 | POD_LABEL as the node selector because the node step is used inside a podTemplate step. |
3 | Set the container to execute the commands. The container has the name mymaven as defined above. |
Overriding the default jnlp
container
As described in the previous sections, ephemeral agents are provided as pod templates. In addition to the image
with the required tool, the plugin injects the jnlp
container.
If the container
step is not used, commands are executed by default in the jnlp
container.
If you want to execute commands in other containers, you must use the container
step in the Pipeline, and controllers
use Kubernetes API requests to run those commands within the step.
Kubernetes API requests are slow, and if you have many requests to agents, this situation might impact your cluster performance. This is because the Kubernetes plugin interacts with the Kubernetes share cloud that uses an active Kubernetes client that has a limitation in the number of concurrent connections to the Kubernetes API-server, and becasue some Kubernetes API requests keep the connections alive while the commands are executed on the container. You can find more information here.
To solve this situation, use a pattern of "All-in-One" containers (also known as "kitchen sink image") by overriding the injected jnlp
container template in your pod templates with your own container template named jnlp
.
This container must specify a container image with all the required resources to run an inbound agent and all the additional tools you may need to build or test your application.
In this use case, no other container is created or injected in the pod.
You can build these container images on top of the default CloudBees agent images. |
The following example shows an example that uses the All-in-one agent image used by the Jenkins infrastructure team.
pipeline { agent { kubernetes { (1) yaml ''' apiVersion: v1 kind: Pod spec: containers: - name: jnlp image: <custom image> (2) command: - /usr/local/bin/jenkins-agent (3) args: envVars: (4) - envVar: key: JENKINS_JAVA_BIN value: /opt/jdk-11/bin/java - envVar: key: JAVA_HOME value: /opt/jdk-17 label: all jnlp-all ''' } } stages { stage('Main') { (5) steps { sh 'java -version' sh 'mvn --version' } } } }
1 | Pod template definition using a YAML block inside the Kubernetes block within the agent directive. |
2 | An "all-in-one" image named jnlp . It overwrites the default jnlp container created by the Kubernetes
plugin. |
3 | Command to launch the inbound agent when the container starts. Different from the sleep command previously
used. |
4 | ENV_VARS to be created in the container. Be aware that the Agent JDK and the tools JDK can be different. |
5 | Stage executing command in the overwritten jnlp container. |
Docker agents
As described here, Docker containers are another alternative for ephemeral agents. To use Docker containers as ephemeral agents, you must do the following:
-
Install the Docker engine on the server running your CloudBees CI agent.
-
Install the Docker Pipeline plugin in the instance.
After all of these requirements are satisfied, you can use Docker containers as ephemeral agents in the following way.
pipeline { agent { docker { image 'node:16-alpine' } (1) } stages { stage('Test') { steps { sh 'node --version' (2) } } } }
1 | docker block within the agent directive to select a Docker image for the Docker containers used as agents. |
2 | Command executed inside the Docker container. |
docker.image('node:lts-slim').inside { (1) sh 'node --version' (2) }
1 | Docker step to set the image an the commands to be executed inside the running container. |
2 | Command executed inside the Docker container. |
For more information about Docker containers as ephemeral agents, refer to here.
All of the Pipeline examples, declarative or scripted, in the rest of this documentation assume that the examples are correctly selecting an available agent with the right tools to complete the build execution. |