MySQL
Production-ready MySQL deployment with support for standalone and source-replica replication architectures.
Key Features
- Standalone and replication — Single instance or source-replica topology
- Automatic initialization — Init scripts and custom configuration
- Backup support — Configurable backup CronJobs to S3-compatible storage
- Metrics — Prometheus exporter with ServiceMonitor
- Security — Non-root containers, network policies, TLS support
- Persistent storage — Configurable PVCs with storage class selection
Architecture
Standalone
Single MySQL instance with persistent storage and optional S3 backup.
Source-Replica
Source (read-write) with binary log replication to read-only replicas.
Installation
HTTPS repository:
helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install my-mysql helmforge/mysql
OCI registry:
helm install my-mysql oci://ghcr.io/helmforgedev/helm/mysql
Deployment Examples
# values.yaml
architecture: standalone
auth:
rootPassword: 'my-secret-password'
database: myapp
username: myuser
password: 'user-password'
primary:
persistence:
size: 20Gi
metrics:
enabled: true
serviceMonitor:
enabled: true# values.yaml
architecture: replication
auth:
rootPassword: 'my-secret-password'
database: myapp
username: myuser
password: 'user-password'
replicationPassword: 'repl-password'
primary:
persistence:
size: 20Gi
secondary:
replicaCount: 2
persistence:
size: 20Gi# values.yaml
architecture: standalone
auth:
rootPassword: 'my-secret-password'
database: myapp
primary:
persistence:
size: 20Gi
backup:
enabled: true
schedule: '0 3 * * *'
s3:
endpoint: https://s3.amazonaws.com
bucket: my-mysql-backups
accessKey: AKIAIOSFODNN7EXAMPLE
secretKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
retention:
days: 30# values.yaml — Use with phpMyAdmin or a web-based management tool
architecture: standalone
auth:
rootPassword: 'my-secret-password'
database: myapp
primary:
persistence:
size: 20Gi
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: phpmyadmin.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: phpmyadmin-tls
hosts:
- phpmyadmin.example.com
# annotations:
# cert-manager.io/cluster-issuer: letsencrypt-prodKey Values
| Key | Type | Default | Description |
|---|---|---|---|
architecture | string | standalone | Deployment architecture: standalone or replication |
auth.rootPassword | string | "" | MySQL root password |
auth.database | string | "" | Default database to create |
auth.username | string | "" | Default user to create |
auth.password | string | "" | Password for default user |
auth.replicationPassword | string | "" | Password for replication user |
primary.persistence.size | string | 8Gi | Primary PVC size |
primary.persistence.storageClass | string | "" | Storage class for primary PVC |
primary.resources.requests.memory | string | 256Mi | Memory request for primary |
primary.resources.requests.cpu | string | 250m | CPU request for primary |
secondary.replicaCount | integer | 1 | Number of read replicas |
secondary.persistence.size | string | 8Gi | Secondary PVC size |
backup.enabled | boolean | false | Enable S3 backup CronJob |
backup.schedule | string | 0 3 * * * | Cron schedule for backups |
metrics.enabled | boolean | false | Enable Prometheus exporter |
metrics.serviceMonitor.enabled | boolean | false | Create ServiceMonitor resource |
networkPolicy.enabled | boolean | false | Enable network policies |
tls.enabled | boolean | false | Enable TLS encryption |
service.ipFamilyPolicy | string | omitted | Service IP family policy: SingleStack, PreferDualStack, or RequireDualStack. Omit for cluster default. |
service.ipFamilies | array | omitted | Ordered list of IP families (IPv4, IPv6). Omit for cluster default. |
Dual-stack Networking
MySQL Services accept Kubernetes dual-stack configuration. By default, both service.ipFamilyPolicy and service.ipFamilies are unset and the chart inherits whatever the cluster advertises (matching prior behavior). Setting them propagates to every chart-managed Service: client, source, replicas, metrics, and the headless StatefulSet services.
service:
ipFamilyPolicy: PreferDualStack
ipFamilies:
- IPv4
- IPv6
PreferDualStack is the safer choice for clusters that may be single- or dual-stack: omit ipFamilies and the cluster auto-populates whatever it supports. Set ipFamilies explicitly only when the cluster is configured for both families — the Kubernetes API rejects an explicit family the cluster does not advertise. RequireDualStack enforces both.
Upgrade Notes
MySQL stores the root password during initial setup. On upgrade, ensure auth.rootPassword matches the original value
or the pod will fail to start with an authentication error.
- When enabling replication on an existing standalone instance, a full re-initialization is required
- Backup CronJob changes take effect on the next scheduled run
- Secondary replicas are read-only; write attempts return an error
Common Issues
If the root password in values doesn’t match the existing data directory, MySQL refuses to start.
Check logs with kubectl logs <pod> and verify the password matches.
Enable metrics and monitor mysql_slave_status_seconds_behind_master. Values consistently above 0 indicate the
replica cannot keep up — consider increasing replica resources or reducing write load.
More Information
See the source code and full values reference on GitHub.