Blog

Azure IP Address Management (IPAM) and Why It Matters

Victor de Baare
Arjan van Bekkum

Victor de Baare, Arjan van Bekkum

June 19, 2026
11 minutes

This article is part of the XPRT. Magazine #21


Azure Virtual Network Manager

Before we dive into IP Address Management (IPAM), it is important to know that this is a feature of Azure Virtual Network Manager (AVNM). Azure Virtual Network Manager is a centralized management service that helps to orchestrate and govern network connectivity and security across multiple subscriptions and regions at scale. It enables landing zone teams, such as CCoE and Platform Teams, to create and manage network topologies, including hub-and-spoke and mesh configurations, by automatically establishing peering relationships between virtual networks.

Azure Virtual Network Manager provides security admin rules that act as a global security policy layer, enforcing network security requirements before Network Security Groups are evaluated, allowing for the implementation of mandatory security controls that cannot be overridden at lower levels.

When scoped to a management group, Azure Virtual Network Manager provides visibility and control across the entire Azure estate, enabling consistent networking policies organization-wide. Azure Virtual Network Manager operates regionally, meaning resources are deployed in specific Azure regions to align with the location of managed virtual networks.

Azure IP Address Management

Azure IP Address Management (IPAM) is a feature that allows users to plan, track, and manage private IP address spaces across their cloud infrastructure more effectively instead of relying on a manual spreadsheet, a wiki page, or custom scripts for tracking IP ranges. These manual tracking methods tend to become outdated the moment network changes are made, leading to situations where several teams unknowingly deploy virtual networks with overlapping address spaces. This results in connectivity failures that require extensive troubleshooting and network redesigns.

IPAM introduces a hierarchical pool system in which you can define a root pool representing the entire address space, such as 10.0.0.0/8, which can then be divided into child pools up to 7 levels deep to mirror organizational structures like platform services, production landing zones, and non-production landing zones.

When teams deploy new virtual networks, you need to assign an IPAM pool that assigns non-overlapping CIDR blocks from the appropriate pool based on the requested capacity. When those networks are eventually deleted, their address space automatically returns to the pool for reuse without manual intervention. For IP ranges that exist outside Azure's direct control, such as on-premises networks, Virtual WAN hubs, AWS private clouds, or VMware Cloud subnets, IPAM supports static CIDR reservations that claim these addresses within pools to prevent accidental allocation while maintaining accurate inventory tracking.

IPAM, like Azure Virtual Network Manager, operates regionally, meaning pools created in specific Azure regions can only allocate addresses to resources in those same regions, which aligns with Azure's architectural model and typically requires parallel pool structures across deployment regions.

IPAM integrates with virtual network deployments through the Azure Portal, Terraform or other infrastructure-as-code tools, allowing teams to simply specify how many IP addresses they need rather than manually selecting available CIDR blocks, while providing complete visibility into pool utilization, allocated versus free space, and which resources consume which prefixes through built-in monitoring capabilities.

Setting up Azure Virtual Network Manager for IPAM

For all the examples in the article, we are using Terraform; other infrastructure-as-code tools work the same.

Resource provider registration (management group scope)

Because the Azure Virtual Network Manager is scoped to a management group, the Microsoft.Network provider must be registered at that same management group level. This enables AVNM and IPAM features to be used across all subscriptions within the management group, and it is a common prerequisite that can be overlooked when provisioning via Terraform.

data "azurerm_management_group" "this" {
  name = "MyManagementGroup"
}

resource "azapi_resource_action" "resource_providers" {
  type        = "Microsoft.Management/managementGroups@2021-04-01"
  resource_id = data.azurerm_management_group.this.id
  action      = "providers/Microsoft.Network/register"
  method      = "POST"
}

Azure Virtual Network Manager instance

The next step is to create the AVNM instance in the target region where you plan to manage IPAM resources. The location matters because AVNM is a regional resource and will manage network resources aligned to that region.

resource "azurerm_network_manager" "network_manager" {
  depends_on          = [azapi_resource_action.resource_providers]
  name                = "nw-prod-weu-001"
  description         = "Network manager in west europe"
  location            = "westeurope"
  resource_group_name = "rg-network-manager-prod-we-001"

  scope {
    management_group_ids = [data.azurerm_management_group.this.id]
  }
}

By scoping the Network Manager to the management group, it can manage IP addresses (and network configurations) across all subscriptions under that group. This provides centralized governance for IPAM while allowing individual teams to deploy networks without risking overlapping address space.

Defining IP address pools (IPAM pools)

With the Network Manager in place, you can define the IP address pools. Think of pools as the inventory of your private address space. You start with a single top-level (root) pool that represents the full range, and then carve that range into smaller child pools that reflect how your organization segments networks by function, environment, or ownership.

  • Root pool: represents the top-level address space you own and want IPAM to manage (for example, 10.0.0.0/xx). This is the umbrella range from which all other allocations are derived.
  • Child pools: subdivide the root space into logical segments so teams can allocate from a scoped range without stepping on each other. Common patterns include:
    • Platform/shared services (central infrastructure, identity, monitoring)
    • Landing zones (workload-specific networks such as production and non-production)

This hierarchy keeps your address space organized, enforces boundaries, and makes it easy to report on utilization by area. It also enables delegation, since teams can be granted access to specific child pools rather than the entire address space.

The snippet below creates such a root IPAM pool. The address_prefixes value should represent the full CIDR range you control (for example, 10.0.0.0/8), and the pool is tied to the AVNM instance so IPAM can enforce allocations and track utilization.

resource "azurerm_network_manager_ipam_pool" "root_ipam" {
  name               = "ipam-root-prod-weu-001"
  location           = "westeurope"
  network_manager_id = azurerm_network_manager.network_manager.id
  display_name       = "ipam-root-prod-weu"
  address_prefixes   = "10.0.0.0/8"
}

The next snippet shows a child pool that subdivides the root range into a smaller, scoped segment (for example, a platform or shared-services range). The parent_pool_name links it to the root pool, and address_prefixes defines the CIDR(s) reserved for this segment. Of course, the address range must be within the parent pool's range.

resource "azurerm_network_manager_ipam_pool" "child_pool" {
  name               = "ipam-pl-prod-weu-001"
  location           = "westeurope"
  parent_pool_name   = azurerm_network_manager_ipam_pool.root_ipam.name
  network_manager_id = azurerm_network_manager.network_manager.id
  display_name       = "ipam-platform-prod-weu"
  address_prefixes   = "10.0.0.0/10"
}

How the pools work together

If the root pool is 10.0.0.0/8 and you create child pools, Platform: 10.0.0.0/10 and Landing zones: 10.64.0.0/10 then IPAM enforces strict boundaries so that any allocation from the Platform pool must stay within 10.0.0.0/10, and any allocation from the Landing zones pool must stay within 10.64.0.0/10.

This separation ensures that teams working in different areas can request address space independently without overlapping. In practice, this means a team deploying shared services can safely create new VNets in the Platform segment while application teams build their networks in the Landing zones segment, all without manual coordination. The result is predictable growth, simpler troubleshooting, and centralized visibility into how each segment of the address space is being consumed across subscriptions and environments.

Reserving external IP ranges as static CIDRs

IPAM can track ranges already in use outside IPAM control using static CIDR allocations within a pool. This is useful for any address space that must be visible to IPAM but isn’t allocated by Azure resources directly, such as on-premises networks, Virtual WAN hubs, AWS private clouds, or third‑party environments.

These static entries don’t map to an Azure resource; they serve as placeholders to keep IPAM’s free/used accounting accurate, and those ranges aren't assigned by accident. In practice, this means you “claim” the external CIDR inside the appropriate pool, preventing IPAM from handing it out to a new VNet while still reflecting the range in utilization reports and capacity planning.

Virtual network integration: automatic IP allocation

Normally, a Terraform azurerm_virtual_network or azurerm_subnet requires explicit address_space or address_prefixes. With IPAM, you can omit it and let Azure allocate a suitable, non-overlapping CIDR from a pool.

Instead of manually specifying a CIDR block like 10.1.0.0/24 or 10.2.0.0/24, you can leave the address space blank and tell IPAM how many IP addresses you need. IPAM then automatically selects an available range from the designated pool that fits your request.

This is accomplished by using the ip_address_pool block to request automatic allocation from IPAM. The number_of_ip_addresses parameter specifies the size you need (for example, 256 addresses for a /24), and IPAM finds a suitable, non-overlapping CIDR block within the pool's boundaries and assigns it to the VNet.

Example:

data "azurerm_network_manager" "network_manager" {
  name                = "nw-prod-weu-001"
  resource_group_name = "rg-network-manager-prod-we-001"
}

data "azurerm_network_manager_ipam_pool" "ipam_pool" {
  name               = "ipam-pl-prod-weu-001"
  network_manager_id = data.azurerm_network_manager.network_manager.id
}

resource "azurerm_virtual_network" "vnet" {
  # ...existing code...
  address_space = null

  ip_address_pool {
      id                     = data.azurerm_network_manager_ipam_pool.ipam_pool.id
      number_of_ip_addresses = 256
  }
  # ...existing code...
}

resource "azurerm_subnet" "subnets" {
  # ...existing code...
  address_prefixes = null

  ip_address_pool {
      id                     = data.azurerm_network_manager_ipam_pool.ipam_pool.id
      number_of_ip_addresses = 64
    }
  # ...existing code...
}

Delegating access with a custom IPAM role

IPAM supports role-based access control (RBAC), and by default, Azure provides a built-in IPAM Pool User role. This role grants broad read and write permissions that may exceed what you need for certain scenarios. If you need users to view IPAM pool properties of a virtual network or subnet, the built-in role has too many permissions.

Unfortunately, there is no read-only role available. Hence, a custom role definition allows you to grant exactly the read-only visibility required to monitor pool utilization across all networks without the risk of accidental modifications.

resource "azurerm_role_definition" "ipam_reader" {
  name  = "Custom Role IPAM Reader"
  scope = data.azurerm_management_group.this.id

  permissions {
    actions = [
      "Microsoft.Network/networkManagers/ipamPools/*/read",
      "Microsoft.Network/networkManagers/ipamPools/*/action"
    ]
    not_actions = [
      "Microsoft.Network/networkManagers/ipamPools/associateResourcesToPool/action",
      "Microsoft.Network/networkManagers/ipamPools/allocateAzureResource/action",
      "Microsoft.Network/networkManagers/ipamPools/allocateNonAzureResource/action",
      "Microsoft.Network/networkManagers/ipamPools/allocateResourcePrefixes/action",
      "Microsoft.Network/networkManagers/ipamPools/disassociateResourcesFromPool/action"
    ]
    data_actions = []
  }
}

This custom role grants visibility into pools and allocations while explicitly preventing users from allocating resources, associating networks with pools, or modifying the address space. Users assigned this role can view pool properties, view utilization metrics, and see which networks and resources consume which prefixes, making it ideal for read-only capacity planning and auditing.

This role definition can look counter‑intuitive at first glance because it includes a broad */action permission and then tries to “undo” the risky parts with not_actions.

In an ideal world, you’d grant only: .../read for reading pool properties, and nothing else. In practice, Azure IPAM doesn’t seem to behave like a clean “read-only = only read operations” API surface. Several “read-like” experiences (portal blades, listing allocations, browsing associations, some GET/list flows) seem to be implemented as action operations under the hood. We expect that this will be adjusted in the near future. For now, we expect this issue is due to IPAM being a service still in preview.

This custom role will need an exemption for policy assignments like ISO27001:2013 and CIS Benchmark

Considerations before you start

Plan your IP space hierarchy before creating pools. Before you begin implementing IPAM, carefully design your IP address pool structure. Consider your organizational boundaries, team structures, regional deployments, and anticipated growth. A well-thought-out hierarchy prevents the need for expensive redesigns later and ensures pools align with how your organization actually manages and deploys networks.

Regional pool alignment matters because IPAM pools are region-specific. Remember that IPAM pools can only allocate addresses to virtual networks and resources in the same Azure region. This means if you deploy in multiple regions, you need to create parallel pool structures in each region. Plan your regional deployment strategy early to avoid confusion about which pools manage which regions and to ensure consistent naming conventions across regions.

Monitor utilization using IPAM views to see allocated and free space. Regularly review your IPAM pool utilization to understand how address space is being consumed and identify which resources occupy which prefixes. This visibility helps you make informed capacity-planning decisions, predict when pools may approach exhaustion, and identify inefficient or orphaned allocations that could be reclaimed. Establish monitoring dashboards and alerts to track utilization trends over time.

Be cost-aware because AVNM is a paid service. Azure Virtual Network Manager incurs charges, and specifically for IPAM, you pay based on the number of active managed IP addresses. Factor this cost into your overall cloud budget and cost modeling, especially for large-scale deployments with hundreds of virtual networks. Monitor your managed IP count to understand cost drivers and optimize your pool allocations accordingly.

Migration to IPAM Migrating from static address ranges to IPAM can be done in three steps. First, disconnect all existing VNets and subnets by removing dependent resources, peering relationships, and network policies; second, connect IPAM by creating your pool hierarchy, reserving external ranges as static CIDRs, and updating your infrastructure-as-code to reference pools instead of hardcoded address spaces; finally, reconnect by redeploying networks with automatic IPAM allocation, restoring peering and hub-and-spoke topologies, and reattaching workloads. Although it is only three steps, migrating all VNets to IPAM can be quite cumbersome and time-consuming. So, if you can start with IPAM from the beginning to prevent a lot of migration work.

Conclusion

Azure IPAM provides structure, automation, and governance for one of the most error-prone aspects of cloud networking: managing private address space at scale. By combining Azure Virtual Network Manager with hierarchical IP pools, static CIDR reservations, and infrastructure-as-code integration, you can prevent overlapping ranges, simplify network deployments, and gain clear visibility into how address space is consumed across teams, environments, and regions.

In short, Azure IPAM helps replace manual tracking with a scalable, governed, and future-ready approach to network address management.

References

Written by

Victor de Baare

Victor de Baare is a developer with a deep passion for building systems that make work more efficient and straightforward. He thrives under pressure, persistently working towards his goals regardless of the challenge. He finds joy in whisky, food, gaming, and board games. He continues to inspire and innovate, making significant contributions to technology and efficiency.

Contact

Let’s discuss how we can support your journey.