Introduction: This is the first chapter of the Scalable, Highly Available, Secure WordPress on Azure series; In here I am going to describe the previous approach, its pitfalls and the new target architecture that we are trying to build.
Previous Architecture
Previously, we had created a WordPress® blog site using the LAMP stack and had it up and running in minutes. All the software was deployed on one Linux machine and external connectivity was established using the Azure DNS Zone and a static public IP address component. It was and is a very simplistic approach to get the WordPress® web site up and running. The architecture looked like the following:
As good as the previous approach is, it suffers from some pitfalls;
- The architecture lacks the high-availability, scalability that is the hall mark of any cloud deployment. It has single point of failures and not much resiliency built in.
- The Azure Web plan – although provisioned, is not used – therefore I am unnecessarily paying for a service that I am not using.
- I was using a bigger machine (B2S) to deliver the complete solution. This VM was prices @ ~ 25£ per month. Including the Azure web plan @ £7£ per month, I am was paying way above what is commercially above to host a reliable WordPress hosting site.
- The aim is to get the hosting cost to be significantly less than what I am paying right now.
New Design
In this second iteration of this exercise, we are going to deploy a highly scalable, robust solution which will leverage the cloud capabilities of scalability, resiliency and that of back-up and restore. We will also be removing the Azure Service Plan and App Services from our final deployment.
Target Architecture
In the target architecture – I’ve separated the previous single instance architecture into a Classique tier-ed server architecture, i.e. front-end servers (Apache web server, WordPress installation) and back-end database server (MySQL database).
The target architecture will increase the availability and reliability of the front-end servers using the Azure Availability Sets capability. Higher availability is also achieved by spreading the incoming request across multiple virtual machines as it will utilize the Azure Load balancer in front of the network interfaces of each VMs. The deployment will be utilising subnets and network security groups (NSGs) to provide secure access. Subnets in Azure are used to control network flow and acts as a security boundary. Back-end database will accept requests only from the front-end sub-net.
Database layer – using MySQL – is still a single instance in our architecture and it can still be a single point of failure. Regular back-up and restore capability of Azure will be utilised to provide a high availability solution – but there is still a possibility that the solution is unavailable for a certain time when the database is being restored. Given the expected load and cost involved, this risk is deemed to be justified.
Let’s start the engines and create the new target architecture. Initially, I’ve removed all the existing components.
If you recall, I bought the domain, ninadkanthi.co.uk from GoDaddy.com® domain registrar and that is my starting point for this v2
Script, Folder structure and execution principles.
All the scripts related to this project are copied under the folder ‘V2‘. The folder contains a master – controller script – install.ps1. This script invokes secondary scripts to create various components under Azure. To uninstall, a similar uninstall.ps1 script is also stored under the same folder. If you want to create all the Azure components in one go, just execute the install.ps1. similarly, to clean the Azure resources, just execute uninstall.ps1 script.
All the scripts make use of common parameters file – parameters.ps1 – which contains all the configuration information for the solution. If you want to change name etc for your deployment, edit this parameters file.
All the scripts include ‘login.ps1‘ script which in turn loads the parameters.ps1 script. This login script file invokes a function ‘Login‘ to connect the current user with the Azure subscription. To avoid unnecessarily asking the user to enter login details every-time a script is run, Login function checks if the previously logged in context is still valid and if it is not, only then ask the current user to provide the credentials.
. "$PSScriptRoot\parameters.ps1"
function Login
{
$needLogin = $true
Try
{
$content = Get-AzContext
if ($content)
{
$needLogin = ([string]::IsNullOrEmpty($content.Account))
}
}
Catch
{
if ($_ -like "*Login-AzAccount to login*")
{
$needLogin = $true
}
else
{
throw
}
}
if ($needLogin)
{
Write-Host -ForegroundColor White "Logging in...";
Login-AzAccount;
# select subscription
Write-Host -ForegroundColor White "Selecting subscription '$SUBSCRIPTION'";
Select-AzSubscription -Subscription $SUBSCRIPTION;
#Create or check for existing resource group
$resourceGroup = Get-AzResourceGroup -Name $RESOURCEGROUP_NAME -ErrorAction SilentlyContinue
if(!$resourceGroup)
{
Write-Host -ForegroundColor Yellow "Resource group '$RESOURCEGROUP_NAME' does not exist. To create a new resource group, please enter a location.";
if(!$LOCATION) {
$LOCATION = Read-Host "LOCATION";
}
Write-Host -ForegroundColor Cyan "Creating resource group '$RESOURCEGROUP_NAME' in location '$LOCATION'";
New-AzResourceGroup -Name $RESOURCEGROUP_NAME -Location $LOCATION
}
else
{
Write-Host -ForegroundColor Green "Using existing resource group '$RESOURCEGROUP_NAME'";
}
}
}
# sign in
Login
Guidelines for development
Wherever possible, Azure portal will not be used to create, modify or delete the components. To deliver robustness, reliability and certainty of the solution, almost of the activities would be done via scripts. Azure portal (https://portal.azure.com ) is to be used to validate the script execution results manually – although a non-error run of the script also implicitly applies success.