Automating Azure Infrastructure for High Availability Web Hosting with Ansible

Networking, Cloud & Automation
6 min readAug 2, 2023

Are you tired of the hassle of setting up the infrastructure for a new website every time you need to run a short-term project, such as a marketing campaign or just for testing? Do you spend too much on resources that are only used for a short period? Look no further, because automation is here to save the day!

By automating the process of setting up the infrastructure and configuring it to host your application, you can save time, reduce errors, and make it cost-effective. The goal is to spin up a platform to host a website with just a click of a button for a one-off campaign or a recurring event.

In this post, we discuss the advantages of automating infrastructure provisioning and configuration through an example to create a platform, which you can customize to suit your needs. Let’s get started!

Target setup

To guarantee the availability of our website, we intend to implement a two-tier software architecture consisting of a few virtual machines (VM) with a load balancer in front of them. The first tier will be the client interface or presentation layer, while the second tier are VMs running the web application and database. For a more scalable deployment, you could consider an N-tier design where we don’t host a web application frontend and backend database on the same machines. For additional information on design options, please refer to Deployment Archetypes for Cloud Applications.

We have chosen Azure as our cloud provider, but if you prefer, you may also run this example on AWS.

Before we proceed with creating the VMs, we need to make the following logical resources available on Azure:

  • A resource group that groups all the project resources.
  • An availability set for VM redundancy and availability.
  • A virtual network for communication between VMs and the internet.
  • A subnet to allocate private IP addresses.
  • A security group to filter network traffic.
  • Public IP addresses.
  • Network interfaces for the VMs and load balancer.

The following is a diagram of the target setup with all the pieces together.

Target setup

Writing a playbook

Different options are available for provisioning and managing cloud resources:

  • One option is to manually navigate through the web console of the cloud provider each time.
  • Another option is to create a template specific to the cloud provider, such as Azure Resource Manager templates or AWS CloudFormation.
  • Or use a domain-specific language such as Azure Bicep or define your AWS cloud infrastructure as code with the AWS Cloud Development Kit (AWS CDK).
  • Alternatively, you can use Ansible or Terraform and ensure that resources are available when needed and removed when not in use.

In this opportunity, we run an Ansible playbook to streamline installing and configuring software in the virtual machines the playbook creates in Azure.

For a similar example in AWS, please refer to the article titled “How to consistently run temporary workloads on AWS and save money”.

Creating cloud resources on Azure

To prevent duplication, we use idempotent Ansible modules when creating Azure resources. We source these modules from the Ansible collection for Azure, specifically designed for Azure.

Idempotency: An operation is idempotent if the result of performing it once is exactly the same as the result of performing it repeatedly without any intervening actions. [Ansible Glossary]

You can access the final playbook in this repository: https://github.com/nleiva/ansible-web-server.

Connecting to Azure

To connect to Azure, the Ansible playbook requires access to your Azure account. In order to authenticate, provide the following variables:

  • Subscription ID: subscription_id (AZURE_SUBSCRIPTION_ID)
  • User/Application ID: client_id (AZURE_CLIENT_ID)
  • User/Application secret: secret (AZURE_SECRET)
  • Tenant: tenant (AZURE_TENANT)

You can get these values from your Azure account by following these steps:

  1. Find your Azure subscription and AD tenant.
  2. Register an application with Azure AD and create a service principal.
  3. Create a new application secret.

Check out these screenshots for reference.

SSH Key pair

The Ansible playbook we execute requires an SSH key pair to authenticate you when connecting to any virtual machine.

Azure adds the public SSH key to the ~/.ssh/authorized_keys file in the instances it creates, so Ansible can use the SSH private key to access and configure these instances.

You can pass the location of these files via the ssh_pubkey and ssh_private_key variables. The default locations are ~/.ssh/id_rsa.pub and ~/.ssh/id_rsa, respectively.

Launching the environment

Ansible automates all tasks through a playbook that describes the sequential steps. The playbook in the repository can either:

  • Create resources: Provision any number of virtual machines behind a load balancer.
  • Delete resources: Destroy all resources previously created.

After cloning the repository and exposing your Azure credentials as environment variables, you can run the playbook with: ansible-navigator run main.yml. I encourage you to change this playbook to better suit your needs.

Wait a couple of minutes while the Load Balancer and VM(s) are being provisioned and Ansible install software as required. The output should look like this:

ansible-navigator output when launching the website

You can change the number and operating system of the backend servers via the variable vms. We set the default value in the vms.yml file in the vars folder of the repository. It lists 2 instances; one running centos, and the other one ubuntu. You can override this with a new vms definition as an Extra Variable. These instances are typically identical to one another, but in the example, we run them as a mix of different Linux distributions (just for fun).

vms:
1: centos
2: ubuntu

Accessing the website

To ensure reliability, we use an Azure Load Balancer to distribute traffic evenly among the backend virtual machines. By default, you can access the web site at http://testbed.eastus.cloudapp.azure.com/. You have the option to customize this URL by adjusting the variable prefix, which is initially set to “testbed”. This URL will direct you to one of the backend VMs.

VM1
VM2

Deleting the resources

To delete all resources, run the playbook with the flag delete set to true: ansible-navigator run main.yml -e delete=true.

ansible-navigator output when deleting all resources

Note: I use podman as my container engine (container-engine). You can change to another alternative in the ansible navigator config file.

Playbook details

The roles folder contains tasks for creating or deleting VMs and Load Balancers in both Azure and AWS, as well as installing and configuring software on the instances.

roles folder

For instance, azure_create_vm provides a comprehensive list of tasks for creating the specified number of VMs. This includes all the logical resources explained in the target setup section of this post.

Creating logical resources on Azure

Each task in the playbook utilizes an Ansible module that is specifically designed to handle a particular resource. For instance, here is an example of how to create a virtual network (VNET) on Azure using Ansible. This is the content of the create_vn.yml file.

Creating a VNET on Azure

Conclusions

With just a few concise Ansible tasks, you can consistently provision the cloud infrastructure and configure the software you need to deploy a website in a matter of a couple of minutes.

I hope this example motivates you to create your own version of it to deploy your applications.

--

--

Networking, Cloud & Automation

Proud dad working at Red Hat (CCIE, CCDE). Sharing content I create about: networking, automation, programming, golang, ipv6, and open source software.