Next up in my migration to K8s is SonarQube. SonarQube needs persistent storage so the first thing to enable is the storage add-on in MicroK8s:
sudo microk8s enable storage
This will give you a Storage Class in K8s. Next thing is to make a deployment for SonarQube that will be using this storage class, by creating a Persistent Volume, a Storage Claim and a Deployment for SonarQube:
apiVersion: v1
kind: PersistentVolume
metadata:
name: sonar-data-disk
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 8Gi
hostPath:
path: /data/sonar
storageClassName: microk8s-hostpath
---
apiVersion: apps/v1
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: sonar-data-disk
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sonarqube
spec:
replicas: 1
selector:
matchLabels:
name: sonarqube
template:
metadata:
name: sonarqube
labels:
name: sonarqube
spec:
nodeName: micro2.singel.home
containers:
- image: sonarqube:latest
name: sonarqube
ports:
- containerPort: 9000
name: sonarqube
volumeMounts:
- name: sonar-data-disk
mountPath: /opt/sonarqube/data
volumes:
- name: sonar-data-disk
persistentVolumeClaim:
claimName: sonar-data-disk
Note that because we are using hostpath Persistent Storage I've bound this deployment to a specific node with nodeName
. This is an issue I will solve in a later post.
I want to use a K8s Ingress for SonarQube because then I will be able to do SSL offloading in there, and I also want this ingress to be loadbalanced. To start off I'll start with enabling those two add-ons to MicroK8s:
sudo microk8s enable ingress
sudo microk8s enable metallb:192.168.1.20-192.168.1.30
To link the two together (the LB to the ingress) you need this:
apiVersion: v1
kind: Service
metadata:
name: lb-ingress
namespace: ingress
spec:
selector:
name: nginx-ingress-microk8s
type: LoadBalancer
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
This should create a loadbalancer IP in the range you gave it when enabling it. In my case 192.168.1.20:
Now if you browse it this IP, it should show you the nginx 404 page:
This is because we still haven't setup our ingress rule. Let's take care of that. First we need to expose the SonarQube application with a ClusterIP Service:
apiVersion: v1
kind: Service
metadata:
name: sonar-service
spec:
selector:
name: sonarqube
ports:
- protocol: TCP
port: 9000
targetPort: 9000
Now we can bind our Ingress rule to this service like this:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-test
spec:
rules:
- host: "sonar.app.singel.home"
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: sonar-service
port:
number: 9000
We should have a working SonarQube at this point, when browsing to the hostname (make sure this dns name resolves first, to the Loadbalancer IP):
This leaves us with only one thing to fix, and that is the certificate used by the ingress service. I will use a self-signed wildcard certificate for that:
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout key.cer -out cert.cer -subj "/CN=.app.singel.home" -addext "subjectAltName=DNS:.app.singel.home"
And import this as a secret into K8s:
kubectl create secret tls ingress-cert --key key.cer --cert cert.cer
Now there are several ways to make the ingress point to this certificate, but in MicroK8s by far the easiest is to disable
and re-enable
the ingress add-on:
sudo microk8s disable ingress
sudo microk8s enable ingress:default-ssl-certificate=default/ingress-cert
And presto, SonarQube is available on https on K8s: