MariaDB
Deploy MariaDB on Kubernetes using the official mariadb Docker image.
Supports standalone and GTID-based asynchronous replication, six built-in configuration presets, TLS, Prometheus
metrics via mysqld-exporter, and scheduled mariadb-dump backups to S3-compatible storage.
When architecture: replication, the chart enables a PodDisruptionBudget (replication.pdb) and configures default
pod anti-affinity rules (replication.scheduling.enableDefaultPodAntiAffinity) to spread source and replica pods
across different nodes. No extra configuration is needed for basic HA scheduling.
Key Features
- Two architectures —
standalone(Deployment) orreplication(StatefulSet + GTID) - GTID-based replication —
MASTER_USE_GTID=slave_poswith parallel replica workers - Configuration presets —
small,medium,large,oltp,read-heavy,analytics - Writable/read-only probes — source readiness requires writable, replica requires read-only
- Hardened by default — non-root UID 999, ALL caps dropped, seccomp
RuntimeDefault - Init scripts — SQL/Shell scripts executed on
docker-entrypoint-initdb.dat first boot - S3 backup —
mariadb-dumpwith--routines --events --triggersflags - NetworkPolicy — optional ingress-only policy for cluster isolation
Installation
HTTPS repository:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install mariadb helmforge/mariadb -f values.yaml
OCI registry:
helm install mariadb oci://ghcr.io/helmforgedev/helm/mariadb -f values.yaml
Deployment Examples
# values.yaml — MariaDB standalone with preset and metrics
architecture: standalone
auth:
rootPassword: 'strong-root-password'
database: myapp
username: myapp
password: 'strong-app-password'
config:
preset: oltp # optimized for transactional workloads
myCnf: |
# extra my.cnf content appended after the generated config
max_connections = 500
standalone:
persistence:
enabled: true
size: 20Gi
metrics:
enabled: true
serviceMonitor:
enabled: true
interval: 30s
labels:
release: prometheus# values.yaml — MariaDB 1 source + 2 read replicas with GTID
architecture: replication
auth:
existingSecret: mariadb-credentials
existingSecretRootPasswordKey: mariadb-root-password
existingSecretUserPasswordKey: mariadb-user-password
existingSecretReplicationPasswordKey: mariadb-replication-password
database: myapp
username: myapp
replicationUsername: replicator
config:
preset: oltp
replication:
source:
persistence:
enabled: true
size: 50Gi
probes:
requireWritable: true # source only becomes ready when confirmed writable
readReplicas:
replicaCount: 2
persistence:
enabled: true
size: 50Gi
probes:
requireReadOnly: true # replica only ready when read-only
requireRunningReplication: true # require IO and SQL threads running
binlog:
format: ROW
retentionDays: 7 # overrides expireLogsSeconds when > 0
replicaTuning:
parallelWorkers: 4 # parallel binlog applier workers on replicas
# Automatically enabled in replication mode:
pdb:
enabled: true
minAvailable: 1
scheduling:
enableDefaultPodAntiAffinity: true # spread source+replicas across nodes
enableDefaultTopologySpread: true
metrics:
enabled: true
serviceMonitor:
enabled: true# values.yaml — MariaDB with daily S3 backup using mariadb-dump
architecture: standalone
auth:
rootPassword: 'strong-root-password'
database: myapp
username: myapp
password: 'strong-app-password'
standalone:
persistence:
enabled: true
size: 20Gi
backup:
enabled: true
schedule: '0 3 * * *'
archivePrefix: mariadb
s3:
endpoint: https://s3.amazonaws.com
bucket: my-mariadb-backups
existingSecret: mariadb-s3-credentials
existingSecretAccessKeyKey: access-key
existingSecretSecretKeyKey: secret-key
database:
mariadbdumpArgs: >-
--single-transaction --quick --skip-lock-tables
--no-tablespaces --routines --events --triggers# values.yaml — MariaDB with server-side TLS
architecture: standalone
auth:
rootPassword: 'strong-root-password'
database: myapp
username: myapp
password: 'strong-app-password'
tls:
enabled: true
existingSecret: mariadb-tls-secret # must contain ca.crt, tls.crt, tls.key
caFilename: ca.crt
certFilename: tls.crt
keyFilename: tls.key
requireSecureTransport: true # reject plaintext connections
client:
enabled: true # use TLS for internal chart client connections (replication bootstrap)
standalone:
persistence:
enabled: true
size: 20GiConfiguration Reference
Core
| Parameter | Type | Default | Description |
|---|---|---|---|
architecture |
string | standalone |
Deployment mode: standalone or replication. |
nameOverride |
string | "" |
Override the chart name. |
fullnameOverride |
string | "" |
Override the full release name. |
commonLabels |
object | {} |
Extra labels added to all resources. |
clusterDomain |
string | cluster.local |
Kubernetes cluster domain. |
Image
| Parameter | Type | Default | Description |
|---|---|---|---|
image.repository |
string | docker.io/library/mariadb |
MariaDB container image. |
image.tag |
string | "12.2.2" |
Image tag. |
image.pullPolicy |
string | IfNotPresent |
Image pull policy. |
Authentication
| Parameter | Type | Default | Description |
|---|---|---|---|
auth.rootPassword |
string | "" |
Root password. Auto-generated if empty. |
auth.database |
string | app |
Application database created on first bootstrap. |
auth.username |
string | app |
Application user created on first bootstrap. |
auth.password |
string | "" |
Application user password. Auto-generated if empty. |
auth.replicationUsername |
string | replicator |
Replication user (only used in replication mode). |
auth.replicationPassword |
string | "" |
Replication password. Auto-generated if empty. |
auth.existingSecret |
string | "" |
Existing secret with all MariaDB passwords. |
auth.existingSecretRootPasswordKey |
string | mariadb-root-password |
Key for root password in existingSecret. |
auth.existingSecretUserPasswordKey |
string | mariadb-user-password |
Key for application user password in existingSecret. |
auth.existingSecretReplicationPasswordKey |
string | mariadb-replication-password |
Key for replication password in existingSecret. |
Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
config.preset |
string | none |
Built-in tuning preset: none, small, medium, large, oltp, read-heavy, analytics. |
config.myCnf |
string | "" |
Extra my.cnf content appended to the generated configuration. |
Initialization
| Parameter | Type | Default | Description |
|---|---|---|---|
initdb.scripts |
object | {} |
SQL or Shell scripts injected into docker-entrypoint-initdb.d at first boot. |
initdb.existingConfigMap |
string | "" |
Existing ConfigMap also mounted into docker-entrypoint-initdb.d. |
Persistence
| Parameter | Type | Default | Description |
|---|---|---|---|
persistence.subPath |
string | mysql |
Data volume subdirectory mounted as /var/lib/mysql; set "" for legacy volume-root installs. |
persistence.prepareDataDir.enabled |
boolean | false |
Opt-in root initContainer for storage drivers that do not honor fsGroup; requires a Pod Security exception. |
The default subPath path relies on podSecurityContext.fsGroup and does not render a root initContainer, keeping it
compatible with Pod Security restricted. Enable persistence.prepareDataDir.enabled only for storage drivers that do
not honor fsGroup for subPath directories.
Extra Objects
| Parameter | Type | Default | Description |
|---|---|---|---|
extraObjects |
array | [] |
Additional Kubernetes manifests rendered with the release. |
Standalone Mode
| Parameter | Type | Default | Description |
|---|---|---|---|
standalone.serverId |
integer | 1 |
MariaDB server ID. |
standalone.persistence.enabled |
boolean | true |
Enable PVC for data. |
standalone.persistence.size |
string | 8Gi |
PVC size. |
standalone.persistence.storageClass |
string | "" |
StorageClass for the PVC. |
standalone.resources |
object | {} |
CPU and memory for the pod. |
Replication Mode
All passwords (root, user, replication) must be stable before the StatefulSet first starts. Auto-generated passwords
will change on Helm upgrades if not stored in an existingSecret, causing replicas to lose their replication
credentials.
| Parameter | Type | Default | Description |
|---|---|---|---|
replication.source.serverId |
integer | 1 |
Source server ID. |
replication.source.persistence.size |
string | 20Gi |
PVC size for the source pod. |
replication.source.probes.requireWritable |
boolean | true |
Source only becomes ready when confirmed writable. |
replication.readReplicas.replicaCount |
integer | 2 |
Number of read replica pods. |
replication.readReplicas.serverIdBase |
integer | 100 |
Base server ID for replicas (replica ordinal added to this). |
replication.readReplicas.persistence.size |
string | 20Gi |
PVC size per replica pod. |
replication.readReplicas.probes.requireReadOnly |
boolean | true |
Replica only ready when confirmed read-only. |
replication.readReplicas.probes.requireRunningReplication |
boolean | false |
Require IO and SQL replication threads running. |
replication.binlog.format |
string | ROW |
Binlog format used by the source. |
replication.binlog.retentionDays |
integer | 7 |
Binlog retention in days. Overrides expireLogsSeconds when > 0. |
replication.binlog.syncBinlog |
integer | 1 |
sync_binlog value on the source (1 = fully durable). |
replication.replicaTuning.parallelWorkers |
integer | 4 |
Parallel binlog applier workers on replicas. |
replication.pdb.enabled |
boolean | true |
Enable PodDisruptionBudget (default enabled in replication mode). |
replication.pdb.minAvailable |
integer | 1 |
Minimum available pods. |
replication.scheduling.enableDefaultPodAntiAffinity |
boolean | true |
Spread source and replicas across different nodes automatically. |
replication.scheduling.enableDefaultTopologySpread |
boolean | true |
Enable topology spread constraints for replication pods. |
TLS
| Parameter | Type | Default | Description |
|---|---|---|---|
tls.enabled |
boolean | false |
Enable MariaDB server-side TLS. |
tls.existingSecret |
string | "" |
Existing Secret with CA, certificate, and private key. |
tls.caFilename |
string | ca.crt |
CA certificate filename in the secret. |
tls.certFilename |
string | tls.crt |
Server certificate filename. |
tls.keyFilename |
string | tls.key |
Server private key filename. |
tls.requireSecureTransport |
boolean | false |
Reject plaintext connections (enforce TLS for all clients). |
tls.client.enabled |
boolean | false |
Use TLS for internal chart client connections. |
Backup
| Parameter | Type | Default | Description |
|---|---|---|---|
backup.enabled |
boolean | false |
Enable scheduled mariadb-dump S3 backup. |
backup.schedule |
string | "0 3 * * *" |
Cron schedule. |
backup.archivePrefix |
string | mariadb |
Prefix for backup archive filenames. |
backup.s3.endpoint |
string | "" |
S3-compatible endpoint URL. |
backup.s3.bucket |
string | "" |
Target bucket name. |
backup.s3.existingSecret |
string | "" |
Existing secret with S3 credentials. |
backup.database.mariadbdumpArgs |
string | --single-transaction ... |
Extra args for mariadb-dump. Includes --routines --events --triggers by default. |
Metrics
| Parameter | Type | Default | Description |
|---|---|---|---|
metrics.enabled |
boolean | false |
Enable mysqld-exporter sidecar. |
metrics.image.repository |
string | docker.io/prom/mysqld-exporter |
Exporter image. |
metrics.image.tag |
string | "v0.17.2" |
Exporter image tag. |
metrics.serviceMonitor.enabled |
boolean | false |
Create a Prometheus Operator ServiceMonitor. |
metrics.serviceMonitor.interval |
string | 30s |
Scrape interval. |
When metrics are enabled, the chart writes a locked-down mysqld-exporter client config from the same MariaDB Secret used
by the database container. This avoids exposing the root password through DATA_SOURCE_NAME and keeps TLS client settings
aligned with the MariaDB pod.
To inspect exporter startup issues:
kubectl logs -n mariadb mariadb-0 -c mysqld-exporter
NetworkPolicy
| Parameter | Type | Default | Description |
|---|---|---|---|
networkPolicy.enabled |
boolean | false |
Create an ingress-only NetworkPolicy. |
networkPolicy.ingress.allowSameNamespace |
boolean | true |
Allow traffic from pods in the same namespace. |
networkPolicy.ingress.extraFrom |
array | [] |
Extra ingress peer selectors. |
networkPolicy.metrics.enabled |
boolean | false |
Allow ingress to the metrics port. |
Security Context
MariaDB runs hardened by default:
| Parameter | Default | Description |
|---|---|---|
podSecurityContext.fsGroup |
999 |
Filesystem group for volume ownership. |
podSecurityContext.seccompProfile.type |
RuntimeDefault |
Seccomp profile. |
securityContext.runAsUser |
999 |
Container UID. |
securityContext.runAsNonRoot |
true |
Enforce non-root execution. |
securityContext.allowPrivilegeEscalation |
false |
Disallow privilege escalation. |
securityContext.capabilities.drop |
["ALL"] |
Drop all Linux capabilities. |
Scheduling
| Parameter | Type | Default | Description |
|---|---|---|---|
terminationGracePeriodSeconds |
integer | 120 |
Grace period. Allows in-progress transactions to commit cleanly. |
nodeSelector |
object | {} |
Node selector for scheduling. |
tolerations |
array | [] |
Tolerations for scheduling. |
affinity |
object | {} |
Affinity rules (replaces default anti-affinity if set). |