Diagram of MySQL InnoDB Cluster deployment architecture using Docker containers and Kubernetes pods.

Integrating MySQL InnoDB Cluster with Docker and Kubernetes

Running MySQL InnoDB Cluster inside containers is now common, but it adds orchestration, storage, and networking concerns that DBAs must handle deliberately. This article walks through how to integrate InnoDB Cluster with Docker and Kubernetes in a practical, production-minded way.

Core concepts: InnoDB Cluster and containers

MySQL InnoDB Cluster combines three main pieces:

  • InnoDB storage engine for transactional data
  • Group Replication for high-availability replication
  • MySQL Router for routing applications to the correct primary or secondary

In containers, you typically map each MySQL server instance to a container, and let Docker or Kubernetes manage placement and restart. The key is to separate ephemeral containers from persistent storage and stable network identities.

Reference layouts in Docker and Kubernetes

Typical Docker layout

For a simple Docker-based lab or small deployment, you might run:

  • 3 MySQL server containers (Group Replication members)
  • 1–2 MySQL Router containers
  • Named volumes or bind mounts for data
+-------------------------- Docker host --------------------------+
|                                                                |
|  [router-1]    [router-2]                                     |
|      |             |                                          |
|   +--+-------------+------------------------------+           |
|   |                                             | |           |
| [mysql-1]      [mysql-2]      [mysql-3]         | |           |
|   |GR member     |GR member     |GR member      | |           |
|   +--------------+--------------+---------------+ |           |
|    volume-1        volume-2        volume-3       |           |
+---------------------------------------------------+           |

Typical Kubernetes layout

In Kubernetes, the usual pattern is:

  • One StatefulSet for the MySQL server pods
  • One Deployment for MySQL Router pods
  • PersistentVolumeClaims (PVCs) for data
  • Services for intra-cluster traffic and application access
+-------------------------- Kubernetes --------------------------+
| StatefulSet: mysql                                          |
|   Pod mysql-0 <- PVC mysql-0-pv                             |
|   Pod mysql-1 <- PVC mysql-1-pv                             |
|   Pod mysql-2 <- PVC mysql-2-pv                             |
|                                                              |
| Deployment: mysql-router                                    |
|   Pod router-0                                              |
|   Pod router-1                                              |
|                                                              |
| Services:                                                   |
|   mysql-internal (ClusterIP)  - server-to-server traffic    |
|   mysql-router (LoadBalancer/ClusterIP) - app entrypoint    |
+--------------------------------------------------------------+

Preparing an InnoDB Cluster image

You can use the official MySQL Server container image as a base. The main requirements are:

  • Enable Group Replication
  • Configure a unique server ID and instance name
  • Expose the MySQL port (3306) and, if needed, group communication ports

Example my.cnf snippet suitable for containerised InnoDB Cluster members:

[mysqld]
server_id=1
log_bin=binlog
binlog_format=ROW
transaction_write_set_extraction=XXHASH64
loose-group_replication_group_name="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
loose-group_replication_start_on_boot=OFF
loose-group_replication_local_address="0.0.0.0:33061"
loose-group_replication_group_seeds="mysql-0:33061,mysql-1:33061,mysql-2:33061"
loose-group_replication_bootstrap_group=OFF

In Docker, you can mount this configuration from the host. In Kubernetes, use a ConfigMap and mount it into /etc/my.cnf.d/ or similar.

Running InnoDB Cluster with Docker

Step 1: Create a Docker network and volumes

docker network create innodb-net

for i in 1 2 3; do
  docker volume create innodb-data-$i
done

Step 2: Start MySQL containers

docker run -d --name mysql-1 \
  --network innodb-net \
  -e MYSQL_ROOT_PASSWORD=secret \
  -v innodb-data-1:/var/lib/mysql \
  -v /opt/mysql/conf.d:/etc/my.cnf.d \
  mysql:latest

# Repeat for mysql-2, mysql-3 with their own volumes

Ensure each container has a unique server_id (via environment or config) and that the Group Replication seed list matches the container hostnames.

Step 3: Initialise the InnoDB Cluster

Use the MySQL Shell (on the host or in a separate container) to configure the cluster:

mysqlsh root@mysql-1 --password=secret -- dba.createCluster('prodCluster')

Then add instances:

mysqlsh root@mysql-1 --password=secret -- \
  dba.getCluster('prodCluster').addInstance('root@mysql-2')

