A Guide with Azure Cloud Network Configuration Examples
In the realm of Infrastructure as Code (IaC), Terraform is a widely adopted tool that simplifies the process of managing and provisioning infrastructure across various cloud platforms. When dealing with cloud networking, especially in Azure, managing IP address spaces and subnetting can become complex. Terraform’s cidrsubnets function helps streamline this process by allowing you to divide a larger CIDR block into multiple subnets efficiently.
In this blog post, we’ll delve into the cidrsubnets function and explore how it can be used within the context of Azure Virtual Networks (VNets). We will provide practical examples to illustrate its usage in designing and configuring network topologies in Azure, including assigning static IPs to Azure Virtual Machines (VMs).
What is the cidrsubnets Function?
The cidrsubnets function in Terraform is designed to create multiple subnet CIDR blocks from a single parent CIDR block. This is particularly useful when designing cloud networks, where you often need to subdivide a Virtual Network (VNet) into smaller subnets that serve different purposes, such as public subnets, private subnets, and database subnets.
Function Signature
The syntax for the cidrsubnets function is straightforward:
cidrsubnets(prefix, newbits1, newbits2, ...)
- prefix: The starting CIDR block that you want to subdivide.
- newbits1, newbits2, …: The number of additional bits to add to the prefix to create each subnet. Each value corresponds to a different subnet.
The function returns a list of subnet CIDR blocks based on the parameters provided.
How cidrsubnets Works in Azure
Azure Virtual Networks (VNets) are the foundation of your network infrastructure in Azure. Each VNet is associated with a CIDR block, and you can create multiple subnets within a VNet to organize your resources logically. The cidrsubnets function is particularly useful when you need to automate the creation of these subnets.
Let’s explore some common scenarios where you might use cidrsubnets in an Azure context.
Example 1: Creating Subnets in a Single VNet
Suppose you have an Azure VNet with a CIDR block of 10.0.0.0/16. You want to divide this VNet into three subnets:
- Subnet 1: A public subnet for hosting web servers.
- Subnet 2: A private subnet for application servers.
- Subnet 3: A private subnet for database servers.
Here’s how you can do it using Terraform:
variable "vnet_cidr" {
default = "10.0.0.0/16"
}
output "subnets" {
value = cidrsubnets(var.vnet_cidr, 8, 8, 8)
}
In this example:
- Each
8represents adding 8 bits to the CIDR prefix, converting the/16block into/24subnets. - The
cidrsubnetsfunction will produce three /24 subnets:
output "subnets" {
value = [
"10.0.0.0/24", # Subnet 1: Public subnet
"10.0.1.0/24", # Subnet 2: Private subnet for application servers
"10.0.2.0/24" # Subnet 3: Private subnet for database servers
]
}
You can then use these subnets to create actual resources in Azure:
resource "azurerm_virtual_network" "main_vnet" {
name = "main-vnet"
address_space = [var.vnet_cidr]
location = "East US"
resource_group_name = "my-resource-group"
}
resource "azurerm_subnet" "public_subnet" {
name = "public-subnet"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main_vnet.name
address_prefixes = [cidrsubnets(var.vnet_cidr, 8)[0]]
}
resource "azurerm_subnet" "app_subnet" {
name = "app-subnet"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main_vnet.name
address_prefixes = [cidrsubnets(var.vnet_cidr, 8)[1]]
}
resource "azurerm_subnet" "db_subnet" {
name = "db-subnet"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main_vnet.name
address_prefixes = [cidrsubnets(var.vnet_cidr, 8)[2]]
}
Example 2: Multi-AZ Deployment with Subnets
Azure allows you to deploy resources across multiple Availability Zones (AZs) for redundancy and high availability. Let’s consider a scenario where you want to create subnets for a multi-AZ setup.
Assume you have a VNet with a CIDR block of 192.168.0.0/16 and you want to create three /20 subnets, each in a different AZ:
variable "vnet_cidr" {
default = "192.168.0.0/16"
}
output "az_subnets" {
value = cidrsubnets(var.vnet_cidr, 4, 4, 4)
}
This Terraform code will generate the following subnets:
192.168.0.0/20(for AZ 1)192.168.16.0/20(for AZ 2)192.168.32.0/20(for AZ 3)
These subnets can then be used to deploy resources across different AZs:
resource "azurerm_subnet" "az1_subnet" {
name = "az1-subnet"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main_vnet.name
address_prefixes = [cidrsubnets(var.vnet_cidr, 4)[0]]
}
resource "azurerm_subnet" "az2_subnet" {
name = "az2-subnet"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main_vnet.name
address_prefixes = [cidrsubnets(var.vnet_cidr, 4)[1]]
}
resource "azurerm_subnet" "az3_subnet" {
name = "az3-subnet"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main_vnet.name
address_prefixes = [cidrsubnets(var.vnet_cidr, 4)[2]]
}
Example 3: Assigning Static IPs to Azure VMs Using cidrsubnets
In many enterprise environments, certain VMs require static IP addresses, either for direct access or to ensure consistent communication with other resources. Terraform’s cidrsubnets function can help assign these static IPs efficiently.
Scenario
Imagine you have a VNet with a CIDR block of 10.2.0.0/16, and you want to create a subnet specifically for VMs that will have static IP addresses. Let’s create a /24 subnet within this VNet and assign static IP addresses to two VMs.
variable "vnet_cidr" {
default = "10.2.0.0/16"
}
output "subnet_cidr" {
value = cidrsubnets(var.vnet_cidr, 8)[0]
}
This will create the first /24 subnet (10.2.0.0/24) within the VNet.
Next, we’ll assign static IPs to two VMs within this subnet.
resource "azurerm_virtual_network" "main_vnet" {
name = "static-ip-vnet"
address_space = [var.vnet_cidr]
location = "East US"
resource_group_name = "my-resource-group"
}
resource "azurerm_subnet" "vm_subnet" {
name = "vm-subnet"
resource_group_name = "my-resource-group"
virtual_network_name = azurerm_virtual_network.main_vnet.name
address_prefixes = [output.subnet_cidr.value]
}
resource "azurerm_network_interface" "vm_nic1" {
name = "vm1-nic"
location = azurerm_virtual_network.main_vnet.location
resource_group_name = azurerm_virtual_network.main_vnet.resource_group_name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "Static"
private_ip_address = cidrhost(azurerm_subnet.vm_subnet.address_prefixes[0], 5)
}
}
resource "azurerm_network_interface" "vm_nic2" {
name = "vm2-nic"
location = azurerm_virtual_network.main_vnet.location
resource_group_name = azurerm_virtual_network.main_vnet.resource_group_name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.vm_subnet.id
private_ip_address_allocation = "Static"
private_ip_address = cidrhost(azurerm_subnet.vm_subnet.address_prefixes[0], 6)
}
}
resource "azurerm_virtual_machine" "vm1" {
name = "vm1"
location = azurerm_virtual_network.main_vnet.location
resource_group_name = azurerm_virtual_network.main_vnet.resource_group_name
network_interface_ids = [azurerm_network_interface.vm_nic1.id]
vm_size = "Standard_B2s"
storage_os_disk {
name = "vm1_os_disk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = "vm1"
admin_username = "adminuser"
admin_password = "P@ssw0rd1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}
resource "azurerm_virtual_machine" "vm2" {
name = "vm2"
location = azurerm_virtual_network.main_vnet.location
resource_group_name = azurerm_virtual_network.main_vnet.resource_group_name
network_interface_ids = [azurerm_network_interface.vm_nic2.id]
vm_size = "Standard_B2s"
storage_os_disk {
name = "vm2_os_disk"
caching = "ReadWrite"
create_option = "FromImage"
managed_disk_type = "Standard_LRS"
}
os_profile {
computer_name = "vm2"
admin_username = "adminuser"
admin_password = "P@ssw0rd1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}
Explanation
- Subnet Creation: The
cidrsubnetsfunction is used to create a /24 subnet (10.2.0.0/24) within the10.2.0.0/16VNet. - Static IP Assignment: We use the
cidrhostfunction to calculate specific IP addresses within the subnet. In this case,cidrhost(azurerm_subnet.vm_subnet.address_prefixes[0], 5)will assign the IP address10.2.0.5tovm1, andcidrhost(azurerm_subnet.vm_subnet.address_prefixes[0], 6)will assign10.2.0.6tovm2.
Tips and Best Practices
- CIDR Planning: Proper CIDR planning is crucial. Ensure that your subnets do not overlap and that there’s enough space for future expansion.
- Variable CIDR Sizes: Consider using variables for
newbitsvalues to allow flexibility in subnet sizes, especially in larger environments. - Resource Group Management: In Azure, group related subnets within the same resource group to manage them effectively and ensure consistency across your network configuration.
- Availability Zone Awareness: When deploying in multiple AZs, ensure that subnets are evenly distributed across AZs to avoid single points of failure.
- Documenting Network Layout: Always document your network layout, including the purpose and usage of each subnet. This helps in managing and scaling your network effectively.
Terraform’s cidrsubnets function is a powerful tool for automating subnet creation in Azure, making it easier to design and manage complex network architectures. By understanding how to use this function effectively, you can create scalable, organized, and well-planned network infrastructures that meet your organization’s needs.
The inclusion of static IP assignments for Azure VMs in this guide demonstrates how cidrsubnets can be integrated into more advanced and practical use cases. With the examples provided, you should be well on your way to implementing robust and flexible networking solutions in Azure using Terraform. As you continue to develop your Terraform skills, consider experimenting with different CIDR block sizes and configurations to find the setup that best fits your use case.