Top Tags

Basic deployment MySQL on Kubernetes microK8s

Deploy MySQL on Kubernetes microK8s

Overview

This guide demonstrates how to deploy a MySQL database on Kubernetes using MicroK8s. The deployment creates multiple MySQL replicas behind a LoadBalancer service, making the database accessible from outside the cluster.

Prerequisites

Before you begin, ensure you have the following:

  • MicroK8s installed and running on your system
  • MetalLB addon enabled for LoadBalancer support
  • kubectl or microk8s kubectl configured
  • Basic understanding of Kubernetes concepts (Pods, Deployments, Services)

Key Kubernetes Concepts

ConceptDescription
DeploymentManages a set of identical Pods, ensuring the specified number of replicas are running
ReplicaSetCreated by Deployment to maintain the desired number of Pod replicas
ServiceExposes Pods to network traffic and provides load balancing
LoadBalancerService type that provisions an external IP address for accessing the application

MySQL Deployment Architecture

The deployment consists of two main Kubernetes resources:

  1. Deployment: Manages 3 MySQL Pod replicas with the container configuration
  2. Service: Exposes MySQL on port 3306 via LoadBalancer

Create deployment file

Save the following YAML manifest as mysql-deployment.yaml. This file defines both the Deployment and Service resources in a single file, separated by ---.

Understanding the Deployment Specification

  • apiVersion: apps/v1: Uses the stable apps API group for Deployments
  • kind: Deployment: Declares this resource as a Deployment controller
  • replicas: 3: Specifies 3 identical Pod instances will be maintained
  • selector.matchLabels: Defines how the Deployment finds Pods to manage
  • template: Pod template that defines the container specification
yaml
1apiVersion: apps/v1
2kind: Deployment
3metadata:
4 name: mysql-deployment
5spec:
6 replicas: 3
7 selector:
8 matchLabels:
9 app: mysql
10 template:
11 metadata:
12 labels:
13 app: mysql
14 spec:
15 containers:
16 - name: mysql
17 image: mysql:latest
18 ports:
19 - containerPort: 3306
20 env:
21 - name: MYSQL_ROOT_PASSWORD
22 value: "123"
23---
24apiVersion: v1
25kind: Service
26metadata:
27 name: mysql-service
28spec:
29 selector:
30 app: mysql
31 ports:
32 - protocol: TCP
33 port: 3306
34 targetPort: 3306
35 type: LoadBalancer

Service Configuration Details

FieldValueDescription
selector.appmysqlRoutes traffic to Pods with label app: mysql
port3306External port the Service listens on
targetPort3306Port on the container to forward traffic to
typeLoadBalancerProvisions an external IP via MetalLB

Deploy the Application

Apply the manifest to your MicroK8s cluster:

bash
1microk8s kubectl apply -f mysql-deployment.yaml

Verify Deployment Status

Check that all resources were created successfully:

bash
1microk8s kubectl get deployment mysql-deployment
2microk8s kubectl get service mysql-service

Expected output shows 3/3 replicas ready and an external IP assigned to the service.

Try to connect to MySQL

Once the LoadBalancer assigns an external IP (in this example 10.11.0.51), you can connect to MySQL from any machine that can reach your cluster network:

bash
1mysql -u root -p -h 10.11.0.51 -P 3306

Connection Parameters Explained

ParameterDescription
-u rootConnect as the MySQL root user
-pPrompt for password (enter the password from MYSQL_ROOT_PASSWORD)
-h 10.11.0.51Host IP address (your LoadBalancer external IP)
-P 3306MySQL port number

Verify Database Connectivity

Once connected, verify the MySQL instance is working:

sql
1-- Show MySQL version
2SELECT VERSION();
3
4-- List available databases
5SHOW DATABASES;
6
7-- Check server status
8STATUS;

Some of information about the deployment

Use these commands to monitor and debug your MySQL deployment:

bash
1microk8s kubectl get pods --watch
2microk8s kubectl get pods -o wide
3microk8s kubectl logs mysql-deployment-c4fccb7d9-fr5tw
4microk8s kubectl describe services mysql-service

Command Reference

CommandPurpose
get pods --watchReal-time monitoring of Pod status changes
get pods -o wideShows Pod IPs and node placement
logs <pod-name>View container logs for debugging
describe servicesDetailed Service info including endpoints