mysqlsh root@mysql-1 --password=secret -- \
  dba.getCluster('prodCluster').addInstance('root@mysql-3')

Step 4: Run MySQL Router in Docker

Bootstrap MySQL Router using MySQL Shell, then run it as a container on the same network:

mysqlrouter --bootstrap root@mysql-1:3306 --user=mysqlrouter

docker run -d --name mysql-router \
  --network innodb-net \
  -p 6446:6446 \
  -v /opt/mysqlrouter/conf.d:/etc/mysqlrouter \
  mysql/mysql-router:latest

Applications connect to the router’s exposed port (for example, 6446) instead of directly to any member.

Running InnoDB Cluster on Kubernetes

Step 1: Storage and StatefulSet

Define a StorageClass in your cluster, then create a StatefulSet for MySQL. A minimal YAML outline:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-internal
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:latest
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-root
              key: password
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 50Gi

Mount your Group Replication configuration via a ConfigMap. Each pod gets its own PVC, which persists across restarts or rescheduling.

Step 2: Headless service for intra-cluster traffic

Create a headless Service to give each pod a stable DNS name:

apiVersion: v1
kind: Service
metadata:
  name: mysql-internal
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
  - port: 3306
    name: mysql

Pods will be reachable as mysql-0.mysql-internal, mysql-1.mysql-internal, and so on. Use these hostnames in your group_replication_group_seeds configuration.

Step 3: Initialise the cluster

Once all pods are running, exec into one pod and use MySQL Shell:

kubectl exec -it mysql-0 -- bash
mysqlsh root@localhost -- dba.createCluster('k8sCluster')
mysqlsh root@localhost -- \
  dba.getCluster('k8sCluster').addInstance('[email protected]')
mysqlsh root@localhost -- \
  dba.getCluster('k8sCluster').addInstance('[email protected]')

Step 4: MySQL Router as a Deployment

Run MySQL Router as a stateless Deployment. A minimal sketch:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-router
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mysql-router
  template:
    metadata:
      labels:
        app: mysql-router
    spec:
      containers:
      - name: mysql-router
        image: mysql/mysql-router:latest
        ports:
        - containerPort: 6446

Expose it via a Service for applications:

apiVersion: v1
kind: Service
metadata:
  name: mysql-router
spec:
  type: ClusterIP
  selector:
    app: mysql-router
  ports:
  - port: 6446
    targetPort: 6446

Applications connect to the mysql-router Service; Router then forwards to the correct primary or secondary nodes.

Best practices for containerised InnoDB Cluster

Storage and durability

  • Use persistent volumes (Docker volumes or Kubernetes PVCs) for /var/lib/mysql.
  • Avoid hostPath volumes in Kubernetes for production; use a proper storage backend.
  • Ensure fsync and flush behaviour is not disabled in container images.
  • Monitor disk latency; Group Replication is sensitive to slow writes.

Networking and timeouts

  • Keep inter-node latency low; place all members in the same region and low-latency network.
  • Configure group_replication_member_expel_timeout and related settings conservatively to avoid flapping members.
  • Ensure Kubernetes NetworkPolicies or firewalls allow group replication ports between pods.

Health checks and liveness

  • Use liveness and readiness probes in Kubernetes based on mysqladmin ping or a simple SQL query.
  • Ensure routers only become ready when they can reach at least one primary.
  • In Docker, use healthcheck instructions in Dockerfiles or docker-compose.

Backups and recovery

  • Run logical or physical backups from a dedicated backup container or pod.
  • Store backups outside the same storage backend as primary data.
  • Test restore into a separate cluster to validate configuration and data.

Container orchestration makes MySQL highly portable, but it does not remove the need for disciplined backup, monitoring, and capacity planning.

Operational reality

Operational tips and common pitfalls

  • Pin MySQL versions across all members; avoid mixed versions unless following supported upgrade paths.
  • Use resource requests and limits in Kubernetes so that MySQL pods are not starved of CPU or memory.
  • Log to stdout/stderr for easy collection, but ensure slow logs and error logs are persisted if needed.
  • Avoid using latest tags in production; pin to a specific, tested version.

This article offers general technical guidance. Validate all configurations in a safe environment before applying them to production.

Container platforms work well with MySQL InnoDB Cluster when you respect stateful workloads: keep storage persistent, networking predictable, and operations scriptable. With those foundations in place, Docker and Kubernetes can give you repeatable, resilient deployments without compromising database integrity.

Smart reads for curious minds

We don’t spam! Read more in our privacy policy

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *