Sign inSign up

instantlinux/mariadb-galera

By instantlinux

•Updated 10 days ago

Automatic cluster generation of MariaDB 12.x

Helm
Image
3

10K+

instantlinux/mariadb-galera repository overview

⁠mariadb-galera

MariaDB 12.x with automatic cluster generation under kubernetes / swarm using named volumes for data persistence. This has robust bootstrap logic based on MariaDB / Galera documentation for automated cluster create / join operations. Requires an etcd instance for sharing instance-health data across the cluster.

⁠Usage - kubernetes

Define the following dependencies before launching the cluster: password for root, network load balancer, and a dedicated etcd key-value store. Here's how:

Create a random root password:

SECRET=mysql-root-password
PW=$(uuidgen | base64)
cat >/dev/shm/new.yaml <<EOT
---
apiVersion: v1
data:
  $SECRET: $PW
kind: Secret
metadata:
  name: $SECRET
  namespace: \$K8S_NAMESPACE
type: Opaque
EOT
sekret enc /dev/shm/new.yaml >secrets/$SECRET
rm /dev/shm/new.yaml

You can use a tool like sops⁠ or sekret⁠ to generate the secrets file.

Set any local my.cnf values in files under a volume mount for /etc/mysql/my.cnf.d (mapped as $ADMIN_PATH/mariadb/etc/). Use a ConfigMap when running under Kubernetes (example is included).

⁠Networking

The container exposes ports 3306, 4444, 4567 and 4568 on the ingress network. An internal network is needed for cluster-sync traffic and/or backups (use mariabackup, or the mysqldump container provided here). In order to enable connections directly to each cluster member for write-safe access or troubleshooting, if you're running a recent version of Docker you can override its ingress load-balancer thus:

    services:
      db:
        ...
        ports:
        - target: 3306
          published: <port>
          protocol: tcp
          mode: host

You almost definitely want a separate load-balancer for serving your published port. This method is defined and documented here in kubernetes.yaml⁠.

⁠DNS names and read/write

With MariaDB technology, write performance is limited to I/O throughput of the slowest single node in the cluster. Read performance can be scaled across the full cluster and is limited only by network capacity.

If you set up a cluster and spread database write traffic across all nodes, performance will be worse than with a single cluster because of issues described in multi-master conflicts⁠. Your logs will have messages like these:

WSREP: MDL conflict db=jira7 table=rundetails ticket=6 solved by abort

and the cluster won't provide stable performance. To make this long story short, here are the steps to take:

  • Allocate two static IP addresses on your LAN
  • Define a primary and read-only DNS name, for example db.mysite.com and db-ro.mysite.com and add address A records for the two IPs
  • Set up an haproxy (or other) load balancer for the primary IP address, with one cluster node configured to serve traffic and the others defined as backup
  • Bind the built-in Docker or Kubernetes service to all the cluster members

For Docker Swarm users, this exercise is left to the reader. For Kubernetes, the kubernetes.yaml⁠ and Makefile⁠ provided here will automate these steps once you've set up the two DNS entries.

⁠Logging

Logs are sent to stdout / stderr with one exception: the slow query log. Add a volume mount of /var/log/mysql if you want to preserve that log.

⁠Setting up etcd

See the k8s/Makefile⁠ for a make etcd to start etcd under kubernetes. A docker-compose service definition is available at docker-tools/services/etcd⁠. Instructions for using the free discovery.etc.io bootstrap service are given there.

This repo has complete instructions for building a kubernetes cluster⁠ where you can launch with helm⁠ or kubernetes.yaml⁠ using make and customizing Makefile.vars⁠ after cloning this repo:

git clone https://github.com/instantlinux/docker-tools.git
cd docker-tools/k8s
# This make target is defined in Makefile.instances
make db00
⁠Restarting

When taking the database down, wait for all pods to stop, and then clear etcd entries for the cluster:

CLUSTER=db00
ETCD_HOST=10.101.1.19
etcdctl --endpoints=$ETCD_HOST:2379 del --prefix /galera/$CLUSTER

Then launch with the helm chart or docker-compose.

⁠Usage - swarm

This was originally developed under docker Swarm. A docker-compose⁠ file is a legacy of that original work. Before stack-deploying it, invoke docker secret create to generate the secret mysql-root-password, and define an ADMIN_PATH environment variable pointing to your my.cnf (it has to be in the same location on each docker node).

⁠Variables
VariableDefaultDescription
CLUSTER_JOINjoin address--usually not needed
CLUSTER_NAMEcluster01cluster name
CLUSTER_SIZE3expected number of nodes
DISCOVERY_SERVICEetcd:2379etcd host list, e.g. etcd1:2379,etcd2:2379
LOG_LEVELinfoset to debug for additional logging
REINSTALL_OKset to any value to enable reinstall over old volume
ROOT_SECNAMEmysql-root-passwordname of secret for password
TTL10longevity (in seconds) of keys posted to etcd
TZUTCtimezone
⁠Notes

When creating this image (in early 2017), DB clustering under Docker Swarm was still in its infancy and I could not find a clustering solution that would automatically restart without problems (like split-brain, or just never coming up) upon a simple "docker stack deploy ; docker stack rm ; docker stack deploy" repeated test cycle. This addresses that problem, using a minimal distro (tried Alpine Linux, wound up having to use debian). I like MariaDB better than MySQL / Percona solutions, after a few years of running MariaDB and a decade+ of running MySQL. A couple years later, there's still no better alternative.

Galera is finicky upon restarts so it requires a fair amount of logic to handle edge cases.

This container image is intended to be run in a 3-, 5-node, or larger configuration. It requires a stable etcd configuration for node discovery and master election at restart. A single instance can be invoked without HA resources using kubernetes-single.yaml.

There is no supported etcd3 library for python3 (as of Oct 2025). For now, this is using python-etcd3 0.12.0, last updated in 2020, with PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION set for compatibility.

⁠Credits

Thanks to ashraf-s9s of severalnines for the healthcheck script.

⁠Contributing

If you want to make improvements to this image, see CONTRIBUTING⁠.

Tag summary

Content type

Image

Digest

sha256:2f66eda19…

Size

147.7 MB

Last updated

about 1 month ago

docker pull instantlinux/mariadb-galera