Understanding Pod States

When running kubectl get pods, you may see these states:

StateDescription
PendingPod accepted but container not yet created
ContainerCreatingImage being pulled and container starting
RunningContainer executing successfully
CrashLoopBackOffContainer crashed and Kubernetes is restarting it
ErrorContainer terminated with an error

Scaling the Deployment

Kubernetes makes it easy to scale your MySQL deployment up or down. Scaling changes the number of Pod replicas managed by the Deployment.

Scale Using kubectl

bash
1# Scale to 5 replicas
2microk8s kubectl scale deployment mysql-deployment --replicas=5
3
4# Verify the scaling operation
5microk8s kubectl get deployment mysql-deployment
6
7# Scale down to 2 replicas
8microk8s kubectl scale deployment mysql-deployment --replicas=2

How Scaling Works

When you scale a Deployment:

  1. Scaling Up: New Pods are scheduled on nodes with available resources
  2. Scaling Down: Kubernetes terminates Pods based on priority (pending pods first, then newest pods)
  3. Load Balancing: The Service automatically distributes traffic across all healthy Pods

Troubleshooting

Common Issues and Solutions

Pod Stuck in Pending State

bash
1# Check why the pod is pending
2microk8s kubectl describe pod <pod-name>
3
4# Common causes:
5# - Insufficient CPU/memory resources
6# - No available nodes
7# - PersistentVolumeClaim not bound

CrashLoopBackOff Error

bash
1# Check container logs for error details
2microk8s kubectl logs <pod-name> --previous
3
4# Common MySQL startup failures:
5# - Invalid MYSQL_ROOT_PASSWORD
6# - Permission issues on data directory
7# - Port already in use

Service Has No External IP

bash
1# Verify MetalLB is enabled
2microk8s enable metallb
3
4# Check MetalLB IP pool configuration
5microk8s kubectl get configmap -n metallb-system
6
7# View service events
8microk8s kubectl describe svc mysql-service

Cleanup Resources

To remove the MySQL deployment and free up cluster resources:

bash
1# Delete all resources defined in the manifest
2microk8s kubectl delete -f mysql-deployment.yaml
3
4# Or delete resources individually
5microk8s kubectl delete deployment mysql-deployment
6microk8s kubectl delete service mysql-service
7
8# Verify cleanup
9microk8s kubectl get all -l app=mysql

Production Considerations

For production deployments, consider these enhancements:

Use Kubernetes Secrets for Credentials

Instead of plaintext passwords in the Deployment manifest, create a Secret:

bash
1# Create a secret for MySQL root password
2microk8s kubectl create secret generic mysql-secret \
3 --from-literal=root-password='YourSecurePassword123!'

Then reference it in your Deployment:

yaml
1env:
2 - name: MYSQL_ROOT_PASSWORD
3 valueFrom:
4 secretKeyRef:
5 name: mysql-secret
6 key: root-password

Add Persistent Storage

To persist data across Pod restarts, add a PersistentVolumeClaim:

yaml
1apiVersion: v1
2kind: PersistentVolumeClaim
3metadata:
4 name: mysql-pv-claim
5spec:
6 accessModes:
7 - ReadWriteOnce
8 resources:
9 requests:
10 storage: 20Gi

Configure Resource Limits

Define CPU and memory constraints to prevent resource contention:

yaml
1containers:
2 - name: mysql
3 image: mysql:8.0
4 resources:
5 requests:
6 cpu: "500m"
7 memory: "1Gi"
8 limits:
9 cpu: "1000m"
10 memory: "2Gi"

Add Health Probes

Kubernetes uses probes to determine container health:

yaml
1containers:
2 - name: mysql
3 image: mysql:8.0
4 livenessProbe:
5 exec:
6 command: ["mysqladmin", "ping", "-h", "localhost"]
7 initialDelaySeconds: 30
8 periodSeconds: 10
9 timeoutSeconds: 5
10 readinessProbe:
11 exec:
12 command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"]
13 initialDelaySeconds: 5
14 periodSeconds: 2
15 timeoutSeconds: 1
Probe TypePurpose
livenessProbeRestarts container if it becomes unresponsive
readinessProbeRemoves Pod from Service endpoints until ready

Next Steps