Deploying MariaDB on Kubernetes with Minikube: A Comprehensive Guide

Deploying MariaDB on Kubernetes with Minikube: A Comprehensive Guide

Introduction

In the modern development landscape, containerization has revolutionized how we build, deploy, and manage applications. Kubernetes has emerged as the de facto standard for container orchestration, but what about databases? In this comprehensive guide, I'll walk you through deploying MariaDB—a popular open-source relational database—on Kubernetes using Minikube for local development or learning environments.

Whether you're a developer looking to match your local environment with production, a DevOps engineer exploring containerized databases, or simply curious about Kubernetes, this tutorial provides a practical, hands-on approach to get you started.

Why Deploy MariaDB on Kubernetes?

Before diving into the technical details, let's understand the benefits of running MariaDB on Kubernetes:

  1. Environment Consistency: Ensure development, testing, and production environments use identical database configurations
  2. Infrastructure as Code: Manage database configurations using version-controlled YAML files
  3. Simplified Operations: Leverage Kubernetes for automated deployments, updates, and rollbacks
  4. Resource Efficiency: Optimize resource utilization through Kubernetes' scheduling capabilities
  5. Scalability: Easily scale your database deployment as your needs grow
  6. Learning Platform: Gain practical experience with Kubernetes concepts using a real-world database

Prerequisites

To follow along with this tutorial, you'll need:

  • Docker: The container runtime that powers Kubernetes
  • kubectl: The Kubernetes command-line tool
  • Minikube: A tool that runs a single-node Kubernetes cluster on your local machine
  • Basic knowledge of command-line operations and database concepts

If you haven't installed these tools yet, here are the installation guides:

Understanding Key Kubernetes Concepts

Before deploying MariaDB, let's briefly review some key Kubernetes concepts that are particularly relevant for database deployments:

StatefulSets vs Deployments

While Deployments are suitable for stateless applications, databases require StatefulSets because they:

  1. Provide stable, unique network identifiers
  2. Provide stable, persistent storage
  3. Offer ordered, graceful deployment and scaling
  4. Offer ordered, automated rolling updates

Persistent Volumes and Claims

Databases need persistent storage to maintain data across pod restarts. Kubernetes provides:

  • PersistentVolume (PV): A piece of storage provisioned by an administrator
  • PersistentVolumeClaim (PVC): A request for storage by a user

Secrets and ConfigMaps

For database credentials and configuration, Kubernetes offers:

  • Secrets: For storing sensitive information like passwords
  • ConfigMaps: For storing configuration data

Step 1: Setting Up Your Environment

Let's start by setting up our Minikube environment with sufficient resources for running MariaDB:

minikube start --cpus=2 --memory=4096        

This command starts Minikube with 2 CPU cores and 4GB of memory, which should be sufficient for running MariaDB.

Verify that Minikube is running:

minikube status        

You should see output indicating that Minikube is running:

minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured        

Step 2: Configuring Persistent Storage

Databases require persistent storage to maintain data across pod restarts. Let's create a PersistentVolume and PersistentVolumeClaim for MariaDB.

Create a file named persistent-volume.yaml:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mariadb-data
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
    type: DirectoryOrCreate        

The type: DirectoryOrCreate directive ensures that the directory is created if it doesn't exist.

Create a file named persistent-volume-claim.yaml:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mariadb-data
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi        

Apply these configurations:

kubectl apply -f persistent-volume.yaml
kubectl apply -f persistent-volume-claim.yaml        

Verify that the PersistentVolume and PersistentVolumeClaim were created:

kubectl get pv
kubectl get pvc        

Step 3: Creating Kubernetes Secrets for Database Credentials

For security, we'll store the MariaDB credentials in a Kubernetes Secret.

First, let's encode our credentials in base64:

bash

echo -n 'your_root_password' | base64
echo -n 'your_database_name' | base64
echo -n 'your_database_user' | base64
echo -n 'your_database_password' | base64        

Create a file named mariadb-secrets.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: mariadb-secrets
type: Opaque
data:
  root-password: eW91cl9yb290X3Bhc3N3b3Jk
  database: eW91cl9kYXRhYmFzZV9uYW1l
  user: eW91cl9kYXRhYmFzZV91c2Vy
  password: eW91cl9kYXRhYmFzZV9wYXNzd29yZA==        

Replace the base64 values with your encoded credentials.

Apply the configuration:

kubectl apply -f mariadb-secrets.yaml        

Verify the secret was created:

kubectl get secrets        

Step 4: Creating a ConfigMap for MariaDB Configuration

