A comprehensive infrastructure-as-code (IaC) project for configuring an Azure Virtual Machine with multiple public IPv4 addresses, implementing policy-based routing (PBR), and verifying multi-IP functionality through automated testing.
This project demonstrates how to:
- Deploy Infrastructure with Terraform: Create a complete Azure environment with configurable multi-IP support
- Automate VM Configuration with Ansible: Set up policy-based routing for multi-IP traffic management
- Verify Functionality: Use Bash scripts to test that all public IPs are functional
- ✅ Configurable number of secondary public IPs (via
secondary_ip_countvariable) - ✅ Standard SKU static public IPs in East US region
- ✅ Policy-based routing for traffic selection per IP
- ✅ Automated VM configuration and validation
- ✅ Comprehensive verification and testing capabilities
- ✅ Full infrastructure cleanup automation
Task Requirement: IaC script to provision resources in East US region.
Current Implementation: Deployed to West US region due to Pluralsight Azure Sandbox limitations (available region).
To change the deployment region to East US, update the region variable in terraform/terraform.tfvars:
region = "eastus" # Change from "westus" to "eastus"All resources (VM, VNet, NSG, Public IPs, etc.) will be deployed to the specified region.
# 1. Clone and navigate
git clone <repository-url>
cd azure-multi-ip-lab
chmod +x scripts/*.sh
# 2. Authenticate with Azure
az login
# 3. Deploy infrastructure + configuration (includes automatic verification)
./scripts/deploy.sh
# 4. Manual verification (optional, if automatic verification was skipped)
ssh azureuser@<primary_public_ip>
sudo /tmp/verify-multi-ip.sh
# 5. Cleanup resources
./scripts/cleanup.sh --forceThe deployment script automatically runs multi-IP verification after infrastructure and Ansible configuration are complete. The verification includes:
- IP Configuration Check: Verifies all 6 private IPs are configured on eth0
- Policy-Based Routing (PBR) Check: Confirms custom routing tables and IP rules exist
- Outbound IP Verification: Tests that each private IP routes through its corresponding public IP
- Summary Report: Shows pass/fail for all configured IPs
If automatic verification is unavailable or you want to run it manually:
ssh azureuser@<primary_public_ip>
sudo /tmp/verify-multi-ip.sh
# Or from your local machine:
ssh -o StrictHostKeyChecking=no azureuser@<primary_public_ip> 'bash -s' < scripts/verify-multi-ip.sh- Azure CLI:
az --version - Terraform 1.0+:
terraform version - Ansible 2.9+:
ansible --version - SSH Key Pair:
~/.ssh/id_rsa
az login
az account set --subscription "YOUR_SUBSCRIPTION_ID"ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""azure-multi-ip-lab/
├── terraform/ # Infrastructure as Code
│ ├── main.tf # Resource definitions
│ ├── variables.tf # Input variables
│ ├── backend.tf # State management
│ └── terraform.tfvars # Configuration values
├── ansible/ # VM Configuration
│ ├── playbook.yml # Networking setup
│ ├── ansible.cfg # Ansible config
│ └── inventory.yml # Host inventory
├── scripts/ # Automation
│ ├── deploy.sh # Full deployment
│ ├── verify-multi-ip.sh # Verification
│ └── cleanup.sh # Resource cleanup
└── README.md # This file
Customize deployment in terraform/terraform.tfvars:
secondary_ip_count = 5 # Number of secondary public IPs
vm_name = "vm-multi-ip" # VM name
vm_size = "Standard_D2s_v5" # VM size
location = "East US" # Azure regionThe automated deployment script handles everything end-to-end:
# Full deployment with infrastructure + Ansible + verification
./scripts/deploy.sh
# Infrastructure only (skip Ansible networking)
./scripts/deploy.sh --skip-ansible
# With debug output
DEBUG=true ./scripts/deploy.shDeployment Steps:
- Terraform initialization
- Infrastructure creation (vNet, VM, NICs, public IPs)
- VM readiness check
- Ansible inventory configuration
- Network setup via Ansible playbook
- Automatic multi-IP verification
Estimated time: 10-15 minutes for full deployment including verification.
This script:
- Initializes Terraform
- Plans and applies infrastructure
- Waits for VM readiness
- Configures Ansible inventory
- Runs networking playbook
cd terraform
terraform init
terraform plan -out=tfplan
terraform apply tfplan
cd ..
# Get deployment information
PRIMARY_IP=$(cd terraform && terraform output -raw primary_public_ip && cd ..)
# Configure and run Ansible
# Edit ansible/inventory.yml with PRIMARY_IP
cd ansible
ansible-playbook -i inventory.yml playbook.yml
cd ..After deployment completes:
# Connect to VM
ssh azureuser@<primary_public_ip>
# Run comprehensive verification
sudo /tmp/verify-multi-ip.sh
# Or verify manually
ip addr show eth0 # View all IPs
ip rule show # View PBR rules
curl -I --interface 10.0.1.10 https://ifconfig.co # Test IPThe Ansible playbook configures:
- IP Aliases: Secondary IPs on eth0 (10.0.1.100-104)
- Routing Tables: Custom tables 100-245 for PBR
- IP Rules: Route traffic per source IP
- Persistence: systemd service maintains config across reboots
# Interactive cleanup
./scripts/cleanup.sh
# Force cleanup (no prompts)
./scripts/cleanup.sh --force
# Preview changes
./scripts/cleanup.sh --dry-runAzure Resource Group
├── VNet (10.0.0.0/16)
│ └── Subnet (10.0.1.0/24)
│ ├── Primary NIC (eth0)
│ │ ├── Primary IP: 10.0.1.10 → Public IP
│ │ └── Secondary IPs: 10.0.1.100-104 → Secondary Public IPs
│ └── NSG (SSH allowed, all outbound)
└── Public IPs (Standard SKU, Static)
├── Primary: 1x
└── Secondary: 5x
chmod 600 ~/.ssh/id_rsa
az login
ssh -i ~/.ssh/id_rsa azureuser@<primary_public_ip># Verify SSH works first
ssh azureuser@<primary_public_ip> echo OK
# Run with verbose output
ansible-playbook -i ansible/inventory.yml ansible/playbook.yml -vvv# Check service status
systemctl status configure-multi-ip.service
# Manually add IPs
sudo ip addr add 10.0.1.100/24 dev eth0| Resource | Cost/Month |
|---|---|
| VM (Standard_D2s_v5) | ~$120 |
| Public IPs (6x Standard) | ~$30 |
| Storage | ~$4 |
| Total | ~$154 |
Cost Optimization:
- Delete immediately after testing (use cleanup script)
- Use smaller VM: Standard_B2s (~$40/mo)
- Deallocate VM when not in use
- Monitor via Azure Cost Management
Educational and testing purposes.
Version: 1.0 | Updated: December 2025