Highly available & distributed MySQL database with MariaDB & Galera Cluster. Supports auto failover.
1. Gather your hosts
In order to have a more flexible configuration, and not have to remember IP addresses, edit /etc/hosts and insert the following lines:
100.0.1.10 db1
100.0.1.11 db2
100.0.1.12 db3Modify each IP address & each hostname as you please.
It is (obviously) possible to add IPv6 addresses:
fe80::1 db1
fe80::2 db2
fe80::2 db32. Install MariaDB & Galera Cluster
- Debian:Copy
sudo apt install mariadb-server galera-4 - Centos/Fedora/RHEL:Copy
sudo dnf install mariadb-server mariadb-server-galera - Gentoo:Copy
sudo emerge dev-db/mariadb sys-cluster/galera
3. Configure the first node
Edit /etc/mysql/mariadb.cnf.d/50-server.cnf & make sure the following line is commented:
# bind-address = 0.0.0.0Create the user that will be used for replication: (modify all bold parameters)
mysql -u root -pCREATE USER 'replication' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'replication';
FLUSH PRIVILEGES;Edit /etc/mysql/mariadb.cnf.d/60-galera.cnf: (modify all bold parameters)
# Debian: [galera]
# RHEL: [mysqld]
[galera]
binlog_format = row
default-storage-engine = innodb
innodb_autoinc_lock_mode = 2
# Galera Provider
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
# Cluster
wsrep_cluster_name = "MariaDB Galera Cluster"
wsrep_cluster_address = "gcomm://db1,db2,db3"
wsrep_sst_method = rsync
wsrep_sst_auth = replication:passwd
# This node's config
bind-address = db1
wsrep_node_name = "db1"
wsrep_node_address = "db1"
wsrep_node_receive_address = "db1"
wsrep_node_incoming_address = "db1"Create the cluster:
systemctl stop mariadb
galera_new_cluster4. Configuring the other nodes
Now that the cluster has been configured on the first node, you need to copy the configuration file to all other nodes, making sure to modify the last 5 parameters, which uniquely identify the node.
Example: configuration on a second node.
# Debian: [galera]
# RHEL: [mysqld]
[galera]
binlog_format = row
default-storage-engine = innodb
innodb_autoinc_lock_mode = 2
# Galera Provider
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
# Cluster
wsrep_cluster_name = "MariaDB Galera Cluster"
wsrep_cluster_address = "gcomm://db1,db2,db3"
wsrep_sst_method = rsync
wsrep_sst_auth = replication:passwd
# This node's config
bind-address = db2
wsrep_node_name = "db2"
wsrep_node_address = "db2"
wsrep_node_receive_address = "db2"
wsrep_node_incoming_address = "db2"After configuring each node, you can start MariaDB:
systemctl start mariadb5. Configure the firewall
Make sure to open the following ports:
3306(TCP): MySQL Client Connections & State Snapshot Transfer (mysqldump)4567(TCP/UDP): Galera Cluster Replication4568(TCP): Incremental State Transfer4444(TCP): State Snapshot Transfers
CentOS/Fedora/RHEL (firewalld):
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --zone=public --add-port=4567/tcp --permanent
firewall-cmd --zone=public --add-port=4567/udp --permanent
firewall-cmd --zone=public --add-port=4568/tcp --permanent
firewall-cmd --zone=public --add-port=4444/tcp --permanent
firewall-cmd --reloadDebian (ufw):
ufw allow 3306,4567,4568,4444/tcp
ufw allow 4567/udpThis is only an example config. It is highly recommended you modify it so that only your nodes can communicate on these ports.
6. Configuration test
Verify that your cluster has the right number of nodes with the following command:
mysql -e "SHOW STATUS LIKE 'wsrep_cluster_size'"In this case, since we configured 3 nodes, the command will return the following:
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| wsrep_cluster_size | 3 |
+--------------------+-------+To be 100% certain that replication works, let's create a DB and a test table on a node:
mysql -u root -pCREATE DATABASE testdb;
CREATE TABLE testdb.msg (
'id' INT NOT NULL AUTO_INCREMENT,
'message' VARCHAR(255) NOT NULL,
PRIMARY KEY ('id')
);
INSERT INTO testdb.msg ('id', 'message') VALUES (1, 'AAA');
INSERT INTO testdb.msg ('id', 'message') VALUES (2, 'BBB');
INSERT INTO testdb.msg ('id', 'message') VALUES (3, 'CCC');Execute this command on any other node:
mysql -e "SELECT * FROM testdb.msg"7. Load balancer with nginx
It's possible to optionally use nginx as a cluster load balancer. Edit /etc/nginx/nginx.conf and add the following config:
stream {
upstream cluster {
zone tcp_servers 64k;
server db1:3306;
server db2:3306;
server db3:3306;
}
# NOTE: change this port if you already have
# mariadb/mysql running on this host
server {
# required: nginx >=1.25.5
# https://nginx.org/en/docs/stream/ngx_stream_core_module.html#server_name
# server_name db.internal.example.com;
listen 3306;
proxy_pass cluster;
proxy_connect_timeout 3s;
}
}
