Skip to main content

Lab 7.1 - StatefulSet for Database

Lab Objectives

By the end of this lab, you will be able to:

  • Deploy a database (MySQL) with a StatefulSet.
  • Configure persistent storage for a database.
  • Understand the importance of startup order for databases.
  • Configure a headless Service for discovery.
  • Test database data persistence.

Estimated Duration

60-75 minutes

Prerequisites

  • kubectl installed and configured.
  • Functional local Kubernetes cluster (minikube or kind).
  • Knowledge of StatefulSets (Chapter 7.1).

Part 1: Preparing the StorageClass

Create a StorageClass for database storage:

# storageclass-mysql.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: mysql-storage
provisioner: k8s.io/minikube-hostpath # For minikube
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete

Apply the StorageClass:

kubectl apply -f storageclass-mysql.yaml

Part 2: Creating the Secret for MySQL

Create a Secret to store the MySQL root password:

# mysql-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
data:
mysql-root-password: cGFzc3dvcmQxMjM= # "password123" in base64
mysql-password: cGFzc3dvcmQxMjM= # "password123" in base64

Apply the Secret:

kubectl apply -f mysql-secret.yaml

Part 3: Creating the Headless Service

A StatefulSet requires a headless Service for DNS discovery:

# mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
labels:
app: mysql
spec:
ports:
- port: 3306
name: mysql
clusterIP: None # Headless service
selector:
app: mysql

Apply the Service:

kubectl apply -f mysql-service.yaml

Part 4: Creating the MySQL StatefulSet

Create the StatefulSet for MySQL with persistent storage:

# mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql # Name of the headless Service
replicas: 1 # For this lab, a single MySQL instance
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
initContainers:
- name: init-mysql
image: busybox:1.35
command:
- sh
- -c
- |
# Create the data directory if needed
if [ ! -d /var/lib/mysql/mysql ]; then
echo "Initializing MySQL data directory"
fi
volumeMounts:
- name: data
mountPath: /var/lib/mysql
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-root-password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: data
mountPath: /var/lib/mysql
resources:
requests:
cpu: 500m
memory: 512Mi
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: mysql-storage
resources:
requests:
storage: 1Gi

Apply the StatefulSet:

kubectl apply -f mysql-statefulset.yaml

Part 5: Verifying the Deployment

Step 5.1: Verify the Pod

Wait for the Pod to be Running:

kubectl get pods -l app=mysql

Check the logs to ensure MySQL starts correctly:

kubectl logs mysql-0

Step 5.2: Verify the PVC

Check that the PVC was created:

kubectl get pvc

You should see a PVC named data-mysql-0.


Part 6: Testing the Database

Step 6.1: Create a Database and a Table

Connect to MySQL and create a test database:

kubectl exec -it mysql-0 -- mysql -uroot -ppassword123 -e "CREATE DATABASE testdb;"
kubectl exec -it mysql-0 -- mysql -uroot -ppassword123 -e "USE testdb; CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50));"
kubectl exec -it mysql-0 -- mysql -uroot -ppassword123 -e "USE testdb; INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie');"

Step 6.2: Verify the Data

Check that the data was inserted:

kubectl exec -it mysql-0 -- mysql -uroot -ppassword123 -e "USE testdb; SELECT * FROM users;"

Part 7: Testing Persistence

Step 7.1: Delete the Pod

Delete the Pod to test persistence:

kubectl delete pod mysql-0

The StatefulSet will automatically recreate the Pod with the same name.

Wait for the new Pod to be Running:

kubectl get pods -l app=mysql

Wait a few seconds for MySQL to fully restart:

kubectl logs mysql-0 -f

Press Ctrl+C once MySQL is ready.

Step 7.2: Verify Data Persistence

Check that the data is still present:

kubectl exec -it mysql-0 -- mysql -uroot -ppassword123 -e "USE testdb; SELECT * FROM users;"

You should see the three users (Alice, Bob, Charlie), proving that the data persisted!


Part 8: Cleanup

Delete the created resources:

kubectl delete statefulset mysql
kubectl delete service mysql
kubectl delete secret mysql-secret
kubectl delete pvc data-mysql-0
kubectl delete -f storageclass-mysql.yaml

Lab Summary

In this lab, you deployed a MySQL database with a StatefulSet. You learned how to configure persistent storage for a database, use Secrets for passwords, and test data persistence during restarts. StatefulSets are ideal for stateful applications like databases.


Next Steps

The next lab will show you how to use DaemonSets to deploy agents on all nodes.

Lab 7.2: DaemonSet for Monitoring


Lab created: December 2024