Skip to main content

SonarQube on AKS with Azure Disk - Helm Chart and Persistent Volume Setup

info

Published Date: 20-JUL-2019

As-is, this sonarqube helm chart will survive a deleted pod event, maybe even a helm delete. But if your cluster is rebuilt, or you run a helm delete --purge sonarqube you're going to lose any data and reports that were living with your deployment.

Pre-requirements

  • 2 x AzureDisk
  • 1 x K8s cluster
  • helm
  • kubectl
  • az-cli
tip

installation instructions for these tools can be found here.

Quick K8s Storage Overview

K8s storage took a bit to wrap my head around but essentially when I understood the following topics, it all made sense:

Understanding PersistentVolumes and PersistentVolumeClaims

This video by "IBM FSS FCI and Counter Fraud Management" (no idea why they're called this?!) is probably the clearest explanation I've seen online.

The abstractions: Volumes, PV, StorageClasses and PVC's

Here's a diagram:

AKS PV PVC

Essentially, in an oversimplified nutshell:

  • Volumes are derived from Physical Disks that an Admin provisions
  • PersistentVolumes (static) are an abstraction of the Physical Disks
  • StorageClasses (dynamic) are also an abstraction of the Physical Disks
  • PersistentVolumeClaims is what the Pod will actually mount as a "volume". The PVC will determine if you'll be mounting a static PV, or a storageClass Volume.

Right, so now that we've got that out of the way, let's build some things.

Provision your AzureDisks

  • 1 x sonarqube data disk
  • 1 x postgresql database disk
az disk create -g AKS-CLOUDRESOURCES -n sonarqube-data --size-gb 10 --sku Standard_LRS --tags application=sonarqube
az disk create -g AKS-CLOUDRESOURCES -n postgresql-data --size-gb 16 --sku Standard_LRS --tags application=postgresql

example output for sonarqube disk

{
"creationData": {
"createOption": "Empty",
"imageReference": null,
"sourceResourceId": null,
"sourceUri": null,
"storageAccountId": null
},
"diskIopsReadWrite": 500,
"diskMbpsReadWrite": 60,
"diskSizeGb": 10,
"encryptionSettings": null,
"id": "/subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/resourceGroups/AKS-CLOUDRESOURCES/providers/Microsoft.Compute/disks/sonarqube-data",
"location": "australiaeast",
"managedBy": null,
"name": "sonarqube-data",
"osType": null,
"provisioningState": "Succeeded",
"resourceGroup": "AKS-CLOUDRESOURCES",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"tags": {
"application": "sonarqube"
},
"timeCreated": "2019-07-23T11:01:16.893039+00:00",
"type": "Microsoft.Compute/disks",
"zones": null
}

storageClass.yaml

Create your storage class. Notice the Retain reclaimPolicy so that the volumes aren't deleted when pods and container disappear.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: staticManagedVolumeRetain
provisioner: kubernetes.io/azure-disk
parameters:
kind: Managed
storageaccounttype: Standard_LRS
reclaimPolicy: Retain

apply

kubectl apply -f storageClass.yaml

Sonarqube Helm Chart

Grab a copy of the official sonarqube helm chart from Github

Update sonarqube values.yaml

add these values to the values.yaml file

persistence:
enabled: true
storageClass: "staticManagedVolumeRetain"
accessMode: ReadWriteOnce
size: 5Gi

azureDisk:
kind: Managed
diskName: sonarqube-data
diskURI: /subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/resourceGroups/AKS-CLOUDRESOURCES/providers/Microsoft.Compute/disks/sonarqube-data

Create pv.yaml for sonarqube chart

Place this under /sonarqube/templates/

sonarqube-pv.yaml
\{\{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) \}\}
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv-\{\{ template "sonarqube.name" . \}\}-data
labels:
app: \{\{ template "sonarqube.name" . \}\}
chart: "\{\{ .Chart.Name \}\}-\{\{ .Chart.Version \}\}"
release: "\{\{ .Release.Name \}\}"
heritage: "\{\{ .Release.Service \}\}"
spec:
capacity:
storage: \{\{ .Values.persistence.size \}\}
storageClassName: \{\{ .Values.persistence.storageClassName | quote \}\}
azureDisk:
kind: \{\{ .Values.azureDisk.kind | quote \}\}
diskName: \{\{ .Values.azureDisk.diskName | quote \}\}
diskURI: \{\{ .Values.azureDisk.diskURI | quote \}\}
accessModes:
- \{\{ .Values.persistence.accessMode | quote \}\}
\{\{- end \}\}

PostgreSQL Helm Sub Chart

We are going to use this PostgreSQL helm chart as a subchart to sonarqube.

  1. Create a directory called '/charts/' in the sonarqube root directory.
  2. Download the postgresql chart into /charts/.
  3. Make the following changes.

Add postgresql values.yaml

Add the following values (that match the azureDisk's you provisioned earlier).

persistence:
enabled: true
storageClass: "staticManagedVolumeRetain"
accessMode: ReadWriteOnce
size: 5Gi

azureDisk:
kind: Managed
diskName: postgresql-data
diskURI: /subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/resourceGroups/AKS-CLOUDRESOURCES/providers/Microsoft.Compute/disks/postgresql-data

Create pv.yaml for PostgreSQL sub-chart

Place this under /post/templates/:

sonarqube-pv.yaml
\{\{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) \}\}
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv-\{\{ template "sonarqube.name" . \}\}-data
labels:
app: \{\{ template "sonarqube.name" . \}\}
chart: "\{\{ .Chart.Name \}\}-\{\{ .Chart.Version \}\}"
release: "\{\{ .Release.Name \}\}"
heritage: "\{\{ .Release.Service \}\}"
spec:
capacity:
storage: \{\{ .Values.persistence.size \}\}
storageClassName: \{\{ .Values.persistence.storageClassName | quote \}\}
azureDisk:
kind: \{\{ .Values.azureDisk.kind | quote \}\}
diskName: \{\{ .Values.azureDisk.diskName | quote \}\}
diskURI: \{\{ .Values.azureDisk.diskURI | quote \}\}
accessModes:
- \{\{ .Values.persistence.accessMode | quote \}\}
\{\{- end \}\}

Zip PostgreSQL (optional)

After adding the pv.yaml file to the postgresql/templates directory and adding the details into the postgresql values.yaml file you can tar zip that up so as postgresql-0.8.3.tgz and make sure it can be found under sonarqube/charts folder.

You can also just keep the files unzipped in their folders under sonarqube/charts/postgresql/ etc.

Worse case scenario none of this makes sense and is hard to follow - have a look at my git repo with the files laid out how it worked for me: https://github.com/ronamosa/sonarqube-static-disks.gitng}

Helm deploy chart

You can now run whatever helm deploy line you usually do to put that badboy into your k8s cluster.

Test the persistence by doing a

  • helm delete --purge sonarqube or
  • terraform destroy myAksCluster

and watch when you re-deploy sonarqube that the deployment will find and mount the existing PV's into the pod and you'll see all your previous sonarqube data.

References

Enjoying the docs? Good.

The docs are the how. The newsletter is the what... as in, what the f*** — AI, power, Big Tech and the tech industry, through a Pasifika lens, from an engineer who's spent twenty-plus years working inside the machine. Fortnightly. No filter.

Leave whenever.

Get the newsletter →