Giter Club home page Giter Club logo

kubernetes-mysql-cluster's Introduction

MySQL with automatic failover on Kubernetes

Our requirement was an SQL server for modest loads but with high availability because it backs our login system and public web.

We want automatic failover, not manual, and a single configuration to maintain, not leaders and followers.

Initially we tried Postgres, but clustering solutions like pgpool-II felt a bit outdated, and patroni etc was overly complex for our needs.

Galera is a good fit for us with Kubernetes because it allows nodes to share the same configuration through wsrep_cluster_address="gcomm://host-0,host-1... where access to only 1 of those instances lets a new instance join the cluster.

As of MariaDB 10.1 the official docker image comes with "wsrep" support. Using official images direcly mean less maintenance for us.

Kubernetes recently added support for "stateful applications", the StatefulSet. There's a semi-official example using MySQL. It's more an example of what you can do with StatefulSet than a production setup. It uses the init container concept, which looks heavily alpha, to try to automate installation.

Using a semi-manual bootstrap process and a container with galera support built in, we were able to simplify the setup and thus the maintenance.

Tradeoffs

Testing this is a TODO.

The database should remain available during cluster upgrades and node replacement, i.e. when something like 1 out of 3 VMs is gone. A Kubernetes upgrade on GKE means 1 at a time is gone, with only a short period of time between one upgrade completes and the next starts.

Failure on 2 VMs concurrently probably mean our cluster is going down badly, and that SQL downtime isn't our major headache. In this case we expect the DB to recover automatically once 2 out of 3 nodes are live.

With 3 nodes we aim for the following characteristics, prioritizing consistency over performance:

  • Consistent reads if 1 or even 2 nodes are gone.
  • Block writes if 2 nodes are gone.
  • Ideally accept writes if 1 nodes are gone.

Preparations

Unless your Kubernetes setup has volume provisioning for StatefulSet (GKE has) you need to make sure the Persistent Volumes exist first.

Then:

  • Create namespace.
  • Create 10pvc.yml if you created PVs manually.
  • Create configmap (see 40configmap.sh) and secret (see 41secret.sh).
  • Create StatefulSet's "headless" service 20mariadb-service.yml.
  • Create the service that other applications depend on 30mysql-service.yml.

After that start bootstrapping.

Initialize volumes and cluster

First get a single instance with --wsrep-new-cluster up and running:

kubectl create -f ./
kubectl logs -f mariadb-0

You should see something like

...[Note] WSREP: Quorum results:
  version    = 3,
  component  = PRIMARY,
  conf_id    = 0,
  members    = 1/1 (joined/total),
  act_id     = 4,
  last_appl. = -1,
  protocols  = 0/7/3 (gcs/repl/appl),

Now keep that pod running, but change StatefulSet to create normal replicas.

./70unbootstrap.sh

This scales to three nodes. You can kubectl -n mysql logs -f mariadb-1 to see something like:

[Note] WSREP: Quorum results:
	version    = 3,
	component  = PRIMARY,
	conf_id    = 4,
	members    = 2/3 (joined/total),
	act_id     = 4,
	last_appl. = 0,
	protocols  = 0/7/3 (gcs/repl/appl),

Now you can kubectl -n mysql delete pod mariadb-0 and it'll be re-created without the --wsrep-new-cluster argument. Logs will confirm that the new mariadb-0 joins the cluster.

Keep at least 1 node running at all times - which is what you want anyway, and the manual "unbootstrap" step isn't a big deal.

phpMyAdmin

Carefully consider the security implications before you create this. Note that it uses a non-official image.

kubectl create -f myadmin/

PhpMyAdmin has a login page where you need a mysql user. The default for root is localhost-only access (the merits of this in a micorservices context can be discussed). To allow root login from phpMyAdmin:

# enter pod
kubectl exec -ti mariadb-0 -- /bin/bash
# inside pod
mysql --password=$MYSQL_ROOT_PASSWORD -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD' WITH GRANT OPTION;

kubernetes-mysql-cluster's People

Contributors

jacobh2 avatar solsson avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.