How to deploy Jenkins on Kubernetes + OpenEBS

Modern IT infrastructure of a large enterprise requires Continuous Integration / Continuous Delivery (CI/CD) for software development, testing, and operations. It means building and validating the software on every commit ensuring that testing and production environments are always up-to-date. Such level of automation is a combination of extreme programming methodologies and practices, also known as DevOps. Through CI/CD pipelines, developers and operators frequently integrate new changes into IT infrastructure increasing organization’s ability to deliver applications and services at high velocity. One of the most popular open-source automation tools used in CI/CD environments is Jenkins. It serves as a workflow engine that ensures continuous integration of new changes.

Deploying Jenkins on Kubernetes provides the following benefits:

  • Isolates different jobs from one another.
  • Quickly cleans job’s workspace.
  • Dynamically deploys or schedules jobs with Kubernetes pods.
  • Allows increased resource utilization and efficiency.
  • Dynamically scales up Jenkins slaves on demand

Specifically, running and automating the scaling of dynamic Jenkins slaves in Kubernetes/Docker on top of OpenEBS significantly minimizes the overall deployment time and cost. OpenEBS enables you to build extremely scalable test cycles. You can create instant snapshots (thanks to the CoW) from Jenkins master and deploy new slaves faster. This eliminates the need to perform container-to-container copies.

Since in many IT infrastructures Jenkins slaves are optional, OpenEBS can help when you have a smaller environment and run a monolithic Jenkins master. In such model, state on the master is lost every time you shut down the Jenkins master service. When using a monolithic Jenkins master on OpenEBS, the volume that stores Jenkins data is persistent and replicated to multiple nodes (defined in your OpenEBS storage class). It means that the master can exit. Even if the node fails, Jenkins can start on other nodes, migrate from private to the public cloud and vice-versa when needed, and your data will follow you everywhere.

As discussed in this AWS Paper, Jenkins installations can be categorized under two scenarios:

  1. A single, monolithic master server with multiple slave nodes connected to it.
  2. Multiple smaller master servers with multiple slave nodes connected to each.

In both scenarios, there is no HA for Jenkins master unless you go with an enterprise Jenkins solution from Cloudbees. Therefore, protecting your storage with OpenEBS storage classes becomes even more important.

Let’s deploy Jenkins on our existing K8s cluster with OpenEBS. You will notice that it’s not much different from deploying on a local storage, except your data will be protected with OpenEBS.

Prerequisites

Software
Cloud Provider

Deploy Jenkins Pod with Persistent Storage

Once you have OpenEBS storage classes created on your K8s cluster, you can use the following simple steps to launch a Jenkins service with a monolithic master.

Before getting started, check the status of the cluster using the following command.

kubectl get nodes

In my environment, I have one master and two worker nodes.

ubuntu@ip-172-23-1-115:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-172-23-1-115.us-west-2.compute.internal Ready master 2h v1.8.3
ip-172-23-1-144.us-west-2.compute.internal Ready <none> 2h v1.8.3
ip-172-23-1-244.us-west-2.compute.internal Ready <none> 2h v1.8.3

Download the Jenkins.yml file to your host, which has access to kubectl.

wget https://raw.githubusercontent.com/openebs/openebs/master/k8s/demo/jenkins/jenkins.yml

This file looks like the text below. You can edit and specify a different OpenEBS storage class before applying.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: jenkins-claim
annotations:
volume.beta.kubernetes.io/storage-class: openebs-standard
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5G
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: jenkins
spec:
replicas: 1
template:
metadata:
labels:
app: jenkins-app
spec:
securityContext:
fsGroup: 1000
containers:
- name: jenkins
imagePullPolicy: IfNotPresent
image: jenkins/jenkins:lts
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /var/jenkins_home
name: jenkins-home
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins-claim
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-svc
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: jenkins-app
type: NodePort

Now apply jenkins.yml file.

ubuntu@kubemaster:~kubectl apply -f jenkins.yml

Get the status of running pods using the following command.

kubectl get pods

Result should like similar to the text below and the Jenkins pod must be running.

