
Designing Azure VNets with Purpose-Driven Subnets (using Terraform Module)
- Posted by Martin Linxfeld
- Categories azure, opentofu, terraform
- Date December 18, 2025
- Comments 0 comment
- Tags AKS networking, Azure Architecture, Azure Networking, Azure VNet, cloud networking, FoggyKitchen, Infrastructure as Code, Private Endpoints, terraform, Terraform Modules
Azure VNet Terraform Module – Explained
An Azure VNet Terraform module is the foundation of every scalable Azure network architecture. Yet in many projects, virtual networks are still designed ad-hoc — without clear intent, subnet boundaries, or future workloads in mind.
In this article, I’ll show how to design Azure VNets using a purpose-driven Terraform module, where subnets are first-class architectural decisions rather than an afterthought.
This approach is based on a reusable Terraform module used across FoggyKitchen Azure content.
📐 Design notes
The short video below explains why Azure VNets must be designed as intent-driven contracts, and why ad-hoc subnet layouts become technical debt long before workloads exist.
This design-level discussion complements the hands-on Terraform implementation described below.
The problem with ad-hoc VNet design
A very common pattern looks like this:
Create a VNet
Add one or two subnets “for now”
Deploy AKS, VMs, or PaaS services
Add more subnets later when something breaks
This works — until it doesn’t.
Typical consequences:
overlapping address spaces
subnets that mix unrelated responsibilities
painful refactoring when Private Endpoints or private AKS APIs appear
networking becoming the bottleneck instead of the foundation
The root cause is simple: the VNet was not designed with intent.
If you’re starting with Azure networking, this approach is completely natural.
In fact, I’ve previously shown how to build an Azure VNet using raw Terraform resources step by step in this article:
👉 Azure Virtual Network (VNet) and Subnets with Terraform — The Foundation of Your Cloud Network
This is why Azure infrastructure with Terraform should be designed as a layered system — not as isolated resources.
👉 See the full Azure infrastructure with Terraform architecture model: Azure Infrastructure with Terraform – Architecture Model
Thinking in intent, not resources
Instead of asking:
“What resources do I need right now?”
we should ask:
“What responsibilities must this network support over time?”
This shift changes everything.
A subnet is no longer:
“where something happens”
It becomes:
“where a specific category of traffic and responsibility lives”
Examples:
public ingress
private workloads
application services
platform components
private endpoints
Azure VNet address space as an architectural decision
One practical example of intent-driven design appears even before Terraform modules are applied: choosing the VNet address space.
A poorly chosen address range often forces painful redesign later — especially when new services like Private Endpoints, AKS, or hub-and-spoke networking are introduced.
For this reason, many Azure VNet address space best practices focus on planning for future platform layers.
Typical considerations include:
• leaving enough address space for multiple subnets
• avoiding CIDR ranges that may overlap with VPN or hybrid networks
• reserving dedicated subnets for platform services such as Private Endpoints or container platforms
In the module used in this article, the address space becomes the network contract that later workloads consume.
Terraform then enforces that contract consistently across environments.
A purpose-driven subnet layout
Design context
This example does not focus on creating individual Azure resources.
Instead, it demonstrates how to design Azure networking as a reusable, opinionated Terraform module.
The goal is not to build “a VNet”, but to create a network foundation that:
- can be reused across environments,
- scales naturally with platform services like AKS,
- and enforces architectural intent through subnet design.
This approach mirrors how real-world Azure landing zones evolve — starting simple, but with clear boundaries that support Private Endpoints, PaaS services, and Kubernetes workloads later on.
Key idea:
We validate the network contract before deploying anything on top of it.
👉 See the full Azure infrastructure with Terraform architecture model: Azure Infrastructure with Terraform – Architecture Model
Implementing intent as a Terraform payload
Instead of creating subnets with individual azurerm_subnet resources, we express network intent as data.
Example payload:
subnets = {
public = {
address_prefixes = ["10.10.0.0/24"]
}
private = {
address_prefixes = ["10.10.1.0/24"]
}
apps = {
address_prefixes = ["10.10.2.0/24"]
}
}
This payload is then consumed by a reusable Terraform module.
The reusable VNet module
The module itself lives here:
👉 Repository:
https://github.com/foggykitchen/terraform-az-fk-vnet
It is designed to:
accept subnet intent as input
create subnets dynamically
expose subnet IDs for downstream consumers
remain stable as workloads evolve
This allows us to separate network design from network usage.
Example: VNet with purpose-driven subnets
The full working example used in this article is:
👉 Example 02 – VNet with subnets:
https://github.com/foggykitchen/terraform-az-fk-vnet/tree/main/examples/02-vnet-with-subnets
This example intentionally deploys no workloads.
That is not a limitation — it is a design choice.
The goal is to validate:
address space planning
subnet responsibility
future extensibility
before AKS, VMs, or PaaS services are introduced.
Why this approach scales
Once the network is defined this way:
AKS can consume a dedicated subnet
Private Endpoints can live in a separate, controlled subnet
security rules remain predictable
future services do not force a redesign
The network stays stable.
Only its consumers change.
This is the foundation of scalable Azure architectures.
From fundamentals to real workloads
In future articles, this exact VNet layout will be reused to deploy:
Azure Kubernetes Service (AKS)
Azure Container Registry with Private Endpoints
Private DNS integration
fully private traffic flows
The network itself will not change.
Only the workloads layered on top of it will.
Learn the foundations first
If you want to understand why this matters in real AKS deployments, the next logical step is learning AKS networking fundamentals properly.
👉 Azure Kubernetes Service (AKS) with Terraform – Fundamentals
https://foggykitchen.com/aks-terraform-course/
That course focuses on:
AKS networking basics
VNet and subnet integration
building clusters that don’t need redesign later
This article goes beyond the course on purpose —
but the course gives you the necessary foundation to fully appreciate it.
Building an Azure platform with Terraform
A VNet is only the foundation of an Azure platform. Real environments emerge when networking, storage, compute, and traffic layers are composed together.
Typical next steps include:
• Network security boundaries
👉 Azure Network Security Groups with Terraform
• Private data services
👉 Azure Blob Storage with Private Endpoint
👉 Azure Files with Private Endpoint
• Workloads inside private subnets
👉 Azure Virtual Machines with Terraform
• Controlled traffic entry points
👉 Azure Load Balancer with Terraform
👉 Azure NAT Gateway with Terraform
• Container platforms built on the same network
👉 Azure Kubernetes Service (AKS) with Terraform
Well-designed Terraform modules allow these layers to be composed predictably and repeatedly.
A strong VNet design becomes the contract that everything else builds on.
Final thoughts
Good Azure architectures are not built by adding resources.
They are built by:
designing contracts
defining intent
and letting modules enforce consistency
A VNet designed this way becomes an asset — not a constraint.

From Network Design to Real Azure Architecture
This article introduced the foundation of every Azure platform — the network boundary.
Real systems are built by layering compute, storage, and private connectivity on top of this design — not by skipping it.
This is exactly the architecture path followed in the Azure Fundamentals course.
🔒 Lifetime • ⏱️ Self-paced • 🧪 Real labs


