MariaDB Synced Databases Between Two VMs
Introduction
In this ThreeFold Guide, we show how to deploy a VPN with Wireguard and create a synced MariaDB database between the two servers using GlusterFS, a scalable network filesystem. Any change in one VM's database will be echoed in the other VM's database. This kind of deployment can lead to useful server architectures.
Main Steps
This guide might seems overwhelming, but the steps are carefully explained. Take your time and it will all work out!
To get an overview of the whole process, we present the main steps:
- Download the dependencies
- Find two 3Nodes on the TFGrid
- Deploy and set the VMs with Terraform
- Create a MariaDB database
- Set GlusterFS
Prerequisites
You need to download and install properly Terraform and Wireguard on your local computer. Simply follow the documentation depending on your operating system (Linux, MAC and Windows).
Find Nodes with the ThreeFold Explorer
We first need to decide on which 3Nodes we will be deploying our workload.
We thus start by finding two 3Nodes with sufficient resources. For this current MariaDB guide, we will be using 1 CPU, 2 GB of RAM and 50 GB of storage. We are also looking for a 3Node with a public IPv4 address.
- Go to the ThreeFold Grid Node Finder (Main Net)
- Find a 3Node with suitable resources for the deployment and take note of its node ID on the leftmost column
ID
- For proper understanding, we give further information on some relevant columns:
ID
refers to the node IDFree Public IPs
refers to available IPv4 public IP addressesHRU
refers to HDD storageSRU
refers to SSD storageMRU
refers to RAM (memory)CRU
refers to virtual cores (vcores)
- To quicken the process of finding proper 3Nodes, you can narrow down the search by adding filters:
- At the top left of the screen, in the
Filters
box, select the parameter(s) you want. - For each parameter, a new field will appear where you can enter a minimum number requirement for the 3Nodes.
Free SRU (GB)
: 50Free MRU (GB)
: 2Total CRU (Cores)
: 1Free Public IP
: 2- Note: if you want a public IPv4 address, it is recommended to set the parameter
FREE PUBLIC IP
to at least 2 to avoid false positives. This ensures that the shown 3Nodes have viable IP addresses.
- Note: if you want a public IPv4 address, it is recommended to set the parameter
- At the top left of the screen, in the
Once you've found a proper node, take node of its node ID. You will need to use this ID when creating the Terraform files.
Set the VMs
Create a Two Servers Wireguard VPN with Terraform
For this guide, we use two files to deploy with Terraform. The first file contains the environment variables and the second file contains the parameters to deploy our workloads.
To facilitate the deployment, only the environment variables file needs to be adjusted. The main.tf
file contains the environment variables (e.g. var.size
for the disk size) and thus you do not need to change this file.
Of course, you can adjust the deployment based on your preferences. That being said, it should be easy to deploy the Terraform deployment with the main.tf
as is.
On your local computer, create a new folder named terraform
and a subfolder called deployment-synced-db
. In the subfolder, store the files main.tf
and credentials.auto.tfvars
.
Modify the variable files to take into account your own seed phras and SSH keys. You should also specifiy the node IDs of the two 3Nodes you will be deploying on.
Create the Terraform Files
Open the terminal.
-
Go to the home folder
-
cd ~
-
-
Create the folder
terraform
and the subfolderdeployment-synced-db
:-
mkdir -p terraform/deployment-synced-db
-
cd terraform/deployment-synced-db
-
-
Create the
main.tf
file:-
nano main.tf
-
-
Copy the
main.tf
content and save the file.
terraform {
required_providers {
grid = {
source = "threefoldtech/grid"
}
}
}
variable "mnemonics" {
type = string
}
variable "SSH_KEY" {
type = string
}
variable "tfnodeid1" {
type = string
}
variable "tfnodeid2" {
type = string
}
variable "size" {
type = string
}
variable "cpu" {
type = string
}
variable "memory" {
type = string
}
provider "grid" {
mnemonics = var.mnemonics
network = "main"
}
locals {
name = "tfvm"
}
resource "grid_network" "net1" {
name = local.name
nodes = [var.tfnodeid1, var.tfnodeid2]
ip_range = "10.1.0.0/16"
description = "newer network"
add_wg_access = true
}
resource "grid_deployment" "d1" {
disks {
name = "disk1"
size = var.size
}
name = local.name
node = var.tfnodeid1
network_name = grid_network.net1.name
vms {
name = "vm1"
flist = "https://hub.grid.tf/tf-official-vms/ubuntu-22.04.flist"
cpu = var.cpu
mounts {
disk_name = "disk1"
mount_point = "/disk1"
}
memory = var.memory
entrypoint = "/sbin/zinit init"
env_vars = {
SSH_KEY = var.SSH_KEY
}
publicip = true
planetary = true
}
}
resource "grid_deployment" "d2" {
disks {
name = "disk2"
size = var.size
}
name = local.name
node = var.tfnodeid2
network_name = grid_network.net1.name
vms {
name = "vm2"
flist = "https://hub.grid.tf/tf-official-vms/ubuntu-22.04.flist"
cpu = var.cpu
mounts {
disk_name = "disk2"
mount_point = "/disk2"
}
memory = var.memory
entrypoint = "/sbin/zinit init"
env_vars = {
SSH_KEY = var.SSH_KEY
}
publicip = true
planetary = true
}
}
output "wg_config" {
value = grid_network.net1.access_wg_config
}
output "node1_zmachine1_ip" {
value = grid_deployment.d1.vms[0].ip
}
output "node1_zmachine2_ip" {
value = grid_deployment.d2.vms[0].ip
}
output "planetary_ip1" {
value = grid_deployment.d1.vms[0].planetary_ip
}
output "planetary_ip2" {
value = grid_deployment.d2.vms[0].planetary_ip
}
output "ipv4_vm1" {
value = grid_deployment.d1.vms[0].computedip
}
output "ipv4_vm2" {
value = grid_deployment.d2.vms[0].computedip
}
In this file, we name the first VM as vm1
and the second VM as vm2
. For ease of communication, in this guide we call vm1
as the master VM and vm2
as the worker VM.
In this guide, the virtual IP for vm1
is 10.1.3.2 and the virtual IP for vm2
is 10.1.4.2. This might be different during your own deployment. If so, change the codes in this guide accordingly.
-
Create the
credentials.auto.tfvars
file:-
nano credentials.auto.tfvars
-
-
Copy the
credentials.auto.tfvars
content and save the file.-
mnemonics = "..." SSH_KEY = "..." tfnodeid1 = "..." tfnodeid2 = "..." size = "50" cpu = "1" memory = "2048"
-
Make sure to add your own seed phrase and SSH public key. You will also need to specify the two node IDs of the servers used. Simply replace the three dots by the content. Obviously, you can decide to increase or modify the quantity in the variables size
, cpu
and memory
.
Deploy the 3Nodes with Terraform
We now deploy the VPN with Terraform. Make sure that you are in the correct folder terraform/deployment-synced-db
with the main and variables files.
-
Initialize Terraform:
-
terraform init
-
-
Apply Terraform to deploy the VPN:
-
terraform apply
-
After deployments, take note of the 3Nodes' IPv4 address. You will need those addresses to SSH into the 3Nodes.
Note that, at any moment, if you want to see the information on your Terraform deployments, write the following:
-
terraform show
SSH into the 3Nodes
- To SSH into the 3Nodes, write the following while making sure to set the proper IP address for each VM:
-
ssh root@3node_IPv4_Address
-
Preparing the VMs for the Deployment
- Update and upgrade the system
-
apt update && sudo apt upgrade -y && sudo apt-get install apache2 -y
-
- After download, you might need to reboot the system for changes to be fully taken into account
-
reboot
-
- Reconnect to the VMs
Test the Wireguard Connection
We now want to ping the VMs using Wireguard. This will ensure the connection is properly established.
First, we set Wireguard with the Terraform output.
-
On your local computer, take the Terraform's
wg_config
output and create awg.conf
file in the directory/usr/local/etc/wireguard/wg.conf
.-
nano /usr/local/etc/wireguard/wg.conf
-
-
Paste the content provided by the Terraform deployment. You can use
terraform show
to see the Terraform output. The WireGuard output stands in betweenEOT
. -
Start the WireGuard on your local computer:
-
wg-quick up wg
-
-
To stop the wireguard service:
-
wg-quick down wg
-
Note: If it doesn't work and you already did a WireGuard connection with the same file from Terraform (from a previous deployment perhaps), do
wg-quick down wg
, thenwg-quick up wg
. This should set everything properly.
- As a test, you can ping the virtual IP addresses of both VMs to make sure the Wireguard connection is correct:
-
ping 10.1.3.2
-
ping 10.1.4.2
-
If you correctly receive the packets for the two VMs, you know that the VPN is properly set.
For more information on WireGuard, notably in relation to Windows, please read this documentation.
Configure the MariaDB Database
Download MariaDB and Configure the Database
-
Download the MariaDB server and client on both the master VM and the worker VM
-
apt install mariadb-server mariadb-client -y
-
-
Configure the MariaDB database
-
nano /etc/mysql/mariadb.conf.d/50-server.cnf
- Do the following changes
- Add
#
in front ofbind-address = 127.0.0.1
- Remove
#
in front of the following lines and replaceX
by1
for the master VM and by2
for the worker VM#server-id = X #log_bin = /var/log/mysql/mysql-bin.log
- Below the lines shown above add the following line:
binlog_do_db = tfdatabase
- Add
- Do the following changes
-
-
Restart MariaDB
-
systemctl restart mysql
-
-
Launch Mariadb
-
mysql
-
Create User with Replication Grant
- Do the following on both the master and the worker
-
CREATE USER 'repuser'@'%' IDENTIFIED BY 'password'; GRANT REPLICATION SLAVE ON *.* TO 'repuser'@'%' ; FLUSH PRIVILEGES; show master status\G;
-
Verify the Access of the User
- Verify the access of repuser user
SELECT host FROM mysql.user WHERE User = 'repuser';
- You want to see
%
in Host
- You want to see
Set the VMs to accept the MariaDB Connection
TF Template Worker Server Data
- Write the following in the Worker VM
-
CHANGE MASTER TO MASTER_HOST='10.1.3.2', MASTER_USER='repuser', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=328;
-
start slave;
-
show slave status\G;
-
TF Template Master Server Data
- Write the following in the Master VM
-
CHANGE MASTER TO MASTER_HOST='10.1.4.2', MASTER_USER='repuser', MASTER_PASSWORD='password', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=328;
-
start slave;
-
show slave status\G;
-
Set the MariaDB Databases on Both 3Nodes
We now set the MariaDB database. You should choose your own username and password. The password should be the same for the master and worker VMs.
-
On the master VM, write:
CREATE DATABASE tfdatabase; CREATE USER 'ncuser'@'%'; GRANT ALL PRIVILEGES ON tfdatabase.* TO ncuser@'%' IDENTIFIED BY 'password1234'; FLUSH PRIVILEGES;
-
On the worker VM, write:
CREATE USER 'ncuser'@'%'; GRANT ALL PRIVILEGES ON tfdatabase.* TO ncuser@'%' IDENTIFIED BY 'password1234'; FLUSH PRIVILEGES;
-
To see a database, write the following:
show databases;
-
To see users on MariaDB:
select user from mysql.user;
-
To exit MariaDB:
exit;
Install and Set GlusterFS
We will now install and set GlusterFS, a free and open-source software scalable network filesystem.
-
Install GlusterFS on both the master and worker VMs
-
add-apt-repository ppa:gluster/glusterfs-7 -y && apt install glusterfs-server -y
-
-
Start the GlusterFS service on both VMs
-
systemctl start glusterd.service && systemctl enable glusterd.service
-
-
Set the master to worker probe IP on the master VM:
-
gluster peer probe 10.1.4.2
-
-
See the peer status on the worker VM:
-
gluster peer status
-
-
Set the master and worker IP address on the master VM:
-
gluster volume create vol1 replica 2 10.1.3.2:/gluster-storage 10.1.4.2:/gluster-storage force
-
-
Start Gluster:
-
gluster volume start vol1
-
-
Check the status on the worker VM:
-
gluster volume status
-
-
Mount the server with the master IP on the master VM:
-
mount -t glusterfs 10.1.3.2:/vol1 /var/www
-
-
See if the mount is there on the master VM:
-
df -h
-
-
Mount the Server with the worker IP on the worker VM:
-
mount -t glusterfs 10.1.4.2:/vol1 /var/www
-
-
See if the mount is there on the worker VM:
-
df -h
-
We now update the mount with the filse fstab on both master and worker.
- To prevent the mount from being aborted if the server reboot, write the following on both servers:
-
nano /etc/fstab
-
Add the following line in the
fstab
file to set the master VM with the master virtual IP (here it is 10.1.3.2):-
10.1.3.2:/vol1 /var/www glusterfs defaults,_netdev 0 0
-
-
Add the following line in the
fstab
file to set the worker VM with the worker virtual IP (here it is 10.1.4.2):-
10.1.4.2:/vol1 /var/www glusterfs defaults,_netdev 0 0
-
-
The databases of both VMs are accessible in /var/www
. This means that any change in either folder /var/www
of each VM will be reflected in the same folder of the other VM. In order words, the databases are now synced in real-time.
Conclusion
You now have two VMs syncing their MariaDB databases. This can be very useful for a plethora of projects requiring redundancy in storage.
You should now have a basic understanding of the Threefold Grid, the ThreeFold Explorer, Wireguard, Terraform, MariaDB and GlusterFS.
As always, if you have any questions, you can ask the ThreeFold community for help on the ThreeFold Forum or on the ThreeFold Grid Tester Community on Telegram.