SonarQube is a web-based open source platform used to measure and analyze the source code quality. Code quality analysis makes your code more reliable and more readable.
SonarQube is written in Java but it can analyze and manage code of more than 20 programming languages, including c/c++, PL/SQL, Cobol etc through plugins. Plugins extend the functionality of SonarQube. More than 50 plugins are available.
SonarQube is maintained by SonarSource.
Find about more benefits on https://foxutech.com/benefits-of-sonarqube/
In this post we are going to see how to deploy the SonarQube on Azure Kubernetes Service (AKS), as we have seen in last post How to setup AKS via terraform, I may recommend to use that and setup your environment in Azure.
Prerequisites
- Azure Kubernetes Service up and running
- Kubectl installed in the VM or machine you are going to manage the AKS.
- Postgresql server available, if not please find the optional step below. If you are creating new server, please make sure you have terraform installed in the VM.
Provision Azure PostgreSQL Server (Optional)
You can check our repository https://github.com/foxutech/kubernetes.git.
# git clone https://github.com/foxutech/kubernetes.git
# cd kubernetes/sonarqube/database
Change the required values in the variables.tf or main.tf file. Once all done, please run following terraform commands,
# terraform init # terraform plan # terraform apply
This should help you to create the azure PostgreSQL server, please use the details in the deployment manifest.
Create PersistentVolumeClaims to store SonarQube data
AKS comes with built-in Storage Classes for HDD (default) and SSD (premium) storage: Please refer more details on azure portal and check the storage classes using
# kubectl get sc
As we need to create 2 PVCs as SonarQube uses two locations to store data /opt/sonarqube/data/ and /opt/sonarqube/extensions/. Once you check out the directory, you need to change the directory to kubernetes/sonarqube/application and run the commands or copy the file below and create a files.
PVC for Sonar’s data directory
# cat sonar-data.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: sonar-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 30Gi
PVC for Sonar’s extensions directory
# cat sonar-extensions.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: sonar-extensions
spec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 30Gi
Create the PVC now using following commands,
# kubectl apply -f sonar-data.yaml # kubectl apply -f sonar-extensions.yaml
Create a Secret to store PostgreSQL password
Kubernetes has a built-in capability to store secrets. To create a secret, you need to base64 encode a secret value
# echo -n 'myson@rTempP@$$' | base64
bXlzb25AclRlbXBQQCQk
and create a k8s secret using YAML file as below,
# cat sonar-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: postgres
type: Opaque
data:
#my password is myson@rTempP@$$, change it before using
password: bXlzb25AclRlbXBQQCQk
Create a deployment
After creating PVCs and Postgres secret we are ready to deploy using the following YAML file
Please note, here what we did,
- We have set container limits so that it cannot put cluster node into Out-of-memory state and also used init-containers to set the permissions and elasticsearch vm.max_map_count. (This is mandatory, otherwise you may end with elasticsearch error)
- We use environment variables to pass database connection info to container
# cat sonar-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sonarqube
labels:
app: sonarqube
spec:
replicas: 1
selector:
matchLabels:
app: sonarqube
template:
metadata:
labels:
app: sonarqube
spec:
terminationGracePeriodSeconds: 15
initContainers:
- name: fix-the-volume-permission-extension
image: busybox
command:
- sh
- -c
- chown -R 1000:1000 /opt/sonarqube/extensions
securityContext:
privileged: true
volumeMounts:
- name: sonar-extensions
mountPath: /opt/sonarqube/extensions
- name: fix-the-volume-permission-data
image: busybox
command:
- sh
- -c
- chown -R 1000:1000 /opt/sonarqube/data
securityContext:
privileged: true
volumeMounts:
- name: sonar-data
mountPath: /opt/sonarqube/data
containers:
- name: sonarqube
image: sonarqube
resources:
requests:
cpu: 500m
memory: 1024Mi
limits:
cpu: 2000m
memory: 2048Mi
ports:
- name: sonarqube
containerPort: 9000
env:
- name: SONARQUBE_JDBC_USERNAME
value: "foxutech@devops-tools"
- name: SONARQUBE_JDBC_PASSWORD
valueFrom:
secretKeyRef:
name: postgres
key: password
- name: SONARQUBE_JDBC_URL
value: "jdbc:postgresql://devops-tools.postgres.database.azure.com/sonarqube"
volumeMounts:
- mountPath: /opt/sonarqube/data/
name: sonar-data
- mountPath: /opt/sonarqube/extensions/
name: sonar-extensions
initContainers:
- name: sonarqube-es-init
image: busybox:1.27.2
command: ['sysctl', '-w', 'vm.max_map_count=262144']
securityContext:
privileged: true
volumes:
- name: sonar-data
persistentVolumeClaim:
claimName: sonar-data
- name: sonar-extensions
persistentVolumeClaim:
claimName: sonar-extensions
# kubectl apply -f sonar-deployment.yaml deployment.extensions/sonarqube created
# kubectl get pods
NAME READY STATUS RESTARTS AGE
sonarqube-5c5976bdf5-2dcxv 1/1 Running 0 55m
Once the pod up and running, check the pod logs to check the service is up and running.
# kubectl logs -f sonarqube-5c5976bdf5-2dcxv
2022.04.29 15:46:54 INFO ce[][o.s.c.c.CePluginRepository] Load plugins
2022.04.29 15:46:55 INFO ce[][o.s.c.c.ComputeEngineContainerImpl] Running Community edition
2022.04.29 15:46:56 INFO ce[][o.s.ce.app.CeServer] Compute Engine is started
2022.04.29 15:46:56 INFO app[][o.s.a.SchedulerImpl] Process[ce] is up
2022.04.29 15:46:56 INFO app[][o.s.a.SchedulerImpl] SonarQube is operational
Create the Kubernetes Service
Once you see the service is up, now lets create the Kubernetes service to expose the application to external.
# cat sonar-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: sonarqube
name: sonarqube
spec:
ports:
- name: sonar
port: 80
protocol: TCP
targetPort: 9000
selector:
app: sonarqube
type: LoadBalancer
# kubectl apply -f sonar-svc.yaml
service/sonarqube created
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
sonarqube LoadBalancer 10.0.255.65 20.85.188.179 80:32195/TCP 51m
Now we can hit EXTERNAL-IP address and login to SonarQube, you can find the external IP via command or you can go to services and ingresses in azure portal your AKS service and check the external IP in services tab.
That’s it! Now we have a SonarQube running on azure Kubernetes service. And if one of the nodes fails, pod will be automatically redeployed to a healthy node. For now we have seen Deploy SonarQube on Azure Kubernetes service. in upcoming post will see more example with some different scenarios.