ubuntu@ip-172-23-1-115:~$ kubectl get pods
NAME READY STATUS RESTARTS AGE
jenkins-797b888448-pfx8x 1/1 Running 0 11m
maya-apiserver-5994b58bbb-ck2tv 1/1 Running 0 2h
openebs-provisioner-6f45dcf459-qjdlx 1/1 Running 0 2h
pvc-94586807-cb09-11e7-b125-064dff6dc2a2-ctrl-864fcb6f74-2phfw 1/1 Running 0 11m
pvc-94586807-cb09-11e7-b125-064dff6dc2a2-rep-575d85d96c-dk4dq 1/1 Running 0 11m
pvc-94586807-cb09-11e7-b125-064dff6dc2a2-rep-575d85d96c-pzrgn 1/1 Running 0 11m

As you noticed, your OpenEBS controller pvc-...-ctrl-... and two copies of persistent volumes pvc-...-rep-... are also deployed and running.

Get the status of underlying persistent volumes used by Jenkins deployment using the following command.

kubectl get pvc

Example output below:

ubuntu@ip-172-23-1-115:~$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
jenkins-claim Bound pvc-94586807-cb09-11e7-b125-064dff6dc2a2 5G RWO openebs-standard 22m

Get the status of Jenkins service using the following command:

kubectl get svc

Example output below:

ubuntu@ip-172-23-1-115:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
jenkins-svc NodePort 10.3.0.17 <none> 80:31705/TCP 25m
kubernetes ClusterIP 10.3.0.1 <none> 443/TCP 3h
maya-apiserver-service ClusterIP 10.3.0.34 <none> 5656/TCP 3h
pvc-94586807-cb09-11e7-b125-064dff6dc2a2-ctrl-svc ClusterIP 10.3.0.100 <none> 3260/TCP,9501/TCP 25m

Launching Jenkins

The Jenkins deployment YAML file jenkins.yaml used above creates a NodePort service type to make Jenkins available outside the cluster.

Get the node IP Address that is running the Jenkins pod using the following command.

NOTE: Replace your pod name with the pod name returned when you run kubectl get pods command.

kubectl describe pod jenkins-797b888448-pfx8x | grep Node:

Example output below:

kubectl describe pod jenkins-797b888448-pfx8x | grep Node:
Node: ip-172-23-1-144.us-west-2.compute.internal/172.23.1.144

Get the port number from the Jenkins service using the following command:

kubectl describe svc jenkins-svc | grep NodePort:

Example output below:

ubuntu@ip-172-23-1-115:~$ kubectl describe svc jenkins-svc | grep NodePort:
NodePort: <unset> 31705/TCP

The IP adress above is your private IP on AWS. It can be used if you are accesing through another instance on AWS. To access it remotely, you also need to open that port on E2C instance’s security group.

Go to the Network & Security -> Security Group settings in the left-hand navigation menu.
Find the Security Group that your instance belongs to. Click on Inbound Rules. Click on Edit and Add Rule. Then add HTTP (port 31705). Click Save.

Now, combine your public IP and port numbers and open in your browser. In my case, it is https://34.223.235.50:31705.

Once you access the URL, the Getting Started page is displayed. Follow the procedure below to set up Jenkins.

Provide the initialAdminPassword in the Unlock Jenkins screen and copy the password in the Administrator password field. Click Continue.

Get the password using the following command:

kubectl exec -it jenkins-797b888448-pfx8x cat /var/jenkins_home/secrets/initialAdminPassword

Example output below:

ubuntu@ip-172-23-1-115:~$ kubectl exec -it jenkins-797b888448-pfx8x cat /var/jenkins_home/secrets/initialAdminPassword
5aa044d226d1466eb84621e75e369c64

On the Customize Jenkins screen, click Install suggested plugins.


Configure the Administrator user in the Create First Admin User screen. Fill in the following fields.

Username: – Key in the administrator username.
Password: – Key in the password for the administrator.
Confirm password: – Key in the password again and confirm.
Full name: – Key in the administrator’s full name.

Click Continue as admin if you want to perform further administrator tasks or click Save and Finish.
You can now start using Jenkins that is backed by OpenEBS!

Please share:

Also published on Medium.

One thought on “How to deploy Jenkins on Kubernetes + OpenEBS

  1. Aapswdrulp says:

    http://dkjshye7s632.com
    Nice post. I learn something more challenging on different blogs everyday. It’ll at all times be stimulating to learn content from different writers and practice a little bit something from their store. I’d want to make use of some with the content on my blog whether or not you don’t mind. Natually I’ll give you a hyperlink on your net blog. Thanks for sharing.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.