How To Install Jenkins On A Kubernetes Cluster
Introduction
Jenkins is a CI tool ( continuous integration) that automates a large portion of the software development process. Several development teams working on multiple projects in a complex microservices environment can be a strain on limited resources. In this tutorial, you will learn how to install Jenkins and create a CI/CD pipeline.
Prerequisites
- Docker installed on your server.
- A Kubernetes cluster.
- Root privileges.
Jenkins Installation On Kubernetes
Jenkins installation is consisting of 5 steps:
-
-
-
-
Namespace creation for the Jenkins Deployment
To isolate our Jenkings deployment from the rest of the namespaces that might exist (dev, staging, production) a separate namespace will provide the essential layer of isolation we need to our environment. Create a namespace for your Jenkins deployment by executing the following command on your terminal:
kubectl create namespace jenkins
You will see the output:
namespace/jenkins created
And if you execute:
kubectl get namespaces
You will see:
NAME STATUS AGE default Active 11d jenkins Active 2m34s kube-node-lease Active 11d kube-public Active 11d kube-system Active 11d kubernetes-dashboard Active 11d
-
Create a Jenkins Service Account, Role, and Rolebinding.
Now that we have created our namespace, we shall create a jenkins-service-account.yaml file. The service account, the role, and the role binding are all necessary for Jenkins to be able to have the appropriate permissions to connect to the cluster, create new pods, delete pods etc:
apiVersion: v1 kind: ServiceAccount metadata: name: jenkins namespace: jenkins --- kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: jenkins namespace: jenkins rules: - apiGroups: [""] resources: ["pods"] verbs: ["create","delete","get","list","patch","update","watch"] - apiGroups: [""] resources: ["pods/exec"] verbs: ["create","delete","get","list","patch","update","watch"] - apiGroups: [""] resources: ["pods/log"] verbs: ["get","list","watch"] - apiGroups: [""] resources: ["events"] verbs: ["watch"] - apiGroups: [""] resources: ["secrets"] verbs: ["get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: jenkins roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: jenkins subjects: - kind: ServiceAccount name: jenkins
Save the file and exit. Now we will apply to this service account and rules to the Jenkins namespace we already created. Execute the command:kubectl apply -n jenkins -f jenkins-service-account.yaml
As you noticed, we deployed the Jenkins service account into the Kubernetes Jenkins namespace.
-
Create Jenkins Services.
Now we need to create the appropriate Services. A Kubernetes Service is an abstraction that exposes an application (in our case Jenkins pod(s) )to the Internet.
We will create 2 services. The first one will have a type NodePort for exposing Jenkins user interface to us at port 32000, and a second Service which will handle all the internal workins. Create a file jenkins-services.yaml file, as shown below:
apiVersion: v1 kind: Service metadata: name: jenkins-ui spec: type: NodePort selector: app: jenkins ports: - port: 8080 targetPort: 8080 nodePort: 32000 selector: app: jenkins --- apiVersion: v1 kind: Service metadata: name: jenkins labels: app: jenkins spec: type: ClusterIP ports: - name: jenkins-ui port: 8080 targetPort: 8080 protocol: TCP - name: jenkins-agent port: 50000 protocol: TCP - name: http port: 80 targetPort: 8080 selector: app: jenkins
In the next step, we will apply our Services to the Cluster.
-
Deploy Jenkins Services
Now that everything is in place, it’s time to see our services taking shape:
kubectl apply -n jenkins -f jenkins-services.yaml
-
Create a Jenkins Stateful Set
This is basically the core of Jenkins deployment. Like a Kubernetes Deployment, a StatefulSet manages Pods that are based on an identical container specification. Unlike a Deployment, a StatefulSet maintains a sticky identity for each of their Pods. These pods are created from the same specifications, but are not interchangeable: each one of them is having a persistent identifier which is maintained unchanged across any rescheduling or server restarts. StatefulSets are a very important Kubernetes function for applications requiring stable, unique network identifiers, stable and persistent storage, graceful deployment, automated rolling updates, and horizontal scaling.
Let’s create a file jenkins-stateful.yaml, with the following content:apiVersion: apps/v1 kind: StatefulSet metadata: name: jenkins spec: selector: matchLabels: app: jenkins # has to match .spec.template.metadata.labels serviceName: jenkins replicas: 1 template: metadata: labels: app: jenkins name: jenkins name: jenkins spec: serviceAccountName: jenkins terminationGracePeriodSeconds: 10 containers: - env: - name: JAVA_OPTS value: -Xmx2048m -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85 name: jenkins image: jenkins/jenkins:lts-alpine ports: - containerPort: 8080 name: jenkins - containerPort: 50000 name: jenkins-agent volumeMounts: - name: jenkins-home mountPath: /var/jenkins_home volumes: - name: jenkins-home emptyDir: {}
-
Apply Jenkins Stateful Set
Apply the above stateful set using the command:
kubectl apply -n jenkins -f jenkins-stateful.yaml
-
Open Jenkins In Your Browser.
Visit Http://<node_address>:32000 in your browser to open the initial Jenkins setup wizard.
At that point, you will need the auto-generated password that Jenkins created. This can be found easily but checking the Kubernetes logs for the jenkins-0 pod that is currently running.
This can be done by issuing the commands:kubectl get pods -n jenkins
Output:
NAME READY STATUS RESTARTS AGE jenkins-0 1/1 Running 0 2h
And,
kubectl logs jenkins-0 -n jenkins
Output,
2020-05-23 13:01:26.939+0000 [id=25] INFO o.s.b.f.s.DefaultListableBeanFactory#preInstantiateSingletons: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@64487588: defining beans [filter,legacy]; root of factory hierarchy 2020-05-23 13:01:27.129+0000 [id=25] INFO jenkins.install.SetupWizard#init: ************************************************************* ************************************************************* ************************************************************* Jenkins initial setup is required. An admin user has been created and a password generated. Please use the following password to proceed to installation: ae7e043ee34047be8f7d84fd59b9586b This may also be found at: /var/jenkins_home/secrets/initialAdminPassword ************************************************************* ************************************************************* ************************************************************* 2020-05-23 13:01:36.346+0000 [id=25] INFO jenkins.InitReactorRunner$1#onAttained: Completed initialization 2020-05-23 13:01:36.351+0000 [id=19] INFO hudson.WebAppMain$3#run: Jenkins is fully up and running 2020-05-23 13:01:36.579+0000 [id=39] INFO h.m.DownloadService$Downloadable#load: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller 2020-05-23 13:01:36.580+0000 [id=39] INFO hudson.util.Retrier#start: Performed the action check updates server successfully at the attempt #1 2020-05-23 13:01:36.582+0000 [id=39] INFO hudson.model.AsyncPeriodicWork#lambda$doRun$0: Finished Download metadata. 10,521 ms
Copy the password and past it to the appropriate field. By continuing the setup, you will be asked to create a new user account and create and another one.
-
-
-