Find file History
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Galera Replication for MySQL on Kubernetes

This document explains a simple demonstration example of running MySQL synchronous replication using Galera, specifically, Percona XtraDB cluster. The example is simplistic and used a fixed number (3) of nodes but the idea can be built upon and made more dynamic as Kubernetes matures.


This example assumes that you have a Kubernetes cluster installed and running, and that you have installed the kubectl command line tool somewhere in your path. Please see the getting started for installation instructions for your platform.

Also, this example requires the image found in the image directory. For your convenience, it is built and available on Docker's public image repository as capttofu/percona_xtradb_cluster_5_6. It can also be built which would merely require that the image in the pod or replication controller files is updated.

This example was tested on OS X with a Galera cluster running on VMWare using the fine repo developed by Paulo Pires [] and client programs built for OS X.

Basic concept

The basic idea is this: three replication controllers with a single pod, corresponding services, and a single overall service to connect to all three nodes. One of the important design goals of MySQL replication and/or clustering is that you don't want a single-point-of-failure, hence the need to distribute each node or slave across hosts or even geographical locations. Kubernetes is well-suited for facilitating this design pattern using the service and replication controller configuration files in this example.

By defaults, there are only three pods (hence replication controllers) for this cluster. This number can be increased using the variable NUM_NODES, specified in the replication controller configuration file. It's important to know the number of nodes must always be odd.

When the replication controller is created, it results in the corresponding container to start, run an entrypoint script that installs the MySQL system tables, set up users, and build up a list of servers that is used with the galera parameter wsrep_cluster_address. This is a list of running nodes that galera uses for election of a node to obtain SST (Single State Transfer) from.

Note: Kubernetes best-practices is to pre-create the services for each controller, and the configuration files which contain the service and replication controller for each node, when created, will result in both a service and replication contrller running for the given node. An important thing to know is that it's important that initially pxc-node1.yaml be processed first and no other pxc-nodeN services that don't have corresponding replication controllers should exist. The reason for this is that if there is a node in wsrep_clsuter_address without a backing galera node there will be nothing to obtain SST from which will cause the node to shut itself down and the container in question to exit (and another soon relaunched, repeatedly).

First, create the overall cluster service that will be used to connect to the cluster:

kubectl create -f examples/storage/mysql-galera/pxc-cluster-service.yaml

Create the service and replication controller for the first node:

kubectl create -f examples/storage/mysql-galera/pxc-node1.yaml

Create services and controllers for the remaining nodes

Repeat the same previous steps for pxc-node2 and pxc-node3

When complete, you should be able connect with a MySQL client to the IP address service pxc-cluster to find a working cluster

An example of creating a cluster

Shown below are examples of Using kubectl from within the ./examples/storage/mysql-galera directory, the status of the lauched replication controllers and services can be confirmed

$ kubectl create -f examples/storage/mysql-galera/pxc-cluster-service.yaml 

$ kubectl create -f examples/storage/mysql-galera/pxc-node1.yaml 

$ kubectl create -f examples/storage/mysql-galera/pxc-node2.yaml 

$ kubectl create -f examples/storage/mysql-galera/pxc-node3.yaml 

Confirm a running cluster

Verify everything is running:

$ kubectl get rc,pods,services
CONTROLLER   CONTAINER(S)   IMAGE(S)                                    SELECTOR           REPLICAS
pxc-node1    pxc-node1      capttofu/percona_xtradb_cluster_5_6:beta    name=pxc-node1     1
pxc-node2    pxc-node2      capttofu/percona_xtradb_cluster_5_6:beta    name=pxc-node2     1
pxc-node3    pxc-node3      capttofu/percona_xtradb_cluster_5_6:beta    name=pxc-node3     1
NAME              READY     STATUS    RESTARTS   AGE
pxc-node1-h6fqr   1/1       Running   0          41m
pxc-node2-sfqm6   1/1       Running   0          41m
pxc-node3-017b3   1/1       Running   0          40m
NAME          LABELS    SELECTOR           IP(S)            PORT(S)
pxc-cluster   <none>    unit=pxc-cluster    3306/TCP
pxc-node1     <none>    name=pxc-node1   3306/TCP
pxc-node2     <none>    name=pxc-node2    3306/TCP
pxc-node3     <none>    name=pxc-node3    3306/TCP

The cluster should be ready for use!

Connecting to the cluster

Using the name of pxc-cluster service running interactively using kubernetes exec, it is possible to connect to any of the pods using the mysql client on the pod's container to verify the cluster size, which should be 3. In this example below, pxc-node3 replication controller is chosen, and to find out the pod name, kubectl get pods and awk are employed:

$ kubectl get pods|grep pxc-node3|awk '{ print $1 }'

$ kubectl exec pxc-node3-0b5mc -i -t -- mysql -u root -p -h pxc-cluster

Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.6.24-72.2-56-log Percona XtraDB Cluster (GPL), Release rel72.2, Revision 43abf03, WSREP version 25.11, wsrep_25.11

Copyright (c) 2009-2015 Percona LLC and/or its affiliates
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show status like 'wsrep_cluster_size';
| Variable_name      | Value |
| wsrep_cluster_size | 3     |
1 row in set (0.06 sec)

At this point, there is a working cluster that can begin being used via the pxc-cluster service IP address!


This setup certainly can become more fluid and dynamic. One idea is to perhaps use an etcd container to store information about node state. Originally, there was a read-only kubernetes API available to each container but that has since been removed. Also, Kelsey Hightower is working on moving the functionality of confd to Kubernetes. This could replace the shell duct tape that builds the cluster configuration file for the image.