5 – Azure VNet Peering: A Real-World Terraform Mini Project to Build a Secure Cloud Network

In this mini project, I implemented Azure VNet peering using Terraform, but instead of applying everything at once, I deliberately broke the setup into small, testable steps.
This approach makes it much easier to understand what’s happening, catch mistakes early, and build real confidence with Terraform and Azure networking.

Below is the exact flow I followed — and you can follow the same steps as a beginner.

Table of Contents

  1. Step 1: Create the Resource Group, Virtual Networks, and Subnets
  2. Step 2: Create VM1 in Subnet 1 (via a NIC)
  3. Step 3: Create VM2 in Subnet 2
  4. Step 4: Test Connectivity Before Peering (Expected to Fail)
  5. Step 5: Add VNet Peering (Both Directions)
  6. Step 6: Test Connectivity After Peering (Expected to Work)
  7. Key Takeaways for Beginners
  8. Why This Step-by-Step Approach Matters

Step 1: Create the Resource Group, Virtual Networks, and Subnets

We start by creating the network foundation:

  • One resource group
  • Two separate virtual networks
  • One subnet inside each virtual network

At this stage, there is no connectivity between the networks.

What we created

  • vnet1 → address space 10.0.0.0/16
  • vnet2 → address space 10.1.0.0/16
  • One /24 subnet in each VNet
resource "azurerm_resource_group" "rg" {
  name     = "rgminipro76876"
  location = "Central US"
}

resource "azurerm_virtual_network" "vnet1" {
  name                = "vnet1minipro8768"
  location            = azurerm_resource_group.rg.location
  address_space       = ["10.0.0.0/16"]
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "sn1" {
  name                 = "subnet1minipro878"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet1.name
  address_prefixes     = ["10.0.0.0/24"]
}

resource "azurerm_virtual_network" "vnet2" {
  name                = "vnet2minipro8768"
  location            = azurerm_resource_group.rg.location
  address_space       = ["10.1.0.0/16"]
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_subnet" "sn2" {
  name                 = "subnet2minipro878"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet2.name
  address_prefixes     = ["10.1.0.0/24"]
}

How to verify

  • Run terraform apply
  • Open Azure Portal
  • Confirm:
    • Both VNets exist
    • Each VNet has its own subnet
    • Address spaces do not overlap

At this point, nothing can talk to anything else yet — and that’s expected.


Step 2: Create VM1 in Subnet 1 (via a NIC)

In Azure, VMs don’t live directly inside subnets.
Instead, a Network Interface (NIC) is placed inside a subnet, and the VM attaches to that NIC.

Here, we:

  • Create a NIC attached to subnet1
  • Create a VM that uses that NIC

VM1 and NIC1

resource "azurerm_network_interface" "nic1" {
  name                = "nic1minipro8789"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "ipconfignic1minipro989"
    subnet_id                     = azurerm_subnet.sn1.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_virtual_machine" "vm1" {
  name                = "vm1minipro98908"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  network_interface_ids = [
    azurerm_network_interface.nic1.id
  ]
  vm_size = "Standard_D2s_v3"

  delete_os_disk_on_termination = true

  storage_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }

  storage_os_disk {
    name              = "storageosdisk1"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  os_profile {
    computer_name  = "peer1vm"
    admin_username = "testadmin"
    admin_password = "Password1234!"
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }
}

How to verify

  • Run terraform apply
  • In Azure Portal:
    • VM1 exists
    • NIC is attached
    • NIC is in subnet1
    • VM has no public IP

Step 3: Create VM2 in Subnet 2

Now we repeat the same pattern for the second network:

  • NIC attached to subnet2
  • VM attached to that NIC
resource "azurerm_network_interface" "nic2" {
  name                = "nic2minipro8789"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "ipconfignic2minipro989"
    subnet_id                     = azurerm_subnet.sn2.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_virtual_machine" "vm2" {
  name                = "vm2minipro98908"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  network_interface_ids = [
    azurerm_network_interface.nic2.id
  ]
  vm_size = "Standard_D2s_v3"

  delete_os_disk_on_termination = true

  storage_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }

  storage_os_disk {
    name              = "storageosdisk2"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  os_profile {
    computer_name  = "peer2vm"
    admin_username = "testadmin"
    admin_password = "Password1234!"
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }
}

How to verify

  • Run terraform apply
  • Confirm:
    • VM2 exists
    • NIC2 is attached
    • NIC2 belongs to subnet2
    • VM2 also has no public IP

Step 4: Test Connectivity Before Peering (Expected to Fail)

Now we test whether the two VMs can communicate without peering.

Because:

  • They are in different VNets
  • There is no peering
  • No public IPs

They should not be able to communicate.

How I tested

Using Azure Run Command (no SSH or Bastion needed):

  • VM1 → Operations → Run command → RunShellScript
  • Command:
ping -c 4 10.1.0.x

Result

4 packets transmitted, 0 received, 100% packet loss

✅ This is the correct and expected behavior


Step 5: Add VNet Peering (Both Directions)

VNet peering in Azure is not automatic.
You must create two peering connections:

  • VNet1 → VNet2
  • VNet2 → VNet1
resource "azurerm_virtual_network_peering" "peer1to2" {
  name                      = "peer1to2minipro455"
  resource_group_name       = azurerm_resource_group.rg.name
  virtual_network_name      = azurerm_virtual_network.vnet1.name
  remote_virtual_network_id = azurerm_virtual_network.vnet2.id
}

resource "azurerm_virtual_network_peering" "peer2to1" {
  name                      = "peer2to1minipro455"
  resource_group_name       = azurerm_resource_group.rg.name
  virtual_network_name      = azurerm_virtual_network.vnet2.name
  remote_virtual_network_id = azurerm_virtual_network.vnet1.id
}

How to verify

  • Run terraform apply
  • Azure Portal → Virtual Networks → Peering
  • Status should show Connected

Step 6: Test Connectivity After Peering (Expected to Work)

Now we repeat the same test as before.

ping -c 4 10.1.0.x

Result

4 packets transmitted, 4 received, 0% packet loss

🎉 Success!

This proves:

  • VNet peering is working
  • Traffic stays on Azure’s private backbone
  • No public IPs are required

Key Takeaways for Beginners

  • VMs communicate via NICs, not directly via subnets
  • VNets are isolated by default
  • Peering must be created in both directions
  • Always test:
    • ❌ Before peering
    • ✅ After peering
  • Applying Terraform in small steps makes debugging much easier

Why This Step-by-Step Approach Matters

Instead of running one giant terraform apply and hoping for the best, this method:

  • Builds real understanding
  • Makes Azure networking concepts visual
  • Helps you debug like a real DevOps engineer

If you can do this project, you already understand:

  • VNets
  • Subnets
  • NICs
  • VM placement
  • VNet peering
  • Real-world network isolation

That’s solid progress 👏

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

TechMilestoneHub

Build Skills, Unlock Milestones

This is a test – edited from front page