How to Install Jenkins on Kubernetes Cluster

September 4, 2024

Introduction

Working on multiple projects in a complex microservices environment takes time and strains the available resources. Jenkins is a continuous integration (CI) tool that aims to solve this problem by automating the software development process.

A Kubernetes cluster adds another automation layer to Jenkins. It ensures that Jenkins always has the right amount of resources available.

This tutorial shows how to install Jenkins on a Kubernetes cluster.

How to install Jenkins on a Kubernetes cluster.

Prerequisites

  • Command-line access.
  • A working Kubernetes cluster.
  • The kubectl CLI installed on the local system.

Install Jenkins on Kubernetes Cluster Using YAML Files

The YAML files for installing Jenkins on Kubernetes are easily tracked and edited. They are reusable, which is why YAML files are often used to deploy apps on Kubernetes.

Follow the steps below to install Jenkins on a Kubernetes cluster using YAML manifests.

Warning: The YAML files in this article illustrate the Jenkins deployment process. They should not be used in a production environment without being modified to accommodate cluster-specific settings and network resources.

Step 1: Create Namespace for Jenkins Deployment

A distinct namespace provides an additional isolation layer and control over the continuous integration environment. Create a namespace for the Jenkins deployment by typing the following command in your terminal:

kubectl create namespace [name]

The name of the namespace should be a DNS-compatible label. The example below uses the name jenkins.

Successfully created the jenkins namespace.

Use the following command to list existing namespaces:

kubectl get namespaces

The output confirms that the jenkins namespace was created successfully.

list of existing namespace on the Kubernetes master node.

Step 2: Create Service Account

Service accounts provide identities that are used to control Kubernetes pod processes. Follow the steps below to create a service account on a local cluster:

1. Use a text editor to create a file for storing the service account declarations:

nano sa-jenkins.yaml

