MariaDB, a popular open-source relational database, runs beautifully in Kubernetes — especially when paired with tools like Helm and Kustomize for clean, repeatable infrastructure management.
In this guide, you’ll learn how to deploy MariaDB into a Kubernetes cluster using Helm for templated configuration and Kustomize for environment layering and customization.
Using Helm or Kustomize is benefitial in a couple of ways:
- Helm simplifies complex deployments using charts — reusable application templates.
- Kustomize allows you to declaratively patch and manage multiple environments (dev, staging, prod) without duplicating YAML.
In this guide, you’ll learn how to:
- Deploy MariaDB in Kubernetes
- Manage configuration using Helm and Kustomize
- Secure secrets using External Secrets
- Use Helmfile for simplified release management
Prerequisites
- Kubernetes cluster (local via kind/minikube, or cloud via GKE/EKS/AKS)
- kubectl, helm, and kustomize installed
- Optional: kubens and kubectx for context/namespace management
Create a Namespace
Isolate the MariaDB resources in a dedicated namespace. Save this under namespace.yml
1
2
3
4
5
6
| # namespace.yml
---
apiVersion: v1
kind: Namespace
metadata:
name: mariadb
|
Namespacing keeps resources logically grouped and avoids name collisions.
Define Persistent Volume Claim
Create a persistent volume to store MariaDB data. Save this under pvc.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| # pvc.yml
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mariadb-data-vol
namespace: mariadb
labels:
app.kubernetes.io/name: app
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
|
MariaDB stores data on disk. A PVC ensures the data persists even if the pod is restarted.
Manage Secrets with External Secrets
We need a secret to create our password. We need to create in the secrets manager, have it injected to kubernetes by an external secret.
Use External Secrets Operator to securely inject credentials from a secret store (e.g. Vault, AWS Secrets Manager).
Save this under external-secret.yml
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # external-secret.yml
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: mariadb-credentials
namespace: mariadb
spec:
dataFrom:
- extract:
key: infra/mariadb-credentials
secretStoreRef:
kind: ClusterSecretStore
name: vault-backend
target:
name: mariadb-credentials
creationPolicy: Owner
|
This decouples secret management from Kubernetes and keeps secrets out of source control.
Deploy MariaDB with Kustomize
Save this under deployment.yml
. Here’s a declarative deployment manifest:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| # deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mariadb-app
namespace: mariadb
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: app
template:
metadata:
labels:
app.kubernetes.io/name: app
spec:
containers:
- name: mariadb
image: mariadb:11.7
ports:
- containerPort: 3306
name: mariadb
env:
- name: MARIADB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-credentials
key: root-password
volumeMounts:
- name: mariadb-data-vol
mountPath: /var/lib/mysql
volumes:
- name: mariadb-data-vol
persistentVolumeClaim:
claimName: mariadb-data-vol
|
Expose MariaDB via Service
We need a way to expose our deployment. Save this under service.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
| # service.yml
---
apiVersion: v1
kind: Service
metadata:
name: mariadb-app
namespace: mariadb
spec:
ports:
- port: 3306
targetPort: mariadb
selector:
app.kubernetes.io/name: app
|
This creates a ClusterIP service allowing other services in the cluster to access MariaDB.
We use kustomize to manage all the yaml files. Bring it all together using a kustomization.yml
file:
1
2
3
4
5
6
7
8
9
10
11
12
13
| # kustomization.yml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: mariadb
resources:
- ./namespace.yml
- ./pvc.yml
- ./external-secret.yml
- ./deployment.yml
- ./service.yml
|
Apply the Configuration
Apply everything using Kustomize:
1
| kustomize build . | k apply -f -
|
Verify:
1
2
3
4
5
6
7
8
9
10
11
12
13
| $ k get all -n mariadb
NAME READY STATUS RESTARTS AGE
pod/mariadb-app-7c9f6d4d8-gv67k 1/1 Running 0 21h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mariadb-app ClusterIP 10.43.3.189 <none> 3306/TCP 22h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mariadb-app 1/1 1 1 22h
NAME DESIRED CURRENT READY AGE
replicaset.apps/mariadb-app-7c9f6d4d8 1 1 1 22h
|
You should see a running pod, service, and associated deployment.
Deploy MariaDB Using Helm + Helmfile (Optional)
I have a public helm charts for common things here that we can also use.
If you prefer Helmfile
for managing releases, here’s how to define it, create a helmfile.yml
file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # helmfile.yml
---
helmDefaults:
createNamespace: true
wait: true
repositories:
- name: mycharts
url: https://etowett.github.io/helm-charts
releases:
- name: mariadb
namespace: mariadb
chart: mycharts/app
version: "1.1.1"
values:
- ./values.yml
|
Then create a values file - values.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| replicaCount: 1
image:
repository: mariadb
pullPolicy: IfNotPresent
tag: 11.7
serviceAccount:
create: true
service:
type: ClusterIP
name: mariadb
port: 3306
resources:
limits:
cpu: 1000m
memory: 1024Mi
requests:
cpu: 50m
memory: 64Mi
pvc:
create: true
claimName: mariadb-data-vol
size: 10Gi
volumeMounts:
- name: mariadb-data-vol
mountPath: /var/lib/mysql
volumes:
- name: mariadb-data-vol
persistentVolumeClaim:
claimName: mariadb-data-vol
externalSecrets:
- name: mariadb-credentials
refreshInterval: 5m
secretStoreRefName: vault-backend
targetName: mariadb-credentials
dataKey: infra/mariadb-credentials
secretEnv:
MARIADB_ROOT_PASSWORD:
name: mariadb-credentials
key: root-password
|
Then apply
Validate with:
1
2
3
4
| $ helm ls -n mariadb
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
mariadb mariadb 3 2025-05-05 11:27:54.825897 +0300 EAT deployed app-1.1.1 1.0.0
|
Final Thoughts
Deploying MariaDB in Kubernetes using Helm and Kustomize provides:
- Declarative configuration
- Secure secret management
- Reusable environments
Whether you’re deploying for development or production, this setup ensures consistency, flexibility, and security.