Skip to content

MariaDB

Deploy MariaDB on Kubernetes using the official mariadb Docker image (11.4 LTS). 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.

Replication mode enables PDB and pod anti-affinity automatically

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 architecturesstandalone (Deployment) or replication (StatefulSet + GTID)
  • GTID-based replicationMASTER_USE_GTID=slave_pos with parallel replica workers
  • Configuration presetssmall, 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.d at first boot
  • S3 backupmariadb-dump with --routines --events --triggers flags
  • 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: 20Gi

Configuration Reference

Core

ParameterTypeDefaultDescription
architecturestringstandaloneDeployment mode: standalone or replication.
nameOverridestring""Override the chart name.
fullnameOverridestring""Override the full release name.
commonLabelsobject{}Extra labels added to all resources.
clusterDomainstringcluster.localKubernetes cluster domain.

Image

ParameterTypeDefaultDescription
image.repositorystringdocker.io/library/mariadbMariaDB container image.
image.tagstring"11.4"Image tag (LTS).
image.pullPolicystringIfNotPresentImage pull policy.

Authentication

ParameterTypeDefaultDescription
auth.rootPasswordstring""Root password. Auto-generated if empty.
auth.databasestringappApplication database created on first bootstrap.
auth.usernamestringappApplication user created on first bootstrap.
auth.passwordstring""Application user password. Auto-generated if empty.
auth.replicationUsernamestringreplicatorReplication user (only used in replication mode).
auth.replicationPasswordstring""Replication password. Auto-generated if empty.
auth.existingSecretstring""Existing secret with all MariaDB passwords.
auth.existingSecretRootPasswordKeystringmariadb-root-passwordKey for root password in existingSecret.
auth.existingSecretUserPasswordKeystringmariadb-user-passwordKey for application user password in existingSecret.
auth.existingSecretReplicationPasswordKeystringmariadb-replication-passwordKey for replication password in existingSecret.

Configuration

ParameterTypeDefaultDescription
config.presetstringnoneBuilt-in tuning preset: none, small, medium, large, oltp, read-heavy, analytics.
config.myCnfstring""Extra my.cnf content appended to the generated configuration.

Initialization

ParameterTypeDefaultDescription
initdb.scriptsobject{}SQL or Shell scripts injected into docker-entrypoint-initdb.d at first boot.
initdb.existingConfigMapstring""Existing ConfigMap also mounted into docker-entrypoint-initdb.d.

Standalone Mode

ParameterTypeDefaultDescription
standalone.serverIdinteger1MariaDB server ID.
standalone.persistence.enabledbooleantrueEnable PVC for data.
standalone.persistence.sizestring8GiPVC size.
standalone.persistence.storageClassstring""StorageClass for the PVC.
standalone.resourcesobject{}CPU and memory for the pod.

Replication Mode

Set replication passwords before first deployment

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.

ParameterTypeDefaultDescription
replication.source.serverIdinteger1Source server ID.
replication.source.persistence.sizestring20GiPVC size for the source pod.
replication.source.probes.requireWritablebooleantrueSource only becomes ready when confirmed writable.
replication.readReplicas.replicaCountinteger2Number of read replica pods.
replication.readReplicas.serverIdBaseinteger100Base server ID for replicas (replica ordinal added to this).
replication.readReplicas.persistence.sizestring20GiPVC size per replica pod.
replication.readReplicas.probes.requireReadOnlybooleantrueReplica only ready when confirmed read-only.
replication.readReplicas.probes.requireRunningReplicationbooleanfalseRequire IO and SQL replication threads running.
replication.binlog.formatstringROWBinlog format used by the source.
replication.binlog.retentionDaysinteger7Binlog retention in days. Overrides expireLogsSeconds when > 0.
replication.binlog.syncBinloginteger1sync_binlog value on the source (1 = fully durable).
replication.replicaTuning.parallelWorkersinteger4Parallel binlog applier workers on replicas.
replication.pdb.enabledbooleantrueEnable PodDisruptionBudget (default enabled in replication mode).
replication.pdb.minAvailableinteger1Minimum available pods.
replication.scheduling.enableDefaultPodAntiAffinitybooleantrueSpread source and replicas across different nodes automatically.
replication.scheduling.enableDefaultTopologySpreadbooleantrueEnable topology spread constraints for replication pods.

TLS

ParameterTypeDefaultDescription
tls.enabledbooleanfalseEnable MariaDB server-side TLS.
tls.existingSecretstring""Existing Secret with CA, certificate, and private key.
tls.caFilenamestringca.crtCA certificate filename in the secret.
tls.certFilenamestringtls.crtServer certificate filename.
tls.keyFilenamestringtls.keyServer private key filename.
tls.requireSecureTransportbooleanfalseReject plaintext connections (enforce TLS for all clients).
tls.client.enabledbooleanfalseUse TLS for internal chart client connections.

Backup

ParameterTypeDefaultDescription
backup.enabledbooleanfalseEnable scheduled mariadb-dump S3 backup.
backup.schedulestring"0 3 * * *"Cron schedule.
backup.archivePrefixstringmariadbPrefix for backup archive filenames.
backup.s3.endpointstring""S3-compatible endpoint URL.
backup.s3.bucketstring""Target bucket name.
backup.s3.existingSecretstring""Existing secret with S3 credentials.
backup.database.mariadbdumpArgsstring--single-transaction ...Extra args for mariadb-dump. Includes --routines --events --triggers by default.

Metrics

ParameterTypeDefaultDescription
metrics.enabledbooleanfalseEnable mysqld-exporter sidecar.
metrics.image.repositorystringdocker.io/prom/mysqld-exporterExporter image.
metrics.image.tagstring"v0.17.2"Exporter image tag.
metrics.serviceMonitor.enabledbooleanfalseCreate a Prometheus Operator ServiceMonitor.
metrics.serviceMonitor.intervalstring30sScrape interval.

NetworkPolicy

ParameterTypeDefaultDescription
networkPolicy.enabledbooleanfalseCreate an ingress-only NetworkPolicy.
networkPolicy.ingress.allowSameNamespacebooleantrueAllow traffic from pods in the same namespace.
networkPolicy.ingress.extraFromarray[]Extra ingress peer selectors.
networkPolicy.metrics.enabledbooleanfalseAllow ingress to the metrics port.

Security Context

MariaDB runs hardened by default:

ParameterDefaultDescription
podSecurityContext.fsGroup999Filesystem group for volume ownership.
podSecurityContext.seccompProfile.typeRuntimeDefaultSeccomp profile.
securityContext.runAsUser999Container UID.
securityContext.runAsNonRoottrueEnforce non-root execution.
securityContext.allowPrivilegeEscalationfalseDisallow privilege escalation.
securityContext.capabilities.drop["ALL"]Drop all Linux capabilities.

Scheduling

ParameterTypeDefaultDescription
terminationGracePeriodSecondsinteger120Grace period. Allows in-progress transactions to commit cleanly.
nodeSelectorobject{}Node selector for scheduling.
tolerationsarray[]Tolerations for scheduling.
affinityobject{}Affinity rules (replaces default anti-affinity if set).

More Information