Building an HA Virtual Infrastructure
This tutorial will use VirtualBox and Vagrant to create redundant components for an HA Infrastructure. This includes using HAProxy as a load balancer, Apache webservers, and a MySQL master-master database cluster. The load-balancer will be configured with round robin, a scheduling algorithm that distributes work evenly. The webservers will be identical Rocky Linux 8 servers running the Apache webserver. The database will be two MySQL servers in a master-master configuration. Also known as “mirror” because both servers update the data in real-time to ensure that both servers have the latest data. All of this can be done on Mac, Windows and Linux.
Install VirtualBox first and reboot after installation. Then install Vagrant and reboot. Once rebooted, open a shell of your choice. I am using Powershell. Type 'vagrant' on the command line to verify it is installed correctly. Make sure VirtualBox is up and running. Create a directory C:\vagrant. In Powershell change into the vagrant directory and type
vagrant init
vagrant plugin install vagrant-vbguest
Install the extension pack in VirtualBox. Support for VirtualBox RDP, disk encryption, NVMe and PXE boot for Intel network cards. For Linux servers this may require recompiling the kernel. While this is done with automation it sometimes creates an error. For this tutorial we will disable these automatic updates.
In this infrastructure example we will use Ubuntu for the HAProxy load balancer, Rocky Linux 8 for the Apache web servers, and Ubuntu for the MySQL instances. Port forwarding will be configured for each server. We will use the following IP addresses and ports:
Server | IP | VBox | Local ssh | Local web |
---|---|---|---|---|
Load Balancer | 10.0.2.200 | yunsheng/haproxybase | 20022 | 20080 |
Web Server 1 | 10.0.2.201 | geerlingguy/rockylinux8 | 20122 | 20180 |
Web Server 2 | 10.0.2.202 | geerlingguy/rockylinux8 | 20222 | 20280 |
Database1 | 10.0.2.203 | dperezc01/mysqltrusty64 | 20322 | 20380 |
Database 2 | 10.0.2.204 | dperezc01/mysqltrusty64 | 20422 | 20480 |
We will edit the file called Vagrantfile in C:\vagrant.
Vagrant.configure("2") do |config|
if Vagrant.has_plugin?("vagrant-vbguest")
config.vbguest.auto_update = false
end
config.vm.define "lb1" do |lb1|
lb1.vm.box = "yunsheng/haproxybase"
lb1.vm.hostname = 'lb1'
lb1.vm.box_version = "1.0.0"
lb1.vm.network :private_network, ip: "10.0.2.200"
lb1.vm.network :forwarded_port, guest: 22, host: 20022, id: "ssh"
lb1.vm.network :forwarded_port, guest: 80, host: 20080, id: "http"
lb1.vm.provider :virtualbox do |v|
v.customize ["modifyvm", :id, "--memory", 512]
v.customize ["modifyvm", :id, "--name", "lb1"]
v.customize ["modifyvm", :id, "--uartmode1", "disconnected" ]
end
end
config.vm.define "web1" do |web1|
web1.vm.box = "geerlingguy/rockylinux8"
web1.vm.hostname = 'web1'
web1.vm.box_url = "geerlingguy/rockylinux8"
web1.vm.network :private_network, ip: "10.0.2.201"
web1.vm.network :forwarded_port, guest: 22, host: 20122, id: "ssh"
web1.vm.network :forwarded_port, guest: 80, host: 20180, id: "http"
web1.vm.provider :virtualbox do |v|
v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
v.customize ["modifyvm", :id, "--memory", 512]
v.customize ["modifyvm", :id, "--name", "web1"]
end
end
config.vm.define "web2" do |web2|
web2.vm.box = "geerlingguy/rockylinux8"
web2.vm.hostname = 'web2'
web2.vm.box_url = "geerlingguy/rockylinux8"
web2.vm.network :private_network, ip: "10.0.2.202"
web2.vm.network :forwarded_port, guest: 22, host: 20222, id: "ssh"
web2.vm.network :forwarded_port, guest: 80, host: 20280, id: "http"
web2.vm.provider :virtualbox do |v|
v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
v.customize ["modifyvm", :id, "--memory", 512]
v.customize ["modifyvm", :id, "--name", "web2"]
end
end
config.vm.define "db1" do |db1|
db1.vm.box = "dperezc01/mysqltrusty64"
db1.vm.hostname = 'db1'
db1.vm.box_url = "dperezc01/mysqltrusty64"
db1.vm.network :private_network, ip: "10.0.2.203"
db1.vm.network :forwarded_port, guest: 22, host: 20322, id: "ssh"
db1.vm.network :forwarded_port, guest: 80, host: 20380, id: "http"
db1.vm.provider :virtualbox do |v|
v.customize ["modifyvm", :id, "--memory", 512]
v.customize ["modifyvm", :id, "--name", "db1"]
db1.vm.network "forwarded_port", guest: 3306, host: 3307, host_ip: "127.0.0.1"
end
end
config.vm.define "db2" do |db2|
db2.vm.box = "dperezc01/mysqltrusty64"
db2.vm.hostname = 'db2'
db2.vm.box_url = "dperezc01/mysqltrusty64"
db2.vm.network :private_network, ip: "10.0.2.204"
db2.vm.network :forwarded_port, guest: 22, host: 20422, id: "ssh"
db2.vm.network :forwarded_port, guest: 80, host: 20480, id: "http"
# MySQL server
db2.vm.network "forwarded_port", guest: 3306, host: 3308, host_ip: "127.0.0.1"
db2.vm.provider :virtualbox do |v|
v.customize ["modifyvm", :id, "--memory", 512]
v.customize ["modifyvm", :id, "--name", "db2"]
end
end
end
Once saved, run the following command
vagrant up
Switch to VirtualBox. You should see the new virtual machines coming up and running. Open and log in to the new virtual machines with user name 'vagrant' and password 'vagrant'. In Powershell type
PS C:\vagrant> vagrant ssh web1
Last login: Mon Jan 1 01:18:53 2024
[vagrant@web1 ~]$
This is just the beginning of using this combination of technologies. The combination of Vagrant and VirtualBox should save you lots of time. Spinning up this infrastructure with Vagrant takes only a few minutes because of the automation and other human task elimination. This can equate to hours of productivity gains per day if you do a lot of prototyping. This gets even more impressive when you layer in components like Ansible and Kubernetes. You can find Vagrant Boxes on the Vagrant Cloud.
Server | IP | Web page |
---|---|---|
Load Balancer | 10.0.2.200 | 20080 |
Web Server 1 | 10.0.2.201 | 20180 |
Web Server 2 | 10.0.2.202 | 20280 |
Database1 | 10.0.2.203 | 20380 |
Database 2 | 10.0.2.204 | 20480 |
To delete the servers run the following in Powershell. Vagrant normally asks for Y/N verification for each server. We will use -f to disable this.
PS C:\vagrant> vagrant destroy -f
Helpful links
https://developer.hashicorp.com/vagrant/docs
https://www.virtualbox.org/wiki/Documentation
https://www.activecountermeasures.com/port-forwarding-with-virtualbox/