We all love using databases to store our application data, but what if your database dies and you don't have a backup? Clustering may just help with that. Whilst we highly recommend you still take backups of your data, having a cluster will not only improve speed for both read and writes, it also provides high availability by distributing changes to different servers. In the event that one of the instances fails, others are already available and will continue serving your application. Who doesn't love that?!
Galera clusters can be run in two different configurations, active-passive and active-active. In the active-passive setup, all writes are made to a single active server and then copied to one or more passive servers that will take over in the event of an active server failure.
We will be configuring our cluster in an active-active setup running on three instances, this is the smallest configurable cluster.
You will need a total of three instances running Ubuntu 16.04, with a minimum of 1GB RAM (so our Extra Small instances will be fine). If you have a particularly high workload application you may want to choose a larger instance size (as a MySQL Galera cluster stores a lot of information in RAM).
We first need to add an external repository to each of our instances as MariaDB isn't patched to include Galera clustering by default.
First, we need to add the repository key using the
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
Now we have the key, we can add the MariaDB repository and then update the repository list once it has been added.
sudo add-apt-repository 'deb [arch=amd64,i386,ppc64el] http://ftp.utexas.edu/mariadb/repo/10.1/ubuntu xenial main' sudo apt-get update
Now we have installed the repository on all three instances, we can install MariaDB. The good news now is that with MariaDB 10.1, the MariaDB and Galera packages are combined, so you can install all the packages and dependencies required with a single command on each instance:
sudo apt-get install mariadb-server
The above command will install all of the dependencies for MariaDB and Galera for you. During the setup process you will be prompted to set a MariaDB administrative user.
Important: When you enter a password, this will be overwritten by the first instances in the cluster when we configure the replication to begin from Galera
We also need to install
rsync to ensure all nodes are kept up to date with file transfers. This should be installed by default on Ubuntu 16.04 but just in case, the command to install it is:
sudo apt-get install rsync
Now we have MariaDB installed on all three instances, we can start to configure it.
Each instance in the cluster will need to have pretty much an identical configuration. This is a good thing, as we can do all the configuration on one instance and then copy it over to the other two.
We will need to create a Galera configuration file that MariaDB can read and put it in the
/etc/mysql/conf.d directory (we'll use
vim, but you can use any other editor such as
sudo vim /etc/mysql/conf.d/galera.cnf
You can copy and paste the config below and edit the following sections:
[mysqld] binlog_format=ROW default-storage-engine=innodb innodb_autoinc_lock_mode=2 bind-address=0.0.0.0 # Galera Provider Configuration wsrep_on=ON wsrep_provider=/usr/lib/galera/libgalera_smm.so # Galera Cluster Configuration wsrep_cluster_name="civo_cluster" wsrep_cluster_address="gcomm://first_internal_ip,second_internal_ip,third_internal_ip" # Galera Synchronization Configuration wsrep_sst_method=rsync # Galera Node Configuration wsrep_node_address="this_instance_internal_ip" wsrep_node_name="this_instance_name"
Once you are happy with your configuration file, copy it to your clipboard and add it to the other two instances and modify the
Galera Node Configuration section to match up to that particular instance IP address and name.
By default MySQL sets the bind address to
/etc/mysql/my.cnf - we need to comment this out to ensure the
galera.cnf file is used correctly.
Important: This needs to be done on all three instances.
sudo vim /etc/mysql/my.cnf
# Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. # bind-address = 127.0.0.1
During the MariaDB installation, the database service would have started up. We need to stop the service so our cluster can be brought up. On all three of your instances stop the MariaDB service by doing the following:
sudo systemctl stop mysql
You will not get an output to say MariaDB has stopped. However, you can check the status by running the following command:
sudo systemctl status mysql
You should get something similar to the output below that shows the service is stopped:
Nov 10 16:48:15 mysql-1-civo systemd: Stopped MariaDB database server.
To bring up the first instance, we'll need to use a special startup script. The cluster is configured in such a way that each node that comes online tries to connect to at least one other node specified in the galera.cnf file to get its initial state. Without using the special script that allows systemd to pass the the
--wsrep-new-cluster parameter, a normal
systemctl start mysql would fail because there are no instances running for the first instance to connect with. To run the special script to prep the instance, run the following:
Once the command has been run, the instance will now be registered as part of the cluster and we can see if this has been successful by running the following:
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
Which should output something like:
+--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 1 | +--------------------+-------+
Now the first instance is online, we can bring up the remaining two instances using the normal method of starting a MariaDB server. They will automatically search for any member in the cluster list that is already online and join the cluster. We can bring up the second instance by running the following command:
sudo systemctl start mysql
Once done bring up the third instance with the same command. If everything is working as we expect, the cluster size should now have increased to 3 instances:
mysql -u root -p -e "SHOW STATUS LIKE 'wsrep_cluster_size'"
The output should look like:
+--------------------+-------+ | Variable_name | Value | +--------------------+-------+ | wsrep_cluster_size | 3 | +--------------------+-------+
The entire cluster is now online and communicating. Before we can really test the replication, there is a little house-keeping we need to do. In the current version of MariaDB for Debian based systems, the servers do routine maintenance with a special maintenance user. When we first install MariaDB on our instances the credentials for the user are randomly generated and stored in
/etc/mysql/debian.cnf and that is then inserted into MariaDB's database.
When we brought up the other two instances in the cluster, the credentials are automatically copied over to them, so the value in
debian.cnf no longer matches the password set in the database. This will mean anything that uses the maintenance account will try and connect to the database with the wrong password, which in turn will then fail on the second and third instance. A simple fix for this is to copy the first instance's
debian.cnf over to the other instances.
On the first node edit the following:
It should look something similar to this:
# Automatically generated for Debian scripts. DO NOT TOUCH! [client] host = localhost user = debian-sys-maint password = c4ok66WEMfLfIBQg socket = /var/run/mysqld/mysqld.sock [mysql_upgrade] host = localhost user = debian-sys-maint password = c4ok66WEMfLfIBQg socket = /var/run/mysqld/mysqld.sock basedir = /usr
Copy the above to your clipboard and then edit the same file on your second instance. Ignore the warning at the top that says
Automatically generated for Debian scripts. DO NOT TOUCH!. We need to make the changes for the cluster to work efficiently. Delete the content that is already there and simply paste your clipboard into the file on the second instance and save it. Repeat this for the third instance so all three now have the same
Now we have done the tidy up process, we can start to have fun with the cluster and test that the replication is working as we would like. On the first node let's create a test database and a test table on that database:
root@mysql-1-civo:~# mysql Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 10 Server version: 10.1.29-MariaDB-1~xenial mariadb.org binary distribution Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [(none)]> CREATE DATABASE galerarocks; Query OK, 1 row affected (0.12 sec) MariaDB [(none)]> CREATE TABLE galerarocks.testrep ( TestColumn VARCHAR(50) ); Query OK, 0 rows affected (2.62 sec)
Now that's done we can check if the database and table has been replicated over to the second and third instances:
root@mysql-2-civo:~# mysql -u root -p galerarocks Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 8 Server version: 10.1.29-MariaDB-1~xenial mariadb.org binary distribution Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [galerarocks]> show tables; +-----------------------+ | Tables_in_galerarocks | +-----------------------+ | testrep | +-----------------------+ 1 row in set (0.00 sec)
root@mysql-3-civo:~# mysql -u root -p galerarocks Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 5 Server version: 10.1.29-MariaDB-1~xenial mariadb.org binary distribution Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MariaDB [galerarocks]> show tables; +-----------------------+ | Tables_in_galerarocks | +-----------------------+ | testrep | +-----------------------+ 1 row in set (0.00 sec)
Excellent! As we can see the database has been replicated over to the other two instances in the cluster. You can also write on any one of the instances and it will replicate over to the other two. We now have a fully functioning Galera cluster!