20. February 2024 By Kristóf Nyári
Jenkins on k8s Part 1: Setting up
Jenkins is a venerable open-source automation server that has played a pivotal role in transforming the way teams build, test, and deploy their code. It's a tool that is serving as a linchpin for development teams striving for agility and speed in their software delivery pipelines. With its extensible architecture and robust plugin ecosystem, Jenkins empowers developers to automate mundane tasks, ensuring a seamless integration process and swift delivery of high-quality software.
In this multipart blogpost series, I am going to present all aspects of using Jenkins, from installing the server itself to deploying applications to a Kubernetes cluster. Stay with me as we explore and utilize one of the leading CI/CD tools today.
1. Setting up the infrastructure
1.1 Choosing the right host
To install Jenkins, first, a host server is needed. Now, there are multiple options, such as creating a VM via VirtualBox or VMWare and cloning the repo, then using the Makefile to install. There is also the option to host the server on Kubernetes, with its wide variety of hosting solutions (minikube, k3s, Kubernetes in Docker). These are all locally hosted Kubernetes services, however, for the sake of this demo, I am going to use a cloud provider, namely Google Cloud. GCP offers a generous free tier with its GKE (Google Kubernetes Engine) that allows developers to run a single-node Kubernetes cluster for free in a 3-month period (Not actually free, but the monthly allowance by the free tier should cover the full costs of the cluster).
1.2 Creating a cluster via GKE
To get started with GKE, create a Google Cloud account and apply for the free trial. Once this is done, the GCP Console will be accessible. Creating the cluster, from now on will be quite simple. Open the Cloud Console from the top right, which will initiate a console connection. Be sure to set the correct project in the console via gcloud config set project $MY_PROJECT_ID
. After setting the correct project ID, cluster creation can commence. GKE offers the Autopilot cluster creation mode, which is basically a mode of operation in GKE in which Google manages your cluster configuration, including your nodes, scaling, security, and other preconfigured settings. This option will automatically scale our cluster based on workloads. To create such a cluster, insert the following command into the cloud console:
gcloud beta container --project $MY_PROJECT_ID clusters create-auto $CLUSTER_NAME --region "europe-west3"
This will take some time, as it is quite a task to create a Kubernetes cluster from the ground up. Once the health checks finish, and the cluster is initialized successfully, the process of installing Jenkins can begin. To make sure of the cluster working properly, run a quick kubectl get po -A command
, which lists existing pods in all namespaces.
2. Installing Jenkins
A typical Jenkins deployment consists of a controller node and, optionally, one or more agents.
2.1 Prerequisites
A prerequisite to the installation is Helm, which will simplify the deployment process. Helm is a package manager for Kubernetes and its package format is called a chart. Helm comes pre-installed in the GKE cluster, however, for local development, Helm may not be available. Installation guides can be found on Helm’s homepage.
2.2 Required Kubernetes objects
Some additional prerequisites include a PersistentVolume and a ServiceAccount to correctly install and persist Jenkins data. The yaml object definition of these can be found here:
To translate these yaml definitions to actual Kubernetes objects, apply them via kubectl apply -f pv.yaml sa.yaml
Be sure to double check whether these objects get created in the right namespace, and if not, adjust the object definition files accordingly!
2.3 Helm
To access the Helm charts for Jenkins deployments, first adding the correct repo is necessary. This can be done via the following commands:
helm repo add jenkinsci https://charts.jenkins.io
helm repo update
After adding the repo to the list of available repositories, the actual installation can begin.
Now that the prerequisites are out of the way, we can easily install Jenkins via the following Helm command:
helm install jenkins -n jenkins -f jenkins-values-2.yaml jenkinsci/jenkins
After successful installation, the following information should be printed out to the Cloud Console:
NAME: jenkins
LAST DEPLOYED: Fri Feb 9 10:21:35 2024
NAMESPACE: jenkins
STATUS: deployed
REVISION: 1
3. Accessing & Configuring Jenkins
With our newfound Jenkins server up and running, it is time to actually do some work within the robust software.
After the installation, be sure to check whether the pods have finished initialisation with kubectl get pod -n jenkins
. The pods should be in a Running state.
3.1 Port-forwarding the service
The Jenkins helm chart also creates a Kubernetes service to expose the specific port of the application, thus making it accessible. In order to access the Jenkins console from our local host, we have to first create a port forward to the according port of the pod:
echo http://127.0.0.1:8080
kubectl --namespace jenkins port-forward svc/jenkins-on-k8s 8080:8080
This command opens the local port 8080 to accept connections, thus navigating to 127.0.0.1:8080 in our browser opens the Jenkins UI.
3.2 Unexpected credentials
Now we face another challenge: a login screen. The installation instructions did not come with a default password nor credentials. The secret is, that the admin password is mounted within the running pod itself. To be able to retrieve it, we need to enter into the pod itself and get the contents of that file. In Kubernetes, it can be done via:
kubectl exec --namespace jenkins -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/additional/chart-admin-password && echo
Now that the admin password is in our clipboard, we can proceed to logging in (default username is admin).
3.3 Plugin management and configuration
In order to actually use Jenkins, some further configuration is required. Namely, we need to add an executor. Executors are one of the basic building blocks which allow a build to run on a node/agent (e.g. build server). Think of an executor as a single "process ID", or as the basic unit of resource that Jenkins executes on your machine to run a build. Going to Manage Jenkins -> System -> # of executors enables us to specify the number of said executors. Let us leave this at 1, so that our future pipelines can run.
Another essential part of Jenkins is its wide variety of plugins. Natively, without plugins, Jenkins can only do so much. The goal of this blogpost series is to eventually deploy a web application to the GKE cluster mentioned earlier. This requires the Kubernetes CLI & Google Kubernetes Engine plugins. Installing these can be done via Manage Jenkins -> Plugins -> Available Plugins. For our upcoming web application, also install the NodeJS & Go plugins.
With these out of the way, our Jenkins server is ready to use and is patiently waiting for new build pipelines.
4.Conclusion
In this first installment of our Jenkins on Kubernetes series, we've navigated through the essential steps of setting up the infrastructure and installing Jenkins on a Google Kubernetes Engine (GKE) cluster. By harnessing the power of Kubernetes, we've laid the foundation for a scalable and efficient CI/CD environment.
As our Jenkins server stands ready, configured, and waiting for new build pipelines, we've only scratched the surface of the capabilities that this dynamic duo offers. In the upcoming parts of this series, we'll delve deeper, exploring advanced configurations, optimizing Jenkins for diverse workloads, and ultimately deploying a web application to our GKE cluster.
So, stay tuned for the next chapter, where we'll continue our journey through the intricacies of Jenkins on Kubernetes.