Introduction

In a previous article, I showed you how you can get up and running with a development OpenShift evironment running on your laptop / work station using Minishift. In this article, I will do the same, but with Minikube and show you how to get started by deployment a Jenkins pod and service with an external “load balencer” to access from your local web browser.

This article assumes the use of a Fedora / RedHat environment using KVM as a Hypervisor.

Deployment

To begin with, we’ll update our system and ensure libvirt is installed. Run through the following on your workstation:

$ sudo dnf -y update
$ sudo dnf -y install bridge-utils libvirt virt-install qemu-kvm
$ sudo dnf -y install virt-top libguestfs-tools
$ sudo systemctl enable --now libvirtd

In order to administer libvirt with the current user, we’ll add that user to the appropriate group:

$ sudo usermod -a -G libvirt $(whoami)

Next, we’ll install kubectl which will enable us to interact with our Kubernetes “cluster”:

$ wget https://storage.googleapis.com/kubernetes-release/release/v1.16.0/bin/linux/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl
$ kubectl version

One precursor we require to running minikube on KVM, is the Docker machine driver for KVM. As we’re installing KVM and Minikube on a RedHat family OS (Fedora in this case) we’ll use the CentOS Docker KVM driver from GitHub@

$ wget https://github.com/dhiltgen/docker-machine-kvm/releases/download/v0.10.0/docker-machine-driver-kvm-centos7
$ sudo cp docker-machine-driver-kvm-centos7 /usr/local/bin/docker-machine

Next, we will download and install minikube:

$ wget https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
$ sudo chmod +x minikube-linux-amd64
$ sudo mv minikube-linux-amd64 /usr/local/bin/minikube

And finally, we shall check our version of minikube and start our single node cluster on KVM:

$ minikube version
$ minikube start cpus=2 memory=8192

After a short time, if all goes well you should have a single node kubernetes cluster running. Next, we’ll check minikube is available:

$ minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Next, we’ll check on the status of Kubernetes:

$ kubectl get pods --all-namespaces
NAMESPACE     NAME                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-5644d7b6d9-bt4j6           1/1     Running   0          6m5s
kube-system   coredns-5644d7b6d9-nt47t           1/1     Running   0          6m5s
kube-system   etcd-minikube                      1/1     Running   0          5m6s
kube-system   kube-addon-manager-minikube        1/1     Running   0          5m5s
kube-system   kube-apiserver-minikube            1/1     Running   0          5m3s
kube-system   kube-controller-manager-minikube   1/1     Running   0          5m14s
kube-system   kube-proxy-bjz2j                   1/1     Running   0          6m5s
kube-system   kube-scheduler-minikube            1/1     Running   0          4m53s
kube-system   storage-provisioner                1/1     Running   0          5m4s

And finally, we’ll launch the Kubernetes dashboard using the minikube cli:

$ minikube dashboard

k8s-dash

Now we’ll create a namespace for the Jenkins deployment will make on the cluster later. Simply create a text file called “jenkins-namespace.yml” in your current working directory and paste the following:

apiVersion: v1
kind: Namespace
metadata:
  name: jenkins-ns

With the file created, we’ll apply it to the cluster:

kubectl apply -f jenkins-namespace.yml

Once complete, we’ll check the namespace has applied:

$ kubectl get namespace
NAME                   STATUS   AGE
default                Active   6h48m
jenkins-ns             Active   6m44s
kube-node-lease        Active   6h48m
kube-public            Active   6h48m
kube-system            Active   6h48m
kubernetes-dashboard   Active   4h1m

Installing and initialising helm

Now that we have a single node kubernetes cluster running using KVM and minikube, we’ll move onto istalling and deploying helm in order to set up a jenkins deployment on our environment. Helm isn’t 100% necessary, as we can manually create a deployment manifest and appply that to our cluster, but helm does offer a quick and easy solution for deplyment to our development scenario on minikube.

At the time of writing, Helm 3 has just been released and as a result we will use that.

First, we’ll grab the amd64 helm binary and copy it to our bin directory so that it is our $PATH in a similar fashion to what we have done previously:

$ wget https://get.helm.sh/helm-v3.0.0-linux-amd64.tar.gz
$ tar -xvf helm-v3.0.0-linux-amd64.tar.gz
$ sudo chmod +x linux-amd64/helm
$ sudo cp linux-amd64/helm /usr/local/bin/

With that, we’ll check our helm version:

$ helm version
version.BuildInfo{Version:"v3.0.0", GitCommit:"e29ce2a54e96cd02ccfce88bee4f58bb6e2a28b6", GitTreeState:"clean", GoVersion:"go1.13.4"}

Fantastic, helm is now installed and added to your execution path. The next stage, is to deploy jenkins on our cluster.

Deploying Jenkins

Enter the following commands, which will add the Kubernetes stable charts to helm (from Google), update te helm chart repository and install Jenkins into our namespace that we created earlier:

$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/
$ helm repo update
$ helm install jenkins-release stable/jenkins --namespace jenkins-ns

With that done, Kubernetes will start the deployment and pull down the relative containers and bring the pod up. We can watch and wait for the pod to provision:

$ kubectl get pods --namespace=jenkins-ns -w
NAME                               READY   STATUS    RESTARTS   AGE
jenkins-release-699b5d6b89-qtlzg   0/1     Running   0          94s

Which when running, will mean the deployment is raedy:

$ kubectl get deployment --namespace=jenkins-ns
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
jenkins-release   1/1     1            1           5m19

Next, we need to make Jenkins available externally. To do that, we need to add a “load balancer” in minikube. If you check for the running service, you’ll see there presently isn’t an external route to the pod:

$ kubectl get service --namespace=jenkins-ns
NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
jenkins-release         ClusterIP   10.109.131.64    <none>        8080/TCP    8m37s
jenkins-release-agent   ClusterIP   10.104.201.155   <none>        50000/TCP   8m37s

Creating a load balencer in Minikube for external access

We’ll now get that slightly fundamental issue resolved. Minikube has an inbuilt cloud provider which will give us a loadbalencer infront of the service:

$ kubectl expose deployment jenkins-release --namespace jenkins-ns --type=NodePort --name=jenkins-service
$ minikube service jenkins-release -n jenkins-service

With that, your browser should open automatically and take you to the jenkins logon screen. We just need the jenkins password for the admin user, which we can get from Kubernetes’ secrets manager:

printf $(kubectl get secret jenkins-release -o jsonpath="{.data.jenkins-admin-password}" --namespace jenkins-ns | base64 --decode);echo

Congratulations! you just configured minikube in your Fedora workstation, and deployed a development jenkins evironment from which you can run your build pipelines.