How to Install Jenkins on Vultr Kubernetes Engine
Jenkins is an open-source continuous-integration (CI) and continuous-delivery (CD) server used for project development, deployment, and automation. Software developers use it to build, test, and deploy their software. It is written in Java and provides hundreds of plugins to automate testing and changes in a larger code base.
This guide shows you how to set up Jenkins on Vultr Kubernetes Engine, which provides many benefits over standalone server-based deployment. Kubernetes-based deployment is a very cost-effective solution and also decreases the time needed for development.
Prerequisites
- Deploy a Vultr Ubuntu 20.04 instance to use as a management workstation.
- Deploy a Kubernetes cluster at Vultr with at least three or more nodes with 2GB RAM and 2 CPUs.
- Install kubectl on Vultr Ubuntu management workstation.
You'll perform the rest of the steps in this guide from your management workstation.
Verify Kubernetes Cluster
Before starting, verify the Vultr Kubernetes Cluster using the following command:
kubectl cluster-info
You will see the Cluster information in the following output:
Kubernetes control plane is running at https://e4737bcd-3971-4624-b896-0181aae56bae.vultr-k8s.com:6443
CoreDNS is running at https://e4737bcd-3971-4624-b896-0181aae56bae.vultr-k8s.com:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To check the active status of all Cluster nodes, run the following command:
kubectl get nodes
You should see that all nodes are in ready status:
NAME STATUS ROLES AGE VERSION
jenkins-cluster-136e69da18fb Ready <none> 3m21s v1.25.4
jenkins-cluster-97b1dd155b22 Ready <none> 3m21s v1.25.4
jenkins-cluster-a329dcb28ac7 Ready <none> 3m21s v1.25.4
Install Jenkins on Kubernetes
First, create the Jenkins namespace:
# kubectl create namespace jenkins-namespace
Output.
namespace/jenkins-namespace created
Next, create a
serviceAccount.yaml
file.# nano serviceAccount.yaml
Add the following configurations to create a service account called
jenkins-account
and binds theclusterRole
to the service account.--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: jenkins-account rules: - apiGroups: [""] resources: ["*"] verbs: ["*"] --- apiVersion: v1 kind: ServiceAccount metadata: name: jenkins-account namespace: jenkins-namespace --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: jenkins-account roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: jenkins-account subjects: - kind: ServiceAccount name: jenkins-account namespace: jenkins-namespace
Apply the above configuration to Kubernetes Cluster.
# kubectl apply -f serviceAccount.yaml
Output.
clusterrole.rbac.authorization.k8s.io/jenkins-account created serviceaccount/jenkins-account created clusterrolebinding.rbac.authorization.k8s.io/jenkins-account created
Create a volume configuration file.
# nano volume.yaml
Add the following configuration for persistent volume.
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: jenkins-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer --- apiVersion: v1 kind: PersistentVolume metadata: name: jenkins-pv-volume labels: type: local spec: storageClassName: jenkins-storage claimRef: name: jenkins-pv-claim namespace: jenkins-namespace capacity: storage: 10Gi accessModes: - ReadWriteOnce local: path: /opt nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - jenkins-cluster-136e69da18fb --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jenkins-pv-claim namespace: jenkins-namespace spec: storageClassName: jenkins-storage accessModes: - ReadWriteOnce resources: requests: storage: 3Gi
Note: Replace the
jenkins-cluster-136e69da18fb
with any of your cluster nodes.If you need to know the hostname of your worker node, run the following command.
# kubectl get nodes
The above configuration will create a
PersistentVolume
volume in a cluster node inside the/opt
directory. You will also need to properly define the worker node name for the Jenkins pod to get scheduled in the specific node.Create a persistent volume on the Kubernetes cluster using the
kubectl
command.# kubectl create -f volume.yaml
Output.
storageclass.storage.k8s.io/jenkins-storage created persistentvolume/jenkins-pv-volume created persistentvolumeclaim/jenkins-pv-claim created
Create a
deployment.yaml
file.# nano deployment.yaml
Add the following manifest configuration.
apiVersion: apps/v1 kind: Deployment metadata: name: jenkins namespace: jenkins-namespace spec: replicas: 1 selector: matchLabels: app: jenkins-server template: metadata: labels: app: jenkins-server spec: securityContext: fsGroup: 1000 runAsUser: 1000 serviceAccountName: jenkins-account 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-pv-claim
The above configuration file will:
- Creates a Jenkins deployment using the latest Jenkins image and opens ports
8080
and50000
to accept connections from Jenkins workers. - Mounts the persistent volume on the
/var/jenkins_home
directory to hold Jenkins data. - Define
liveness probes
to check the container's health status. - Define
readiness probes
to know when a container can start accepting traffic.
- Creates a Jenkins deployment using the latest Jenkins image and opens ports
Apply the above deployment to the Kubernetes cluster.
# kubectl apply -f deployment.yaml
Output.
deployment.apps/jenkins created
Wait for some time to pull the Jenkins image and get the Jenkins pod running.
Verify the status of the Jenkins pod.
# kubectl get deployments -n jenkins-namespace
Output.
NAME READY UP-TO-DATE AVAILABLE AGE jenkins 1/1 1 1 94s
Get a detail information about Jenkins deployment.
# kubectl describe deployments --namespace=jenkins-namespace
Output.
Name: jenkins Namespace: jenkins-namespace CreationTimestamp: Tue, 22 Nov 2022 21:03:42 +0530 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=jenkins-server Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=jenkins-server Service Account: jenkins-account Containers: jenkins: Image: jenkins/jenkins:lts Ports: 8080/TCP, 50000/TCP Host Ports: 0/TCP, 0/TCP Limits: cpu: 1 memory: 2Gi Requests: cpu: 500m memory: 500Mi Liveness: http-get http://:8080/login delay=90s timeout=5s period=10s #success=1 #failure=5 Readiness: http-get http://:8080/login delay=60s timeout=5s period=10s #success=1 #failure=3 Environment: <none> Mounts: /var/jenkins_home from jenkins-data (rw) Volumes: jenkins-data: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: jenkins-pv-claim ReadOnly: false Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: jenkins-7b95fb694 (1/1 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 19m deployment-controller Scaled up replica set jenkins-7b95fb694 to 1
Create Kubernetes Service for External Access
At this point, Jenkins is successfully deployed and running on the Kubernetes cluster. However, you can not access Jenkins from the remote machine. In this case, you will need to create a service and bind it to the Jenkins deployment.
First, create a
service.yaml
file using the following command:# nano service.yaml
Add the following configurations to expose port
8080
of the Jenkins pod to port32000
.apiVersion: v1 kind: Service metadata: name: jenkins-service namespace: jenkins-namespace 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
Next, deploy the service configuration to the Jenkins deployment.
# kubectl apply -f service.yaml
Output.
service/jenkins-service created
Verify the status of the Jenkins service.
# kubectl get services --namespace jenkins-namespace
Output.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE jenkins-service NodePort 10.103.86.99 <none> 8080:32000/TCP 6s
Access Jenkins Web Interface
At this point, Jenkins is installed and listens on port 32000 for external access. Now, you will need to retrieve the IP address of the cluster node to access the Jenkins web interface.
First, get a node IP address using the
kubectl
command.# kubectl get nodes -o wide
You will get the external IP of all nodes in the following output.
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL- VERSION CONTAINER-RUNTIME jenkins-cluster-7e8eba45f3a6 Ready <none> 23m v1.25.4 10.46.96.6 65.20.79.223 Debian GNU/Linux 10 (buster) 4.19.0-22-amd64 containerd://1.6.9 jenkins-cluster-a45a12e27a63 Ready <none> 23m v1.25.4 10.46.96.5 65.20.79.2 Debian GNU/Linux 10 (buster) 4.19.0-22-amd64 containerd://1.6.9 jenkins-cluster-cfacc64361f5 Ready <none> 23m v1.25.4 10.46.96.4 65.20.74.173 Debian GNU/Linux 10 (buster) 4.19.0-22-amd64 containerd://1.6.9
Next, open your web browser and access Jenkins using the URL
http://node-external-ip:32000
. You will be asked to provide the initial Admin password.Get Jenkins pod details using the following command.
# kubectl get pods --namespace=jenkins-namespace
Output.
NAME READY STATUS RESTARTS AGE jenkins-7b95fb694-5xqnp 1/1 Running 0 20m
Check the Jenkins pod logs to retrieve the Jenkins Admin password.
# kubectl logs jenkins-7b95fb694-5xqnp --namespace=jenkins-namespace
Output.
************************************************************* Jenkins initial setup is required. An admin user has been created and a password generated. Please use the following password to proceed to installation: a1f057cba5f6440f863b6e5a57d880fa This may also be found at: /var/jenkins_home/secrets/initialAdminPassword *************************************************************
Copy the password from the above output and enter it on the Jenkins initial Admin password screen to proceed with the Jenkins installation.
Conclusion
This guide shows you how to install and configure Jenkins on Vultr Kubernetes Engine. Jenkins is a core component of CI/CD pipelines. It helps you perform very complex operations and increase productivity. For more information, check out the official Jenkins documentation.