Create a file named mariadb-configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mariadb-configmap
data:
  my.cnf: |
    [mysqld]
    character-set-server = utf8mb4
    collation-server = utf8mb4_unicode_ci
    
    # InnoDB settings
    innodb_buffer_pool_size = 256M
    innodb_log_file_size = 64M
    
    # Connection settings
    max_connections = 100
    
    # Binary log settings
    server_id = 1
    log_bin = mysql-bin
    binlog_format = ROW
    
    [client]
    default-character-set = utf8mb4        

This ConfigMap contains a custom MariaDB configuration with optimized settings.

Apply the configuration:

kubectl apply -f mariadb-configmap.yaml        

Verify the ConfigMap was created:

kubectl get configmaps        

Step 5: Deploying MariaDB Using StatefulSet

Create a file named mariadb-statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mariadb
spec:
  serviceName: mariadb
  replicas: 1
  selector:
    matchLabels:
      app: mariadb
  template:
    metadata:
      labels:
        app: mariadb
    spec:
      containers:
      - name: mariadb
        image: mariadb:10.11
        ports:
        - containerPort: 3306
          name: mysql
        env:
        - name: MARIADB_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mariadb-secrets
              key: root-password
        - name: MARIADB_DATABASE
          valueFrom:
            secretKeyRef:
              name: mariadb-secrets
              key: database
        - name: MARIADB_USER
          valueFrom:
            secretKeyRef:
              name: mariadb-secrets
              key: user
        - name: MARIADB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mariadb-secrets
              key: password
        volumeMounts:
        - name: mariadb-data
          mountPath: /var/lib/mysql
        - name: mariadb-config
          mountPath: /etc/mysql/conf.d
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1"
        livenessProbe:
          exec:
            command: ["mysqladmin", "ping", "-u", "root", "-p${MARIADB_ROOT_PASSWORD}"]
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command: ["mysqladmin", "ping", "-u", "root", "-p${MARIADB_ROOT_PASSWORD}"]
          initialDelaySeconds: 5
          periodSeconds: 2
          timeoutSeconds: 1
      volumes:
      - name: mariadb-config
        configMap:
          name: mariadb-configmap
  volumeClaimTemplates:
  - metadata:
      name: mariadb-data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: manual
      resources:
        requests:
          storage: 1Gi        

This StatefulSet configuration:

  • Uses the MariaDB 10.11 image
  • Sets environment variables from our secrets
  • Mounts our persistent volume for data storage
  • Mounts our ConfigMap for custom configuration
  • Includes resource limits and health checks

Apply the configuration:

kubectl apply -f mariadb-statefulset.yaml        

Verify the StatefulSet was created:

kubectl get statefulsets        

Check the status of the MariaDB pod:

bash

kubectl get pods        

You should see a pod named mariadb-0 in the "Running" state after a few moments.

Step 6: Creating a Service for MariaDB

Create a file named mariadb-service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: mariadb
  labels:
    app: mariadb
spec:
  ports:
  - port: 3306
    targetPort: 3306
    name: mysql
  selector:
    app: mariadb
  type: ClusterIP        

This service configuration makes MariaDB accessible within the cluster.

Apply the configuration:

kubectl apply -f mariadb-service.yaml
        

Verify the service was created:

kubectl get services        

Step 7: Accessing and Testing MariaDB

Connecting to MariaDB from Within the Cluster

To connect to MariaDB from within the cluster, you can use the service name mariadb as the hostname.

Let's test this by running a temporary pod with the MySQL client:

kubectl run -it --rm --image=mariadb:10.11 --restart=Never mysql-client -- mysql -h mariadb -uroot -p        

When prompted, enter your root password.

Connecting to MariaDB from Outside the Cluster

To connect to MariaDB from your local machine, use port forwarding:

kubectl port-forward svc/mariadb 3306:3306        

This command forwards your local port 3306 to the MariaDB service in the cluster.

In a new terminal, you can now connect using a MySQL client:

mysql -h 127.0.0.1 -P 3306 -uroot -p        

Verifying Data Persistence

Let's test data persistence by creating a table and inserting data:

CREATE TABLE test (id INT, name VARCHAR(50));
INSERT INTO test VALUES (1, 'Test Data');
SELECT * FROM test;        

Now, let's delete the MariaDB pod and let Kubernetes recreate it:

kubectl delete pod mariadb-0        

Wait for the pod to be recreated:

kubectl get pods        

Once the pod is running again, connect to MariaDB and verify your data is still there:

kubectl run -it --rm --image=mariadb:10.11 --restart=Never mysql-client -- mysql -h mariadb -uroot -p        
SELECT * FROM test;        

You should see your test data, confirming that the data persisted across pod restarts.

Automating the Deployment Process

To simplify the deployment process, let's create a setup script. Create a file named setup.sh:

