How to Set Up Mariadb in Kubernetes using helm and kustomize

Step-by-step guide on How to Set Up Mariadb in Kubernetes using helm and kustomize

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.

Configure with Kustomize

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

1
helmfile sync

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.

comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy