Azure Cloud Automation Solution

An infrastructure automation project to deploy a n-tier applications on Azure using Terraform and Ansible. It includes creating VMs, networking, and security groups.
Terraform and Ansible Integration: A Comprehensive Cloud Automation Project on Azure
In today's cloud-driven world, automation is key to maintaining consistent, reliable, and scalable infrastructure. This blog post explores a comprehensive project that demonstrates the powerful combination of Terraform for infrastructure provisioning and Ansible for configuration management on Microsoft Azure.
This project showcases an end-to-end deployment solution that creates a multi-tier infrastructure with both Linux and Windows virtual machines, networking components, storage solutions, and databases - all managed through code.
Project Overview
The project implements Infrastructure as Code (IaC) principles to deploy and configure Azure resources. The deployment includes:
- Linux and Windows virtual machines in availability sets
- Virtual network with subnets and security rules
- Load balancer for the Linux VMs
- Data disks attached to VMs
- Storage accounts and containers
- Log analytics workspace
- Recovery services vault
- PostgreSQL database
After deployment, Ansible takes over to configure the Linux VMs, performing tasks such as:
- Partitioning and mounting data disks
- Creating and configuring users
- Setting up system profiles
- Installing and configuring web servers
Architecture Breakdown
Resource Organization
The project uses a modular approach with Terraform, breaking down components into reusable modules:
Terraform-Ansible2/ ├── modules/ │ ├── rgroup/ # Resource group management │ ├── network/ # Virtual network, subnets, NSGs │ ├── common/ # Storage, log analytics, recovery vault │ ├── vmlinux/ # Linux VM deployment │ ├── vmwindows/ # Windows VM deployment │ ├── datadisk/ # Disk management │ ├── loadbalancer/ # Load balancer configuration │ └── database/ # PostgreSQL database deployment ├── ansible/ │ ├── inventory/ # Generated host information │ ├── playbook/ # Ansible playbooks │ └── roles/ # Configuration roles └── terraform/ # Main Terraform configuration
Terraform Configuration
Let's examine the core Terraform configuration in more detail:
Main Configuration
The main.tf file orchestrates the entire deployment by calling each module in sequence:
# Resource Group Module module "resource_group" { source = "./modules/rgroup" rgroup_name = "9079-Assignment2-RG" location = local.location tags = local.tags } # Network Module module "network" { source = "./modules/network" rgroup_name = module.resource_group.rgroup_name location = module.resource_group.location vnet_name = "vnet-production" vnet_space = "10.0.0.0/16" subnet_name = "subnet-1" subnet_space = "10.0.1.0/24" nsg_name = "nsg-1" tags = module.resource_group.tags } # Additional modules for common services, VMs, disks, load balancer, database
Variables and Customization
The project uses variables to make the infrastructure configurable:
locals { tags = { Name = "Automation Project – Assignment 2" GroupMembers = "Paramvir.Singh" ExpirationDate = "2023-06-30" Environment = "Lab" } prefix_name = "Paramvir9079" prefix_id = "9079" location = "eastus" } variable "vmlinux" { type = map(any) default = { name = "linux-9079-vm" avset = "linux-avset" size = "Standard_B1ms" count = 2 } } variable "vmwindows" { type = map(any) default = { name = "win-9079" avset_name = "win-avset" size = "Standard_B1ms" } }
Network Configuration
The network module sets up a virtual network, subnet, and network security group with proper rules:
resource "azurerm_network_security_group" "nsg-1" { name = var.nsg_name location = var.location resource_group_name = var.rgroup_name security_rule { name = "AllowSSH" priority = 100 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "22" source_address_prefix = "*" destination_address_prefix = "*" } tags = var.tags }
Virtual Machine Deployment
The Linux virtual machines are deployed with appropriate network configurations and availability sets:
resource "azurerm_linux_virtual_machine" "linux-vm" { count = var.nb_count name = "${var.vmlinux.name}-vm-${format("%1d", count.index + 1)}" resource_group_name = var.rgroup_name location = var.location size = var.size admin_username = var.admin_username computer_name = "${var.vmlinux.name}-cn-${format("%1d", count.index + 1)}" availability_set_id = azurerm_availability_set.linux-avs.id # Additional configurations... }
Terraform to Ansible Integration
A key aspect of this project is the seamless integration between Terraform and Ansible. After Terraform deploys the infrastructure, a script named create_hosts.sh extracts the IP addresses of the deployed Linux VMs and generates an Ansible inventory file:
#!/bin/bash # Get the ansible host IP addresses using terraform output command ansible_host1=$(terraform output | grep Linux_public_ip_addresses1 | awk -F= '{gsub(/"/, "", $2); print $2}' | sed 's/^[[:space:]]*//') ansible_host2=$(terraform output | grep Linux_public_ip_addresses2 | awk -F= '{gsub(/"/, "", $2); print $2}' | sed 's/^[[:space:]]*//') # Create the hosts file cat </home/ubuntu/automation/Terraform-Ansible2/ansible/inventory/hosts [linux] linux-9079-vm1 ansible_host=${ansible_host1} ansible_user=Paramvir9079 linux-9079-vm2 ansible_host=${ansible_host2} ansible_user=Paramvir9079 [os:children] linux [linux:vars] ansible_connection=ssh EOF # Run the Ansible playbook ansible-playbook /home/ubuntu/automation/Terraform-Ansible2/ansible/playbook/groupX-playbook.yaml
This script is triggered by a Terraform null_resource:
resource "null_resource" "ansible-configuration" { depends_on = [azurerm_linux_virtual_machine.linux-vm] provisioner "local-exec" { working_dir = "${var.ansible_path}" interpreter = ["wsl", "-Command"] command = "./terraform/create_hosts.sh" } }
Ansible Configuration
Playbook Structure
The main playbook (groupX-playbook.yaml) orchestrates the configuration by including multiple roles:
- name: Group-X hosts: linux become: true roles: - datadisk - system_profile - users - webserver
Ansible Roles
The Ansible component of this project is organized into several roles:
- datadisk: Partitions and mounts the attached data disks to the virtual machines
- system_profile: Configures system settings and environment variables
- users: Creates and configures user accounts on the Linux VMs
- webserver: Installs and configures an Apache web server
Key Features and Best Practices
This project demonstrates several important DevOps and cloud automation practices:
1. Modular Design
The Terraform configuration is split into reusable modules, each responsible for a specific aspect of the infrastructure. This makes the code more maintainable, reusable, and easier to understand.
2. Infrastructure as Code
All infrastructure is defined in code, enabling version control, peer review, and consistent deployments.
3. Resource Tagging
All resources are tagged appropriately, which is crucial for resource organization, cost tracking, and management:
tags = { Name = "Automation Project – Assignment 2" GroupMembers = "Paramvir.Singh" ExpirationDate = "2023-06-30" Environment = "Lab" }
4. Configuration Management
Instead of manually configuring servers after deployment, Ansible automates this process, ensuring consistency across environments.
5. Orchestration
The project demonstrates how to orchestrate multiple tools (Terraform and Ansible) to work together seamlessly.
Deployment Process
Here's how you would deploy this infrastructure:
- Initialize Terraform:
terraform init
- Plan the Deployment:
terraform plan
- Apply the Configuration:
terraform apply -auto-approve
- Verify the Deployment:
terraform output
The Ansible playbooks run automatically after Terraform completes, but they can also be run manually:
ansible-playbook -i ansible/inventory/hosts ansible/playbook/groupX-playbook.yaml
Conclusion
This project showcases a comprehensive approach to cloud automation using two industry-standard tools: Terraform and Ansible. By using Infrastructure as Code principles, it enables:
- Consistent and repeatable deployments
- Version-controlled infrastructure
- Reduced manual configuration errors
- Automated configuration management
- Scalable and maintainable architecture
The combination of Terraform for infrastructure provisioning and Ansible for configuration management creates a powerful automation pipeline that can be adapted for various production scenarios.
This approach is particularly valuable for organizations looking to standardize their deployment processes, implement robust DevOps practices, and ensure consistent configurations across development, testing, and production environments.
By studying and adapting this project's structure and techniques, you can build your own automated cloud infrastructure deployments that are scalable, reliable, and maintainable.