2. Paste the following code into the file:

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: admin
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["*"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin
  namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admin
subjects:
- kind: ServiceAccount
  name: admin
  namespace: jenkins

Save the file and exit.

The file defines a cluster role with administrative permissions. It also creates a new service account named admin and binds it with the previously defined cluster role.

3. Apply the configuration with kubectl apply:

kubectl apply -f sa-jenkins.yaml

The output confirms the creation of three Kubernetes objects: a cluster role, a cluster role binding, and a service account.

Applying Jenkins service account configuration with the kubectl apply command.

Step 3: Create Jenkins Persistent Volume and Persistent Volume Claim

The role of a persistent volume is to store basic Jenkins data and preserve it beyond a pod's lifetime. Proceed with the below steps to create a YAML file that defines storage-related components of the deployment:

1. Create a YAML file:

nano volume-jenkins.yaml

2. Paste the code below into the file:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-pv
  labels:
    type: local
spec:
  storageClassName: local-storage
  claimRef:
    name: jenkins-pvc
    namespace: jenkins
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  local:
    path: /mnt
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - minikube

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: jenkins
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

Save the file and exit.

In the first section, the file declares the local-storage storage class. The second section defines the jenkins-pv persistent volume, and the third creates a persistent volume claim jenkins-pvc that binds to the jenkins-pv volume.

The values item in the nodeAffinity section should provide the name of the node Jenkins will use. The example above uses minikube, so the node's name is minikube.

3. Create the volume by applying the file with kubectl:

kubectl apply -f volume-jenkins.yaml

Step 4: Compose and Create Jenkins Deployment

A deployment object controls the number of pods deployed and handles scalability and pod updates. Create a Jenkins deployment by following the procedure below:

1. Create a YAML file to store deployment information:

nano deploy-jenkins.yaml

2. Paste the following code into the file:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins-server
  template:
    metadata:
      labels:
        app: jenkins-server
    spec:
      securityContext:
            fsGroup: 1000 
            runAsUser: 1000
      serviceAccountName: admin
      containers:
        - name: jenkins
          image: jenkins/jenkins:lts
          resources:
            limits:
              memory: "2Gi"
              cpu: "1000m"
            requests:
              memory: "500Mi"
              cpu: "500m"
          ports:
            - name: httpport
              containerPort: 8080
            - name: jnlpport
              containerPort: 50000
          livenessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 90
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          volumeMounts:
            - name: jenkins-data
              mountPath: /var/jenkins_home         
      volumes:
        - name: jenkins-data
          persistentVolumeClaim:
              claimName: jenkins-pvc

Save the changes and exit nano.

The deployment file in this example utilizes the jenkins/jenkins:lts Docker image and creates one replica that will be exposed on port 8080.

The volumeMounts section of the file mounts the persistent volume created in the previous step. The livenessProbe and readinessProbe sections declare probes that restart failed pods and detect when pods are ready.

3. Use the newly created file to deploy Jenkins:

kubectl apply -f deploy-jenkins.yaml

Step 5: Compose and Apply Jenkins Service File

A Kubernetes Service is an abstraction that exposes Jenkins to the broader network. It allows the user to maintain a persistent connection to the pod regardless of the changes taking place within the cluster.

1. Create a YAML file in which you will define the service:

nano service-jenkins.yaml

2. Add the following content to the file:

apiVersion: v1
kind: Service
metadata:
  name: jenkins-svc
  namespace: jenkins
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/path:   /
      prometheus.io/port:   '8080'
spec:
  selector: 
    app: jenkins-server
  type: NodePort  
  ports:
    - port: 8080
      targetPort: 8080
      nodePort: 32000

Save the file and exit.

3. Create the service by typing:

kubectl apply -f service-jenkins.yaml

Jenkins is now accessible in a web browser.

Step 6: Install Jenkins Operator Using YAML Files (Optional)

The Jenkins Operator is a native Kubernetes software extension that manages Jenkins on Kubernetes. Install it by executing the two kubectl apply commands below:

kubectl apply -f https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/config/crd/bases/jenkins.io_jenkins.yaml
kubectl apply -f https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/deploy/all-in-one-v1alpha2.yaml

Watch the operator become ready by adding the -w option to the kubectl get command below:

kubectl get pods -w
Checking if the Jenkins operator pod is ready.

Install Jenkins on Kubernetes Cluster via Helm

Helm is a package manager designed to facilitate installing applications in a Kubernetes cluster. Follow the steps below to install Jenkins using the official Helm chart.

Step 1: Add Jenkins Repository

1. Add the Jenkins repository to the local repository list with the following Helm command:

helm repo add jenkins https://charts.jenkins.io
Adding the Jenkins Helm repository.

2. Update local chart repository data:

helm repo update
Updating Helm repositories.

3. Search for Jenkins in the locally available repositories and note the chart name:

helm search repo jenkins

The output lists the Jenkins chart alongside basic chart information.

Searching for the Jenkins Helm chart.

Step 2: Prepare Cluster for Deployment

Before using the Helm chart to install Jenkins on a cluster, ensure the cluster meets all the requirements.

1. Create a namespace for the deployment:

kubectl create namespace jenkins

2. Create a YAML describing a persistent volume:

nano jenkins-volume.yaml

3. Save the following code in the file:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-pv
  namespace: jenkins
spec:
  storageClassName: jenkins-pv
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 20Gi
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /data/jenkins-volume/

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: jenkins-pv
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

4. Create a persistent volume by entering the following command:

kubectl apply -f jenkins-volume.yaml

5. Create a YAML that will define a cluster role, a cluster role binding, and a service account:

nano jenkins-sa.yaml

6. Paste the following contents into the file:

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: jenkins
rules:
- apiGroups:
  - '*'
  resources:
  - statefulsets
  - services
  - replicationcontrollers
  - replicasets
  - podtemplates
  - podsecuritypolicies
  - pods
  - pods/log
  - pods/exec
  - podpreset
  - poddisruptionbudget
  - persistentvolumes
  - persistentvolumeclaims
  - jobs
  - endpoints
  - deployments
  - deployments/scale
  - daemonsets
  - cronjobs
  - configmaps
  - namespaces
  - events
  - secrets
  verbs:
  - create
  - get
  - watch
  - delete
  - list
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
  - list
  - watch
  - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:serviceaccounts:jenkins

Save the file and exit.

7. Create the Kubernetes object listed in the file by using kubectl apply:

kubectl apply -f jenkins-sa.yaml

Step 3: Modify jenkins-values.yaml File

The jenkins-values.yaml is a pre-generated file with default values for a Jenkins deployment. The steps below show how to customize the file to fit the cluster's needs.

1. Download the file from the Jenkins GitHub page.

2. Open the file in a text editor:

nano jenkins-values.yaml

3. Edit the nodePort line by adding 32000 as the port number.

nodePort: 32000
Editing the nodePort item in the jenkins-values YAML file.

4. Modify the storageClass line to contain a reference to the persistent volume created earlier in the tutorial:

storageClass: jenkins-pv
Editing the storageClass item in the jenkins-values YAML file.

5. Ensure the sub-items of the serviceAccount item have the following values:

serviceAccount:
  create: false
  name: jenkins
  annotations: {}
Editing the serviceAccount item in the jenkins-values YAML file.

Step 4: Install Jenkins

After setting up the cluster, use Helm to install Jenkins.

1. Define the chart variable to be the Jenkins chart name:

chart=[chart_name]

2. Use the helm install command:

helm install jenkins -n jenkins -f jenkins-values.yaml $chart
Installing Jenkins via Helm.

Step 5: Install Jenkins Operator via Helm (Optional)

Proceed with the steps below to install the Jenkins operator using a Helm chart:

1. Create a namespace for the operator:

kubectl create namespace jenkins-operator

2. Add the Jenkins operator repository:

helm repo add jenkins-operator https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart

3. Update the repositories on the system:

helm repo update

4. Search for the Helm chart:

helm repo search jenkins-operator

5. Define the chart variable:

chart=[chart_name]

6. Install the operator with the following command:

helm install jenkins-operator -n jenkins-operator $chart

When Helm finishes deploying the operator, the output confirms the deployment's success.

Installing Jenkins operator via Helm.

Jenkins on Kubernetes: Post-Installation Setup

Before starting Jenkins, check if all deployed components are working. Use the kubectl get all command and specify the namespace:

kubect get all -n jenkins

The example shows a properly functioning deployment:

  • The pod is marked as READY and Running.
  • The service's Cluster IP and ports have been successfully allocated.
  • The deployment is marked as READY and AVAILABLE.
  • The desired number of replicas (1) has been reached.
Checking the state of Jenkins pod, service, deployment and replicas.

Set Up Jenkins After Installing with YAML Files

Proceed with the following steps after installing Jenkins using YAML files:

1. Open a web browser and access the node using its IP address and the port defined in the service file. To find the IP address of the node, run:

kubectl get nodes -o yaml

The node IP address is located in the status section of the output.

A section of the output from the kubectl get nodes command showing the node IP address.

Using the information from the example, the address of the Jenkins dashboard is:

http://192.168.49.2:32000

Upon first access, the prompt to unlock Jenkins appears.

Unlock Jenkins dialog and the location of the password text box.

3. To obtain the password, find the name of the pod in the output of the command below:

kubectl get pods -n jenkins

4. Access the pod's logs:

kubectl logs [pod_name] --namespace jenkins

5. Find the password at the end of the log, formatted as a long alphanumerical string.

Displaying the location of the Jenkins password in the log file.

6. Paste the password into the Administrator password field to unlock Jenkins.

Set Up Jenkins After Installing via Helm

Use the steps below to configure a Helm installation of Jenkins:

1. Find the administrative password with the following kubectl command:

kubectl exec --namespace jenkins -it svc/jenkins -c jenkins -- /bin/cat /run/secrets/additional/chart-admin-password && echo

The password appears in the command output.

Obtaining password for the Jenkins administrator account.

2. Forward the port of the Jenkins service using the following kubectl port-forward command:

kubectl --namespace jenkins port-forward svc/jenkins 8080:8080
Forwarding ports to enable Jenkins.

Set Permissions for minikube

When deploying Jenkins with Helm on a minikube test cluster, the user must change the minikube permissions to allow Jenkins to write data:

1. Use the command below to enter the minikube container using SSH:

minikube ssh
Entering Minikube shell via SSH.

2. Enter the following chown command to change the permissions of the jenkins-volume directory:

sudo chown -R 1000:1000 /data/jenkins-volume

3. Exit the minikube container:

exit

Using Jenkins on Kubernetes

After successfully logging into a Jenkins administrative account, the user can customize their Jenkins installation and create the first admin user. The following sections provide instructions for those actions.

Note: Check out our detailed Jenkins tutorial to learn everything you need to know about using Jenkins.

Customizing Jenkins on Kubernetes

Jenkins supports plugins that customize its functionalities, look, and feel. Users can install recommended plugins on the first login or choose their own.

1. Click Select plugins to install to start customizing the Jenkins installation.

The Customize Jenkins window.

A list of plugins appears, with categories on the left side of the page.

2. Select the plugins to use and click Install.

The plugin list in Jenkins.

Note: Jenkins sometimes requires a restart while troubleshooting or installing plugins. Refer to our article How to Restart Jenkins Manually to learn more.

Creating First Administrator-Level User

The last step of the Jenkins setup is to create the first admin user. Fill out the user creation form by providing the necessary credentials.

Creating the first admin user.

To finish creating the user, click the Save and Continue button at the bottom left side of the page.

You have successfully installed Jenkins on your Kubernetes cluster and can use it to create new and efficient development pipelines.

Example screenshot of the Jenkins dashboard.

Conclusion

After reading this article, you can install Jenkins on a Kubernetes cluster. Jenkins can automate many tasks and help developers submit code efficiently and consistently.

Jenkins on Kubernetes, combined with the cloud agility of Bare Metal Cloud, can help you fully automate your workflow and improve the speed and quality of your software.

Was this article helpful?
YesNo
Marko Aleksic
Marko Aleksić is a Technical Writer at phoenixNAP. His innate curiosity regarding all things IT, combined with over a decade long background in writing, teaching and working in IT-related fields, led him to technical writing, where he has an opportunity to employ his skills and make technology less daunting to everyone.
Next you should read
How to Install Jenkins on Ubuntu 18.04
October 20, 2022

Learn how to install Jenkins on Ubuntu 18.04. This software package is used to automate parts of the build...
Read more
How to Set Up and Run Kafka on Kubernetes
April 24, 2024

Kafka collects and structures vast amounts of data from multiple clients simultaneously. It's a great...
Read more
Introduction to Kubernetes Persistent Volumes
January 27, 2020

Persistent Volumes are used in Kubernetes orchestration when you want to preserve the data in the volume even...
Read more
6 Kubernetes Security Best Practices: Secure Your Workloads
January 23, 2020

This article presents basic security principles such as defense-in-depth and restricted privilege. Learn how...
Read more