MariaDB (MySQL) cluster: Azure tutorial
Important
Classic VMs will be retired on March 1, 2023.
If you use IaaS resources from ASM, please complete your migration by March 1, 2023. We encourage you to make the switch sooner to take advantage of the many feature enhancements in Azure Resource Manager.
For more information, see Migrate your IaaS resources to Azure Resource Manager by March 1, 2023.
Note
Azure has two different deployment models for creating and working with resources: Azure Resource Manager and classic. This article covers the classic deployment model. Microsoft recommends that most new deployments use the Azure Resource Manager model.
Note
MariaDB Enterprise cluster is now available in the Azure Marketplace. The new offering will automatically deploy a MariaDB Galera cluster on Azure Resource Manager. You should use the new offering from Azure Marketplace.
This article shows you how to create a multi-Master Galera cluster of MariaDBs (a robust, scalable, and reliable drop-in replacement for MySQL) to work in a highly available environment on Azure virtual machines.
Architecture overview
This article describes how to complete the following steps:
- Create a three-node cluster.
- Separate the data disks from the OS disk.
- Create the data disks in RAID-0/striped setting to increase IOPS.
- Use Azure Load Balancer to balance the load for the three nodes.
- To minimize repetitive work, create a VM image that contains MariaDB + Galera and use it to create the other cluster VMs.
Note
This topic uses the Azure CLI tools, so make sure to download them and connect them to your Azure subscription according to the instructions. If you need a reference to the commands available in the Azure CLI, see the Azure CLI command reference. You will also need to create an SSH key for authentication and make note of the .pem file location.
Create the template
Infrastructure
Create an affinity group to hold the resources together.
azure account affinity-group create mariadbcluster --location "North Europe" --label "MariaDB Cluster"
Create a virtual network.
azure network vnet create --address-space 10.0.0.0 --cidr 8 --subnet-name mariadb --subnet-start-ip 10.0.0.0 --subnet-cidr 24 --affinity-group mariadbcluster mariadbvnet
Create a storage account to host all our disks. You shouldn't place more than 40 heavily used disks on the same storage account to avoid hitting the 20,000 IOPS storage account limit. In this case, you're well below that limit, so you'll store everything on the same account for simplicity.
azure storage account create mariadbstorage --label mariadbstorage --affinity-group mariadbcluster
Find the name of the CentOS 7 virtual machine image.
azure vm image list | findstr CentOS
The output will be something like
5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-70-20140926
.Use that name in the following step.
Create the VM template and replace /path/to/key.pem with the path where you stored the generated .pem SSH key.
azure vm create --virtual-network-name mariadbvnet --subnet-names mariadb --blob-url "http://mariadbstorage.blob.core.windows.net/vhds/mariadbhatemplate-os.vhd" --vm-size Medium --ssh 22 --ssh-cert "/path/to/key.pem" --no-ssh-password mariadbtemplate 5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-70-20140926 azureuser
Attach four 500-GB data disks to the VM for use in the RAID configuration.
FOR /L %d IN (1,1,4) DO azure vm disk attach-new mariadbhatemplate 512 http://mariadbstorage.blob.core.windows.net/vhds/mariadbhatemplate-data-%d.vhd
Use SSH to sign in to the template VM that you created at mariadbhatemplate.cloudapp.net:22, and connect by using your private key.
Software
Get the root.
sudo su
Install RAID support:
a. Install mdadm.
yum install mdadm
b. Create the RAID0/stripe configuration with an EXT4 file system.
mdadm --create --verbose /dev/md0 --level=stripe --raid-devices=4 /dev/sdc /dev/sdd /dev/sde /dev/sdf mdadm --detail --scan >> /etc/mdadm.conf mkfs -t ext4 /dev/md0
c. Create the mount point directory.
mkdir /mnt/data
d. Retrieve the UUID of the newly created RAID device.
blkid | grep /dev/md0
e. Edit /etc/fstab.
vi /etc/fstab
f. Add the device to enable auto mounting on reboot, replacing the UUID with the value obtained from the previous blkid command.
UUID=<UUID FROM PREVIOUS> /mnt/data ext4 defaults,noatime 1 2
g. Mount the new partition.
mount /mnt/data
Install MariaDB.
a. Create the MariaDB.repo file.
vi /etc/yum.repos.d/MariaDB.repo
b. Fill the repo file with the following content:
[mariadb] name = MariaDB baseurl = http://yum.mariadb.org/10.0/centos7-amd64 gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB gpgcheck=1
c. To avoid conflicts, remove existing postfix and mariadb-libs.
yum remove postfix mariadb-libs-*
d. Install MariaDB with Galera.
yum install MariaDB-Galera-server MariaDB-client galera
Move the MySQL data directory to the RAID block device.
a. Copy the current MySQL directory into its new location and remove the old directory.
cp -avr /var/lib/mysql /mnt/data rm -rf /var/lib/mysql
b. Set permissions for the new directory accordingly.
chown -R mysql:mysql /mnt/data && chmod -R 755 /mnt/data/
c. Create a symlink that points the old directory to the new location on the RAID partition.
ln -s /mnt/data/mysql /var/lib/mysql
Because SELinux interferes with the cluster operations, it is necessary to disable it for the current session. Edit
/etc/selinux/config
to disable it for subsequent restarts.setenforce 0 then editing `/etc/selinux/config` to set `SELINUX=permissive`
Validate MySQL runs.
a. Start MySQL.
service mysql start
b. Secure the MySQL installation, set the root password, remove anonymous users to disable remote root login, and remove the test database.
mysql_secure_installation
c. Create a user on the database for cluster operations, and optionally for your applications.
mysql -u root -p GRANT ALL PRIVILEGES ON *.* TO 'cluster'@'%' IDENTIFIED BY 'p@ssw0rd' WITH GRANT OPTION; FLUSH PRIVILEGES; exit
d. Stop MySQL.
service mysql stop
Create a configuration placeholder.
a. Edit the MySQL configuration to create a placeholder for the cluster settings. Do not replace the
<Variables>
or uncomment now. That will happen after you create a VM from this template.vi /etc/my.cnf.d/server.cnf
b. Edit the galera section and clear it out.
c. Edit the [mariadb] section.
wsrep_provider=/usr/lib64/galera/libgalera_smm.so binlog_format=ROW wsrep_sst_method=rsync bind-address=0.0.0.0 # When set to 0.0.0.0, the server listens to remote connections default_storage_engine=InnoDB innodb_autoinc_lock_mode=2 wsrep_sst_auth=cluster:p@ssw0rd # CHANGE: Username and password you created for the SST cluster MySQL user #wsrep_cluster_name='mariadbcluster' # CHANGE: Uncomment and set your desired cluster name #wsrep_cluster_address="gcomm://mariadb1,mariadb2,mariadb3" # CHANGE: Uncomment and Add all your servers #wsrep_node_address='<ServerIP>' # CHANGE: Uncomment and set IP address of this server #wsrep_node_name='<NodeName>' # CHANGE: Uncomment and set the node name of this server
Open required ports on the firewall by using FirewallD on CentOS 7.
- MySQL:
firewall-cmd --zone=public --add-port=3306/tcp --permanent
- GALERA:
firewall-cmd --zone=public --add-port=4567/tcp --permanent
- GALERA IST:
firewall-cmd --zone=public --add-port=4568/tcp --permanent
- RSYNC:
firewall-cmd --zone=public --add-port=4444/tcp --permanent
- Reload the firewall:
firewall-cmd --reload
- MySQL:
Optimize the system for performance. For more information, see performance tuning strategy.
a. Edit the MySQL configuration file again.
vi /etc/my.cnf.d/server.cnf
b. Edit the [mariadb] section and append the following content:
Note
We recommend that innodb_buffer_pool_size is 70 percent of your VM's memory. In this example, it has been set at 2.45 GB for the medium Azure VM with 3.5 GB of RAM.
innodb_buffer_pool_size = 2508M # The buffer pool contains buffered data and the index. This is usually set to 70 percent of physical memory. innodb_log_file_size = 512M # Redo logs ensure that write operations are fast, reliable, and recoverable after a crash max_connections = 5000 # A larger value will give the server more time to recycle idled connections innodb_file_per_table = 1 # Speed up the table space transmission and optimize the debris management performance innodb_log_buffer_size = 128M # The log buffer allows transactions to run without having to flush the log to disk before the transactions commit innodb_flush_log_at_trx_commit = 2 # The setting of 2 enables the most data integrity and is suitable for Master in MySQL cluster query_cache_size = 0
Stop MySQL, disable MySQL service from running on startup to avoid disrupting the cluster when adding a node, and deprovision the machine.
service mysql stop chkconfig mysql off waagent -deprovision
Capture the VM through the portal. (Currently, issue #1268 in the Azure CLI tools describes the fact that images captured by the Azure CLI tools do not capture the attached data disks.)
a. Shut down the machine through the portal.
b. Click Capture and specify the image name as mariadb-galera-image. Provide a description and check "I have run waagent."
Create the cluster
Create three VMs with the template you created, and then configure and start the cluster.
- Create the first CentOS 7 VM from the mariadb-galera-image image you created, providing the following information:
Virtual network name: mariadbvnet
Subnet: mariadb
Machine size: medium
Cloud service name: mariadbha (or whatever name you want to be accessed through mariadbha.cloudapp.net)
Machine name: mariadb1
Username: azureuser
SSH access: enabled
Passing the SSH certificate .pem file and replacing /path/to/key.pem with the path where you stored the generated .pem SSH key.
Note
The following commands are split over multiple lines for clarity, but you should enter each as one line.
azure vm create --virtual-network-name mariadbvnet --subnet-names mariadb --availability-set clusteravset --vm-size Medium --ssh-cert "/path/to/key.pem" --no-ssh-password --ssh 22 --vm-name mariadb1 mariadbha mariadb-galera-image azureuser
Create two more virtual machines by connecting them to the mariadbha cloud service. Change the VM name and the SSH port to a unique port not conflicting with other VMs in the same cloud service.
azure vm create --virtual-network-name mariadbvnet --subnet-names mariadb --availability-set clusteravset --vm-size Medium --ssh-cert "/path/to/key.pem" --no-ssh-password --ssh 23 --vm-name mariadb2 --connect mariadbha mariadb-galera-image azureuser
For MariaDB3:
azure vm create
--virtual-network-name mariadbvnet
--subnet-names mariadb
--availability-set clusteravset
--vm-size Medium
--ssh-cert "/path/to/key.pem"
--no-ssh-password
--ssh 24
--vm-name mariadb3
--connect mariadbha mariadb-galera-image azureuser
You will need to get the internal IP address of each of the three VMs for the next step:
Use SSH to sign in to the three VMs and edit the configuration file on each of them.
sudo vi /etc/my.cnf.d/server.cnf
Uncomment
wsrep_cluster_name
andwsrep_cluster_address
by removing the # at the beginning of the line. Additionally, replace<ServerIP>
inwsrep_node_address
and<NodeName>
inwsrep_node_name
with the VM's IP address and name, respectively, and uncomment those lines as well.Start the cluster on MariaDB1 and let it run at startup.
sudo service mysql bootstrap chkconfig mysql on
Start MySQL on MariaDB2 and MariaDB3 and let it run at startup.
sudo service mysql start chkconfig mysql on
Load balance the cluster
When you created the clustered VMs, you added them into an availability set called clusteravset to ensure that they were put on different fault and update domains and that Azure never does maintenance on all machines at once. This configuration meets the requirements to be supported by the Azure service level agreement (SLA).
Now use Azure Load Balancer to balance requests between the three nodes.
Run the following commands on your machine by using the Azure CLI.
The command parameters structure is: azure vm endpoint create-multiple <MachineName> <PublicPort>:<VMPort>:<Protocol>:<EnableDirectServerReturn>:<Load Balanced Set Name>:<ProbeProtocol>:<ProbePort>
azure vm endpoint create-multiple mariadb1 3306:3306:tcp:false:MySQL:tcp:3306
azure vm endpoint create-multiple mariadb2 3306:3306:tcp:false:MySQL:tcp:3306
azure vm endpoint create-multiple mariadb3 3306:3306:tcp:false:MySQL:tcp:3306
The CLI sets the load balancer probe interval to 15 seconds, which might be a bit too long. Change it in the portal under Endpoints for any of the VMs.
Select Reconfigure the Load-Balanced Set.
Change Probe Interval to 5 seconds and save your changes.
Validate the cluster
The hard work is done. The cluster should be now accessible at mariadbha.cloudapp.net:3306
, which hits the load balancer and route requests between the three VMs smoothly and efficiently.
Use your favorite MySQL client to connect, or connect from one of the VMs to verify that this cluster is working.
mysql -u cluster -h mariadbha.cloudapp.net -p
Then create a database and populate it with some data.
CREATE DATABASE TestDB;
USE TestDB;
CREATE TABLE TestTable (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, value VARCHAR(255));
INSERT INTO TestTable (value) VALUES ('Value1');
INSERT INTO TestTable (value) VALUES ('Value2');
SELECT * FROM TestTable;
The database you created returns the following table:
+----+--------+
| id | value |
+----+--------+
| 1 | Value1 |
| 4 | Value2 |
+----+--------+
2 rows in set (0.00 sec)
Next steps
In this article, you created a three-node MariaDB + Galera highly available cluster on Azure virtual machines running CentOS 7. The VMs are load balanced with Azure Load Balancer.
You might want to look at another way to cluster MySQL on Linux and ways to optimize and test MySQL performance on Azure Linux VMs.