In this exercise we will get an introduction to the Jenkins Kubernetes plugin for running dynamic and ephemeral agents in a Kubernetes cluster - leveraging the scaling abilities of Kubernetes to schedule build agents.
CloudBees Core has OOTB support for Kubernetes build agents and allow Kubernetes agent templates - called Pod Templates - to be defined at either the Operations Center level or at the Team Master level. The Kubernetes based agent is contained in a Kubernetes pod, where a pod is a group of one or more containers sharing a common storage system and network. A pod is the smallest deployable unit of computing that Kubernetes can create and manage (you can read more about pods in the Kubernetes documentation).
NOTE: One of the containers in a Pod Template must host the actual Jenkins build agent that communicates with the Jenkins Master (the
slave.jar
file that is used for communication between the CloudBees Team Master and the agent). By convention, this container always exists (and is automatically added to any Pod Templates that do not define a Container Template with the name jnlp ). Again, this special container has the Namejnlp
and default execution of the Pipeline always happens in thisjnlp
container (as it did when we usedagent any
above) - unless you declare otherwise with a special Pipeline step provided by the Kuberentes plugin - thecontainer
step. If needed, this automatically providedjnlp
container may be overridden by specifying a Container Template with the Namejnlp
- but that Container Template must be able to connect to the Team Master via JNLP with a version of the Jenkinsslave.jar
that corresponds to the Team Master Jenkins verion or the Pod Template will fail to connect to the Team Master. You can learn more about thejnlp
container and additioal functionality in the Jenkins Kubernetes Plugin documentation on GitHub.
We will use the Kubernetes plugin Pipeline container
block to run Pipeline steps
inside a specific container configured as part of a Jenkins Kubernetes Agent Pod template. In our initial Pipeline, we used agent any
which required at least one Jenkins agent configured to Use this node as much as possible - resulting in the use of a Pod Template that only had a jnlp
container. But now we want to use Node.js in our Pipeline. Jenkins CasC was used to pre-configure the CloudBees Kube Agent Management plugin to include a Kubernetes Pod Template at the Team Master level to provide a Node.js container. Go to the top-level of your Team Master, click on the Manage Jenkins link and then scroll down and click on the Kubernetes Pod Templates item. If not at the top, scroll down to the Kubernetes Pod Template with the Name 'nodejs-app'
Take note of the Labels field with a value of nodejs-app and the Container Template Name field with a value of nodejs - both of these are important and we will need those values to configure our Pipeline to use this Pod Template and Container Template in your Jenkinsfile
.
- Navigate to and click on the
Jenkinsfile
file in the development branch of your forked helloworld-nodejs repository - Click on the Edit this file button (pencil)
- First, we need to update the
agent any
directive with the following so that we will get the correct Kubernetes Pod Template - configured with the Container Template that includes thenode:8.12.0-alpine
Docker image:
agent { label 'nodejs-app' }
- Commit that change and navigate to the Activity view of your helloworld-nodejs job in Blue Ocean on your Team Master. The build logs should be almost the same as before - we are still using the default
jnlp
container. - Let's change that by replacing the Say Hello
stage
with the following Teststage
so the steps run in the nodejscontainer
. Edit theJenkinsfile
file in the development branch of your forked helloworld-nodejs repository so the entire pipeline looks like the following:
pipeline {
agent { label 'nodejs-app' }
stages {
stage('Test') {
steps {
container('nodejs') {
echo 'Hello World!'
sh 'java -version'
}
}
}
}
}
All of the Pipeline steps within that container
block will run in the container specified by the Name of the Container Template - and in this case that Container Template is using the node:8.12.0-alpine
container image as we saw above. Commit the changes and the helloworld-nodejs job will run - it will result in an error because the nodejs
container does not have Java installed (and why should it).
NOTE: If you waited for your job to complete in Blue Ocean before you navigated to the Pipeline Runs Details View you will discover a nice feature where if a particular step fails, the tab with the failed step will be automatically expanded, showing the console log for the failed step as you can see in the image above.
- We will fix the error in the Test
stage
we added above by replacing thesh 'java -version'
step with thesh 'node --version'
step and moving thesh 'java -version'
step above thecontainer
block in theJenkinsfile
file in the development branch of your forked helloworld-nodejs repository so the entire pipeline looks like the following:
pipeline {
agent { label 'nodejs-app' }
stages {
stage('Test') {
steps {
sh 'java -version'
container('nodejs') {
echo 'Hello World!'
sh 'node --version'
}
}
}
}
}
- Commit the changes and the helloworld-nodejs job will run and it will complete successfully with the following output:
NOTE: The sh 'java -version' step before the
container('nodejs')
completed successfully this time because it used the defaultjnlp
container to execute any steps not in thecontainer
block.
You may proceed to the next set of labs - when your are you ready with this lab.