SQL Server on Kubernetes and MetalLB
SQL Server containers on Kubernetes and Pure Storage with MetalLB
In this Blog I will show you how we can use a combination of Kubernetes, Pure Service Orchestrator ( PSO ) and MetalLB to create a load balanced Kubernetes cluster for SQL Server
Pure Service Orchestrator allows for smart provisioning of storage to one or many arrays, this provides administrators and developers the ability to provision storage on demand with cloud like functionality, ease and flexibility.
Pure Service Orchestrator ( PSO ) is used to automate the provisioning of volumes to Kubernetes which will then be used to create the SQL Server containers using persistent storage.
MetalLB is a load-balancer implementation for bare metal Kubernetes clusters, using standard routing protocols.
Environment
Role | FQDN | IP | OS | RAM | CPU | K8 Ver |
---|---|---|---|---|---|---|
Master | k8master | 192.168.111.228 | Ubuntu 18.04 | 8G | 3 | 1.18.2 |
Worker1 | k8worker1 | 192.168.111.229 | Ubuntu 18.047 | 8G | 4 | 1.18.2 |
Worker2 | k8worker2 | 192.168.111.230 | Ubuntu 18.047 | 8G | 4 | 1.18.2 |
I already have a Ubuntu Cluster up and running, so I wont be going through the install process in this blog
- Let's check the cluster status
root@k8master:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8master Ready master 140d v1.18.2
k8worker1 Ready <none> 140d v1.18.2
k8worker2 Ready <none> 140d v1.18.2
- Let's check to see if we have any pod or services deployed
root@k8master:~# kubectl get pods
No resources found in default namespace.
oot@k8master:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hollowdb ClusterIP 10.111.175.138 <none> 3306/TCP 140d
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 140d
As you can see from the above output, we have no PODS and no SERVICES.
Lets' check to make sure the PSO namespace has been configure
root@k8master:~# kubectl get ns
NAME STATUS AGE
default Active 140d
oradb Active 139d
pso Active 140d
- Now let's create a new SQL Server deployment called mssql-deployment, the deployment will do a few things
- Create the persistent volume claim
- Deploy SQL Server using the persistent volume
- Create the SQL server service
root@k8master:~# kubectl apply -f cbsql.yaml
persistentvolumeclaim/pvc-sql-system unchanged
deployment.apps/mssql-deployment configured
service/mssql-deployment created
Here is a link to the deployment yaml - sql server yaml file
- Let's confirm our POD is running
root@k8master:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
mssql-deployment-df565f596-zkb87 1/1 Running 0 48s
- Let's have a closer look, as you can see, the POD has started on node K8worker2, its up and running and uses the 2019-CU4-ubuntu-18.04 image
root@k8master:~# kubectl describe pods mssql-deployment
Name: mssql-deployment-df565f596-zkb87
Namespace: default
Priority: 0
Node: k8worker2/192.168.111.230
Start Time: Tue, 22 Sep 2020 10:03:37 +1000
Labels: app=mssql
pod-template-hash=df565f596
Annotations: <none>
Status: Running
IP: 10.244.2.18
IPs:
IP: 10.244.2.18
Controlled By: ReplicaSet/mssql-deployment-df565f596
Containers:
mssql:
Container ID: docker://db2f3fcfc04b0717db90a146435a2f5476bc88bd415a67710a123ecbe7e1e80e
Image: mcr.microsoft.com/mssql/server:2019-CU4-ubuntu-18.04
Image ID: docker-pullable://mcr.microsoft.com/mssql/server@sha256:360f6e6da94fa0c5ec9cbe6e391f411b8d6e26826fe57a39a70a2e9f745afd82
Port: 1433/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 22 Sep 2020 10:03:43 +1000
Ready: True
Restart Count: 0
Environment:
ACCEPT_EULA: Y
SA_PASSWORD: <set to the key 'SA_PASSWORD' in secret 'mssql'> Optional: false
Mounts:
/var/opt/mssql from mssql-system (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-kj8td (ro)
- Let's log onto worker node 2 and confirm the container is running
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
86b9292ec4c9 mcr.microsoft.com/mssql/server "/opt/mssql/bin/perm…" 2 hours ago Up 2 hours k8s_mssql_mssql-deployment-df565f596-nnctl_default_9b1076d6-bf4c-4c0a-a977-c4f65ce1a9a3_0
- Lets check our persistent volumes, we can see that the volume sqldatavol has been create
NAME STATUS VOLUME CAPACITY ACCES MODE STORAGECLASS AGE
sqldatavol Bound pvc-79bf05e7-4ef7-4355-95e6-76243dded23f 10Gi RWO pure-block 45h
- Let's connect to the container, notice the persistent volume created by PSO
root@k8worker2:~# docker exec -it 86b9292ec4c9 bash
mssql@mssql-deployment-df565f596-nnctl:/$
mssql@mssql-deployment-df565f596-nnctl:/$
mssql@mssql-deployment-df565f596-nnctl:/$ df -k
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 102685624 18154400 79272064 19% /
tmpfs 65536 0 65536 0% /dev
tmpfs 4084140 0 4084140 0% /sys/fs/cgroup
/dev/sda1 102685624 18154400 79272064 19% /etc/hosts
shm 65536 0 65536 0% /dev/shm
/dev/mapper/3624a9370a21265762db64ece00092e5c 10475520 197468 10278052 2% /var/opt/mssql
tmpfs 4084140 12 4084128 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 4084140 0 4084140 0% /proc/acpi
tmpfs 4084140 0 4084140 0% /proc/scsi
tmpfs 4084140 0 4084140 0% /sys/firmware
mssql@mssql-deployment-df565f596-nnctl:/$ ps -ef|grep sql
mssql 1 0 0 01:38 ? 00:00:00 /opt/mssql/bin/sqlservr
mssql 9 1 1 01:38 ? 00:02:14 /opt/mssql/bin/sqlservr
mssql 1344 0 0 03:49 pts/0 00:00:00 bash
mssql 1356 1344 0 03:49 pts/0 00:00:00 ps -ef
mssql 1357 1344 0 03:49 pts/0 00:00:00 grep sql
The serial number of the volume ending in 2e5c, maps to the volume created by PSO
At this point I can connect to the database using the port specified in the service section of the yaml file ( 31433 ), It's a cluster wide port number, however - we need to specify the worker node IP address, so if the pod moves to another worker node, we need to specify the other nodes IP address. A better way is to create a load-Balanced IP address which allows us to connect to one IP address regardless of which node the service is running on. This is where MetalLB comes into play.
---
apiVersion: v1
kind: Service
metadata:
name: mssql-deployment
spec:
selector:
app: mssql
ports:
- protocol: TCP
port: 31433
targetPort: 1433
type: LoadBalancer
Install and configure MetalLB.
Download metalLB from https://metallb.universe.tf/
Select the installation TAB, select installation manifest, copy the code and run it on your cluster
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
# On first install only
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
Ok, let's check to make sure metalLB is installed. First lets check to make sure the namespace has been created.
root@k8master:~# kubectl get ns
NAME STATUS AGE
default Active 140d
metallb-system Active 12h
oradb Active 139d
pso Active 140d
Next, we need to deploy the configuration, we will deploy this using a configmap. Go to the configuration tab on the metallb web page select the Layer 2 configuration
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.111.240-192.168.111.245
In the above configmap, I have configured my Load balancer to use the address range 192.168.111.240 - 192.168.111.245
Let's create the configmap called config
root@k8master:~# kukectl create -f configmap
configmap/config created
root@k8master:~# kubectl describe configmap config -n metallb-system
Name: config
Namespace: metallb-system
Labels: <none>
Annotations: <none>
Data
====
config:
----
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.111.240-192.168.111.245
Now if everything has worked correctly, I should have an external-IP assigned to my mssql-deployment
root@k8master:~# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hollowdb ClusterIP 10.111.175.138 <none> 3306/TCP 140d
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 140d
mssql-deployment LoadBalancer 10.99.155.157 192.168.111.240 31433:30402/TCP 45m
- As we can see from the above output, my mssql deployment how has a load balanced IP address assigned to it ( 192.168.111.240) which is from the range I specified
Now I should be able to connect to my MSSQL database using the 192.168.111.240 IP and port 31433
I'm using SQLPro for MSSQL on a MAC, lets setup the connection details using the 192.168.111.240 IP address
![]() |
Setup database credentials |
![]() |
Logged into the database |
![]() |
Lets create a new database called demo1 |
![]() |
Database created |
Summary
- In this blog I have shown you how we can use MetalLB in our Kubernetes cluster to create a load balanced service for Microsoft SQL Server
Comments