#!/bin/bash

# Start Minikube if not already running
if ! minikube status | grep -q "Running"; then
  echo "Starting Minikube..."
  minikube start --cpus=2 --memory=4096
else
  echo "Minikube is already running."
fi

# Enable storage addons
echo "Enabling storage addons..."
minikube addons enable storage-provisioner
minikube addons enable default-storageclass

# Create directory for persistent volume
echo "Creating directory for persistent volume..."
minikube ssh "sudo mkdir -p /mnt/data && sudo chmod 777 /mnt/data"

# Apply Kubernetes configurations
echo "Creating persistent volume and claim..."
kubectl apply -f persistent-volume.yaml
kubectl apply -f persistent-volume-claim.yaml

# Verify PV and PVC are bound
echo "Verifying PV and PVC status..."
kubectl get pv
kubectl get pvc

# Wait for PVC to be bound
echo "Waiting for PVC to be bound..."
kubectl wait --for=condition=bound pvc/mariadb-pvc --timeout=60s

echo "Creating MariaDB secrets..."
kubectl apply -f mariadb-secrets.yaml

echo "Creating MariaDB ConfigMap..."
kubectl apply -f mariadb-configmap.yaml

echo "Deploying MariaDB StatefulSet..."
kubectl apply -f mariadb-statefulset.yaml

echo "Creating MariaDB Service..."
kubectl apply -f mariadb-service.yaml

echo "Waiting for MariaDB pod to be ready..."
kubectl wait --for=condition=ready pod/mariadb-0 --timeout=120s

echo "MariaDB deployment complete!"
echo "To connect to MariaDB, run: kubectl port-forward svc/mariadb 3306:3306"        

Make the script executable:

chmod +x setup.sh        

Now you can deploy MariaDB with a single command:

./setup.sh        

Troubleshooting Common Issues

Issue: Pod Won't Start Due to Unbound PersistentVolumeClaim

If you see an error like:

Warning  FailedScheduling  2m16s  default-scheduler  0/2 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/2 nodes are available: 2 Preemption is not helpful for scheduling.        

Solution:

Ensure the storage addons are enabled:

minikube addons enable storage-provisioner
minikube addons enable default-storageclass
        

Create the directory on the Minikube VM:

minikube ssh "sudo mkdir -p /mnt/data && sudo chmod 777 /mnt/data"
        

Verify that the PV and PVC have matching specifications:

kubectl describe pv mariadb-pv
kubectl describe pvc mariadb-pvc        

Issue: Can't Connect to MariaDB

If you can't connect to MariaDB, check:

The pod status:

kubectl get pods
        

The pod logs:

kubectl logs mariadb-0
        

The service status:

kubectl get svc
        

Ensure port forwarding is active:

kubectl port-forward svc/mariadb 3306:3306
        

Advanced Topics

Scaling MariaDB (Read Replicas)

For a production environment, you might want to set up MariaDB replication for read scaling. This requires additional configuration:

  1. Modify the StatefulSet to support multiple replicas
  2. Configure master-slave replication
  3. Set up a separate service for read replicas

Implementing Backup and Restore

Regular backups are essential for any database. You can implement backups using:

  1. A CronJob that runs mysqldump
  2. Persistent volume snapshots
  3. MariaDB's built-in backup tools

Monitoring MariaDB on Kubernetes

For monitoring, consider:

  1. Prometheus for metrics collection
  2. Grafana for visualization
  3. Custom health checks and alerts

Conclusion

In this comprehensive guide, we've covered how to deploy MariaDB on Kubernetes using Minikube. We've explored:

  1. Setting up a Minikube cluster
  2. Configuring persistent storage for MariaDB
  3. Creating Kubernetes secrets for database credentials
  4. Deploying MariaDB using a StatefulSet
  5. Accessing and testing your MariaDB deployment
  6. Verifying data persistence
  7. Automating the deployment process
  8. Troubleshooting common issues

This knowledge provides a foundation for deploying and managing databases on Kubernetes in more complex environments. Whether you're using this setup for development, testing, or learning, you now have a solid understanding of how to run stateful applications like MariaDB on Kubernetes.

Next Steps

To further enhance your MariaDB on Kubernetes deployment, consider:

  1. Implementing a proper backup strategy
  2. Setting up monitoring and alerting
  3. Configuring high availability with replication
  4. Automating database operations with operators

The complete code for this tutorial is available in my GitHub repository: MariaDB on Kubernetes with Minikube .

Happy containerizing!


If you found this article helpful, please consider following me for more content on Kubernetes, databases, and DevOps practices.

To view or add a comment, sign in

More articles by Fernando Castro

Insights from the community

Others also viewed

Explore topics