Azure Cloud Automation Solution

Azure Cloud Automation Solution
Technologies: Terraform, Ansible, Azure, Linux, Windows, Bash

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:

  1. datadisk: Partitions and mounts the attached data disks to the virtual machines
  2. system_profile: Configures system settings and environment variables
  3. users: Creates and configures user accounts on the Linux VMs
  4. 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:

  1. Initialize Terraform:
    terraform init
  2. Plan the Deployment:
    terraform plan
  3. Apply the Configuration:
    terraform apply -auto-approve
  4. 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.