Warning
Azure Relational Infrastructure is currently in public preview. Use with caution.
Azure Relational Infrastructure (AzRI) simplifies Azure deployments by modeling infrastructure as code (IaC) like a relational database. In the 1970s, relational databases tamed chaotic data with structured tables, primary keys, and foreign keys, making data compact, queryable, and easy to update. Similarly, AzRI organizes Terraform resources into concise maps with clear relationships, slashing code sprawl and complexity. This relational approach mirrors database normalization, eliminating redundancy and simplifying modifications. Built on Azure Verified Modules (AVM) and aligned with Azureβs Well-Architected Framework, AzRI ensures resilient, scalable Terraform deployments. Features like lock groups enhance management, drawing on Microsoft and partner expertise. AzRI makes Azure IaC cleaner and more efficient, just as relational databases transformed data management.
---
title: Infrastructure Map Model
---
erDiagram
Locations ||--o{ "Resource Groups" : ""
Locations ||--o{ "Networks" : ""
Locations ||--o{ "Role-Based VM Sets" : ""
Locations ||--o{ "Key Vaults" : ""
Locations ||--o{ "Storage Accounts" : ""
Subscriptions ||--o{ "Key Vaults" : ""
Subscriptions ||--o{ "Resource Groups" : ""
Subscriptions ||--o{ "Networks" : ""
Subscriptions ||--o{ "Role-Based VM Sets" : ""
Subscriptions ||--o{ "Storage Accounts" : ""
Subscriptions ||--o{ "Private DNS Zones" : ""
"Shutdown Schedules" ||--o{ "Role-Based VM Sets" : ""
"Resource Groups" ||--o{ "Role-Based VM Sets" : ""
"Resource Groups" ||--o{ "Key Vaults" : ""
"Resource Groups" ||--o{ "Storage Accounts" : ""
"Resource Groups" ||--o{ "Private DNS Zones" : ""
"Private Endpoints" }o--o{ "Private DNS Zones" : ""
"Networks" }o--o{ "Private DNS Zones" : ""
"Subscriptions" ||..|| "Resource Groups" : "has a default"
"Subscriptions" ||..|| "Resource Groups" : "has a dedicated private link"
"Subscriptions" ||--o{ "Networks" : ""
"Subscriptions" ||--o{ "Role-Based VM Sets" : ""
"Subscriptions" ||--o{ "Key Vaults" : ""
"VM Extensions" }o--o{ "Role-Based VM Sets" : ""
"VM Scale Sets" |o--o{ "Role-Based VM Sets" : ""
"Networks" ||..o{ "Subnets" : ""
"Network Security Groups" ||--o{ "Network Security Rules" : "have"
"Networks" }o--o{ "Network Security Groups" : "via security_group_name"
"External Networks" ||..o{ "External Subnets" : ""
"Subnets" ||..o{ "Routes" : ""
"Routes" ||--|| "Networks" : "to"
"Routes" ||--|| "External Networks" : "to"
"Routes" ||--|| "Subnets" : "to"
"Routes" ||--|| "External Subnets" : "to"
"Ports" }o--o{ "Network Security Rules" : "to/from"
"Network Security Rules" ||--o{ "Networks" : "to/from"
"Network Security Rules" ||--o{ "Subnets" : "to/from"
"Network Security Rules" ||--o{ "External Networks" : "to/from"
"Network Security Rules" ||--o{ "External Subnets" : "to/from"
"Network Security Rules" ||--o{ "Role-Based VM Sets" : "to/from"
"Key Vaults" ||..o{ "Role-Based VM Sets" : "protect"
"Role-Based VM Sets" ||..|{ "Network Interfaces" : "have"
"Role-Based VM Sets" ||--o| "Load Balancers" : "have"
"Load Balancers" }o--o{ "Subnets" : "internal frontend on"
"Ports" }o--o{ "Load Balancers" : "probe/rules via"
"Role-Based VM Sets" ||..|{ "Data Disk Groups" : "have"
"Subnets" ||--o{ "Network Interfaces" : "contain"
"Role-Based VM Sets" ||--o| "Availability Zone Distribution Strategy" : "uses"
"Role-Based VM Sets" ||--|| "VM Set Specs" : "have"
"VM Set Specs" ||..o{ "Data Disk Group Specs" : "have"
"Data Disk Groups" ||..|| "Data Disk Group Specs" : "have"
"Resource Groups" ||--o{ "Networks" : "have"
"Key Vaults" ||--o{ "Private Endpoints" : "have"
"Subnets" ||--o{ "Private Endpoints" : "have"
"Networks" ||..o{ "Peerings" : "have"
"Peerings" ||--|| "Networks" : "peered to"
"Peerings" ||--|| "External Networks" : "peered to"
"Lock Groups" ||--o{ "Resource Groups" : "lock"
"Lock Groups" ||--o{ "Networks" : "lock"
"Lock Groups" ||--o{ "Key Vaults" : "lock"
"Lock Groups" ||--o{ "Role-Based VM Sets" : "lock"
"Lock Groups" ||--o{ "Data Disk Groups" : "lock"
"Lock Groups" ||--o{ "Network Interfaces" : "lock"
"Lock Groups" ||--o{ "Private Endpoints" : "lock"
"Lock Groups" ||--o{ "Storage Accounts" : "lock"
"Storage Accounts" ||--o{ "Blob Containers" : "have"
"Storage Accounts" ||--o{ "File Shares" : "have"
"Blob Containers" ||--o{ "Private Endpoints" : "have"
"File Shares" ||--o{ "Private Endpoints" : "have"
Note
In the sections below:
- π indicates a "primary key"; typically the "one" side of a one-to-many relationship
- π indicates a "foreign key"; typically the "many" side of a one-to-many relationship
Terraform variable:
var.locations
The locations table defines the Azure regions where your infrastructure lives, like eastus or westus. Itβs the starting point for placing resources geographically, ensuring they align with Azureβs global regions for availability and compliance. In the entity-relationship diagram (ERD), locations acts as a reference point, linking one-to-many with tables like networks or virtual machine sets to specify where theyβre deployed.
locations = {
primary = "eastus" # π "primary" location; must be a valid Azure region (see below)
alt = "westus" # π "alt" location; must be a valid Azure region (see below)
}Tip
Powershell Users: For a complete list of valid Azure locations, install the Az Powershell module, then run the following command:
Get-AzLocation | Select-Object -Property Name | ForEach-Object { $_.Name }Tip
Azure CLI/Bash Users: For a complete list of valid Azure locations, install the Azure CLI, then run the following command:
az account list-locations --query "[].name" -o tsvTerraform variable:
var.subscriptions
Important
Up to ten (10) subscriptions are supported.
The subscriptions table organizes your Azure subscriptions, acting as a control center for grouping resources across your environment. Each subscription connects to resource groups and Terraform providers, setting the scope for your infrastructure. In the entity-relationship diagram (ERD), subscriptions serves as a central hub, with one-to-many links to tables like resource_groups and networks, ensuring resources stay aligned.
subscriptions = {
production = { # π "production" subscription
default_resource_group_name = "production" # π Links to var.resource_groups
private_link_resource_group_name = "production_networks" # π Optional; links to var.resource_groups
subscription_id = "00000000-0000..." # Azure subscription ID (must be a GUID)
}
non_production = { # π "non_production" subscription
default_resource_group_name = "non_production" # π Links to var.resource_groups
private_link_resource_group_name = "non_production_networks" # π Optional; Links to var.resource_groups
subscription_id = "10000000-0000..." # Azure subscription ID (must be a GUID)
}
}| Field | Description |
|---|---|
default_resource_group_name |
Links to a key in var.resource_groups. Defines the primary resource group for the subscription. |
private_link_resource_group_name |
Optional; if set, links to a key in var.resource_groups for private link resources. Defaults to default_resource_group_name if unset. |
subscription_id |
References a specific Azure subscription ID. Must be a GUID. |
Terraform variable:
var.lock_groups
The lock_groups table groups Azure resourcesβlike VMs, networks, or disksβinto logical sets for coordinated lock management during maintenance, such as updating a regionβs infrastructure or a compute tier. Resources in tables like var.virtual_machine_sets or var.networks can list lock group keys in their lock_groups property to join one or more groups. Each group toggles locks (CanNotDelete or ReadOnly) for its members.
This is how lock groups work:
- If the resource has no
lock_groups, the resource is unlocked. - If any of the resource's
lock_groupsare unlocked, the resource is unlocked. - If all of a resource group's
lock_groupsare locked and any of thelock_groupsare configured forread_only, a read-only lock is applied to the resource. - If all of a resource group's
lock_groupsare locked and none of thelock_groupsare configured forread_only, a do-not-delete lock is applied to the resource.
In the ERD, lock_groups has a many-to-many relationship with resources, linked via lock_groups properties in other tables.
lock_groups = {
production_lock = { # π Primary key: "production_lock"
locked = true # Locks enabled
read_only = true # ReadOnly lock
}
non_production_lock = { # π Primary key: "maintenance_lock"
locked = false # Locks disabled
read_only = false # CanNotDelete lock
}
}Important
When a resource belongs to multiple locked groups (via its lock_groups property), the most restrictive lock wins: a ReadOnly lock (read_only = true) takes precedence over a CanNotDelete lock (read_only = false).
| Field | Description |
|---|---|
locked |
Required; if true, applies locks to group resources; if false, removes them for maintenance. |
read_only |
Optional; if true, applies ReadOnly locks (no changes); if false, applies CanNotDelete locks (allows updates). Defaults to false. ReadOnly wins if multiple locked groups apply. |
Terraform variable:
var.resource_groups
The resource_groups table defines the Azure resource groups that bundle related resources together in your environment. Each resource group ties to a subscription and, optionally, a location, organizing assets like networks or VMs. In the entity-relationship diagram (ERD), resource_groups links one-to-one with subscriptions and optionally to locations, acting as a container for other resources.
resource_groups = {
production = { # π "production" resource group
subscription_name = "production" # π Links to var.subscriptions
location_name = "primary" # π Optional; links to var.locations
name = "production" # Resource group name in Azure
lock_groups = [
"production_lock" # π Optional; links to var.lock_groups
]
}
non_production = { # π "non_production" resource group
subscription_name = "non_production" # π Links to var.subscriptions
location_name = "alt" # π Optional; links to var.locations
name = "non-production" # Resource group name in Azure
lock_groups = [
"non_production_lock" # π Optional; links to var.lock_groups
]
}
}| Field | Description |
|---|---|
subscription_name |
Links to a key in var.subscriptions. Defines the subscription this resource group belongs to. |
location_name |
Optional; if set, links to a key in var.locations. Specifies the Azure region for the resource group. Defaults to the first location in var.locations if unset. |
lock_groups |
Optional; if set, links to keys in var.lock_groups. Specifies the resource lock groups that this resource group belongs to. |
name |
The name of the resource group as it appears in Azure, used to identify it. |
Terraform variable:
var.maintenance_schedules
The maintenance_schedules table defines when Azure applies platform updates, like patches or upgrades, to your virtual machines. Each schedule specifies a start time, update period, and how often updates repeat (daily, weekly, or monthly). In the ERD, maintenance_schedules links one-to-one with subscriptions and one-to-many with virtual_machine_sets, aligning update plans with your infrastructure.
maintenance_schedules = {
guest_updates = { # π Primary key: "guest_updates"
repeat_every = { # Updates every...
week = true # week
}
start_date_time_utc = "2025-01-05 22:00" # Window starts at 22:00
duration = "2:00" # Updates take 2 hours
}
host_updates = { # π Primary key: "host_updates"
repeat_every = { # Updates every...
days = 7 # 7 days
}
start_date_time_utc = "2025-01-06 23:00" # Window starts at 23:00
expiration_date_time_utc = "2026-01-06 23:00" # Expires after 1 year
duration = "1:30" # Updates take 90 minutes
}
}Important
VMs must be running 15 minutes before the update start time. Schedule updates during low-traffic periods to avoid impact.
| Field | Description |
|---|---|
repeat_every |
Required; sets the update frequency: day (daily), week (weekly), month (monthly), days (every n days), weeks (every n weeks), or months (every n months). Only one option can be set. |
start_date_time_utc |
Required; specifies the first update time in UTC, e.g., 2025-01-05 22:00. |
expiration_date_time_utc |
Optional; sets when the schedule ends, e.g., 2026-01-06 23:00. Defaults to null (no expiration). |
duration |
Optional; defines the update period in HH:MM format, e.g., 2:00 or 1:30. Defaults to 1:30 (90 minutes). Minimum varies by scope (e.g., 1.5h for guest updates). |
Terraform variable:
var.virtual_machine_shutdown_schedules
The virtual_machine_shutdown_schedules table defines daily shutdown schedules for Azure virtual machines, helping to reduce costs by automatically powering off VMs during off-hours. Each schedule specifies a shutdown time, timezone, and optional notifications (e.g., email or webhook alerts before shutdown). Schedules link to virtual_machine_sets via the shutdown_schedule_name field, allowing multiple VM sets to share the same schedule. In the ERD, virtual_machine_shutdown_schedules has a one-to-many relationship with virtual_machine_sets, enabling efficient management of shutdown policies across your infrastructure.
virtual_machine_shutdown_schedules = {
evening_shutdown = { # π "evening_shutdown" schedule
daily_recurrence_time = "1800" # Shutdown at 6:00 PM (24-hour format, no colon)
timezone = "Pacific Standard Time" # Timezone for the schedule
enabled = true # Schedule is active
notification_settings = {
enabled = true # Enable notifications
email = "admin@example.com" # Email for alerts
time_in_minutes = "30" # Notify 30 minutes before shutdown
webhook_url = "https://webhook.example.com" # Optional webhook for notifications
}
tags = {
purpose = "cost_savings" # Optional tags
}
}
weekend_shutdown = { # π "weekend_shutdown" schedule
daily_recurrence_time = "2200" # Shutdown at 10:00 PM
timezone = "Eastern Standard Time" # Timezone for the schedule
enabled = false # Schedule is disabled
}
}| Field | Description |
|---|---|
daily_recurrence_time |
Required; specifies the daily shutdown time in 24-hour format without a colon, e.g., 1800 for 6:00 PM. |
timezone |
Required; sets the timezone for the schedule, e.g., Pacific Standard Time. Must be a valid Azure timezone string. |
enabled |
Optional; if true, activates the schedule. Defaults to true. |
notification_settings |
Optional; configures pre-shutdown notifications with enabled (defaults to false), email (optional), time_in_minutes (defaults to "30"), and webhook_url (optional). Defaults to { enabled = false }. |
tags |
Optional; applies key-value tags to the schedule, e.g., { purpose = "cost_savings" }. Defaults to null. |
Note
Shutdown schedules are applied at the VM level and trigger daily based on the specified time and timezone. Notifications, if enabled, send alerts via email or webhook a set number of minutes before shutdown to allow for any necessary actions.
Terraform variable:
var.virtual_machine_extensions
The virtual_machine_extensions table sets up extensions for Azure VMs, adding capabilities like monitoring or management tools. It defines settings such as publisher, type, and versioning for consistent application across your environment. In the ERD, virtual_machine_extensions links one-to-many to virtual_machine_sets, letting multiple VM sets share the same extension configβlike the Azure Monitor Agent for Windows shown below.
virtual_machine_extensions = {
azure_monitor = { // π "azure_monitor" extension
name = "AzureMonitorWindowsAgent"
publisher = "Microsoft.Azure.Monitor"
type = "AzureMonitorWindowsAgent"
type_handler_version = "1.2"
auto_upgrade_minor_version = true
automatic_upgrade_enabled = true
settings = null
}
}| Field | Description |
|---|---|
name |
Identifies the extension within the VM, e.g., AzureMonitorWindowsAgent. |
publisher |
Specifies the extensionβs provider, like Microsoft.Azure.Monitor. |
type |
Defines the extension type, such as AzureMonitorWindowsAgent. |
type_handler_version |
Sets the extension handler version, e.g., 1.2. |
auto_upgrade_minor_version |
Enables automatic minor version updates if true. |
automatic_upgrade_enabled |
Activates automatic upgrades for the extension if true. |
settings |
Optional; holds custom settings for the extension, or null if unused. |
Terraform variable:
var.private_dns_zones
The private_dns_zones table provisions Azure Private DNS Zones.
- Private endpoints can refer to these zones by name when configuring DNS.
- Networks can refer to these zones by name for both DNS registration and resolution.
private_dns_zones = {
key_vault_private_endpoints = { # π "key_vault_private_endpoints" DNS zone
domain_name = "privatelink.vaultcore.azure.net" # Must be a valid domain name
resource_group_name = "production" # π Links to var.resource_groups
subscription_name = "production" # π Links to var.subscriptions
}
}Note
Private endpoints for Azure services require specific domain names. In the example provided above, privatelink.vaultcore.azure.net is the required domain name for Key Vault private endpoints.
Terraform variable:
var.network_ports
The network_ports table maps port names to port numbers. These ports are used when configuring security rules.
The example below illustrates some commonly used ports.
network_ports = {
http = "80" # π "http" port
https = "443" # π "https" port
rdp = "3389" # π "rdp" port
ssh = "22" # π "ssh" port
}Terraform variable:
var.network_security_rules
The network_security_rules table names layer 4 network security rules that are applied to network security groups defined in var.network_security_groups. Security rules are associated with a network security group via its security_rules list, and the group is applied to subnets in var.networks using the security_group_name property.
Network security rules are implemented using an easy-to-read fluent syntax that supports traffic filtering to/from:
- Specific address spaces
- Networks defined in
networks - External networks defined in
external_networks - Specific network subnets defined in
networks - Specific external network subnets defined in
external_networks - Role-based VM sets defined in
virtual_machine_sets
Each network security rule can specify optional inbound/outbound ports as defined in the network_ports table.
Each rule can also specify a protocol (e.g., Tcp, Udp). By default, all protocols are included in the rule's scope.
network_security_rules = {
deny_all_to_network = { # π Named security rule
deny = {
in = {
to = {
network = { # β Deny inbound to network...
name = "main" # π Linked to var.networks or var.external_networks
}
}
}
}
}
}network_security_rules = {
allow_all_http_s_from_alt_to_main_production = { # π Named security rule
port_names = [ # π Optional; links to `var.network_ports`
"http",
"https"
]
allow = {
in = { # β
Allow inbound...
from = {
network = { # From network...
name = "alt" # π Linked to var.networks or var.external_networks
}
}
to = {
subnet = { # To subnet...
network_name = "main" # π Linked to var.networks or var.external_networks
subnet_name = "production" # π Subnet defined on linked network
}
}
}
}
}
}network_security_rules = {
allow_all_tcp_from_on_prem_to_app_vm_set = { # π Named security rule
protocol = "Tcp" # Optional; Tcp protocol only
allow = {
out = { # β
Allow outbound...
from = {
address_space = "10.100.0.0/16" # From address space 10.100.0.0/16
}
to = {
vm_set = { # To role-based VM set
name = "app" # π Linked to var.virtual_machine_sets
}
}
}
}
}
}Terraform variable:
var.network_security_groups
The network_security_groups table defines Azure Network Security Groups (NSGs) that bundle one or more security rules together. An NSG is applied to a subnet by referencing it via the security_group_name property in var.networks.
network_security_groups = {
main = { # π "main" network security group
location_name = "main" # π Links to var.locations
subscription_name = "main" # π Links to var.subscriptions
resource_group_name = "main" # π Links to var.resource_groups
security_rules = [ # π Optional; links to var.network_security_rules
"allow_from_on_prem_to_apps", # Rules are applied in the order they're defined here
"deny_all_to_network"
]
}
}| Field | Description |
|---|---|
location_name |
Links to a key in var.locations, specifying the Azure region for the NSG. |
subscription_name |
Links to a key in var.subscriptions, tying the NSG to a subscription. |
resource_group_name |
Links to a key in var.resource_groups, defining the resource group for the NSG. |
name |
Optional; names the NSG in Azure. Defaults to the map key if not set. |
security_rules |
Optional; an ordered list of keys from var.network_security_rules. Rules are applied in the order listed. Defaults to []. |
tags |
Optional; applies key-value tags to the NSG. Defaults to {}. |
Terraform variable:
var.networks
The networks table defines the virtual networks (VNets) in your Azure environment, distinct from external networks (e.g., on-premises or other clouds) covered in var.external_networks. It organizes VNets and their subnets, linking them to subscriptions, locations, and resource groups. In the ERD, networks connects one-to-many with subnets and one-to-one with subscriptions, locations, and resource_groups, anchoring your network topology.
networks = {
main = { # π "main" network
location_name = "primary" # π Links to var.locations
subscription_name = "production" # π Links to var.subscriptions
resource_group_name = "production" # π Links to var.resource_groups
name = "main-vnet" # Optional; defaults to key π "main" if unset
address_space = "10.0.0.0/16" # Defines network address space in CIDR format
lock_groups = [
"production_lock" # π Optional; links to var.lock_groups
]
private_dns_zones = {
registration_zone_name = "registration_zone" # π Optional; links to var.private_dns_zones
# Only one registration zone is supported
resolution_zone_names = [ # π Optional; links to var.private_dns_zones
"resolution_zone" # Multiple resolution zones are supported
]
}
subnets = {
subnet_a = { # π "subnet_a" subnet
name = "subnet-a" # Optional; defaults to key π "subnet_a" if unset
address_space = "10.0.0.0/24" # Defines "subnet_a" address space in CIDR format
security_group_name = "main" # π Optional; links to var.network_security_groups
}
subnet_b = { # π "subnet_b" subnet
name = "subnet-b" # Optional, defaults to key π "subnet_b" if unset
address_space = "10.0.1.0/24" # Defines "subnet_a" address space in CIDR format
}
}
}
}| Field | Description |
|---|---|
location_name |
Links to a key in var.locations, specifying the Azure region for the VNet. |
subscription_name |
Links to a key in var.subscriptions, tying the VNet to a subscription. |
resource_group_name |
Links to a key in var.resource_groups, defining the resource group for the VNet. |
private_dns_zones |
Optional; if set, links to var.private_dns_zones. Specifies both registration and resolution DNS zones. |
lock_groups |
Optional; if set, links to keys in var.lock_groups. Specifies the resource lock groups that this VNet belongs to. |
name |
Optional; names the VNet in Azure, defaults to the map key (e.g., main) if not set. |
address_space |
Defines the VNetβs IP address range, e.g., 10.0.0.0/16. |
subnets |
A nested map of subnets, each with a name (optional, defaults to key), address_space for its IP range, and an optional security_group_name linking to var.network_security_groups to apply an NSG to the subnet. |
Terraform variable:
var.networks.peered_to
The peerings section within the networks table sets up virtual network peerings, connecting VNets within this model (var.networks) or to external networks (var.external_networks). It enables traffic flow between networks, like linking a primary and alternate VNet. In the ERD, peerings represents a many-to-many relationship between networks, or between networks and external_networks, facilitating flexible network topologies.
Important
Network peerings are a one-way connection. Each peered_to entry establishes traffic flow from the source network to the target network only. For two-way communication, you must configure reciprocal peerings in both directions (e.g., main to alt and alt to main).
networks = {
main = { # π "primary" network
# Other fields like location_name, subnets...
peered_to = [ # Multiple peerings can be declared
"alt" # π Links to var.networks
]
}
alt = { # π "alt" network
# Other fields like location_name, subnets...
peered_to = [ # Multiple peerings can be declared
"main" # π Links to var.networks
]
}
}| Field | Description |
|---|---|
peered_to |
A list of network keys from var.networks or var.external_networks to peer with. For external_networks, a valid Azure resource_id is required. |
Terraform variable:
var.networks.subnets.route_traffic
The route_traffic section is an optional map within each subnet of the networks table, defining custom routing rules for that subnet. Each route directs traffic to gateways, the Internet, appliances, or nowhere (dropped), with destinations as CIDR address spaces, networks, or networks and subnets declared in var.networks and var.external_networks. In the ERD, route_traffic is a one-to-many child of subnets, linking to networks or subnets via destined_for. A route table is created per subnet only if route_traffic is defined.
networks = {
main = { # π "main" network
# Other fields...
subnets = {
subnet_a = { # π "subnet_a" subnet
address_space = "10.0.0.0/24" # Subnet address space in CIDR format
route_traffic = { # Traffic routing rules
gateway_route = { # π "gateway_route" route
destined_for = { # When traffic is destined for...
address_space = "192.168.1.0/24" # the "192.168.1.0/24" address space...
}
to_gateway = true # route to the default network gateway
}
internet_route = { # π "internet_route" route
destined_for = { # When traffic is destined for...
network = { # Network defined in var.networks or var.external_networks...
network_name = "alt" # π linked to "alt" network in var.networks
}
}
to_internet = true # route to the Internet
}
appliance_route = { # π "appliance_route" route
destined_for = { # When traffic is destined for...
subnet = { # Subnet defined in var.networks or var.external_networks...
network_name = "alt" # π linked to "alt" network in var.networks
subnet_name = "subnet_b" # π linked to "subnet_b" subnet in var.networks.subnets
}
}
to_appliance = { # route to a virtual appliance...
ip_address = "192.168.1.1" # running at "192.168.1.1"
}
}
drop_route = { # π "drop_route" route
destined_for = { # When traffic is destined for...
address_space = "0.0.0.0/0" # the Internet (0.0.0.0/0)...
}
to_nowhere = true # drop it
}
}
}
}
}
alt = { # π "alt" network
# Other fields...
subnets = {
subnet_b = { # π "subnet_b" subnet
address_space = "10.1.0.0/24" # Subnet address space in CIDR format
}
}
}
}Important
A dedicated route table is created for each subnet with route_traffic defined. If no routes are specified, no route table is created.
| Field | Description |
|---|---|
destined_for |
Required; sets the traffic target: address_space (CIDR, e.g., 192.168.1.0/24), network (links to var.networks via network_name), or subnet (links to var.networks via network_name and subnet_name). |
route_name |
Optional; names the route, defaults to null (auto-generated). |
to_gateway |
Optional; if true, routes to a network gateway. Defaults to false. |
to_internet |
Optional; if true, routes to the Internet. Defaults to false. |
to_nowhere |
Optional; if true, drops traffic. Defaults to false. |
to_appliance |
Optional; routes to an appliance with ip_address (e.g., 192.168.1.1). Defaults to null. |
Terraform variable:
var.external_networks
The external_networks table captures networks outside this model, unlike those defined in var.networks. These can be on-premises, in Azure, or in another cloud, allowing your infrastructure to interact with them via routing, security rules, or peering. By specifying their address spaces and subnets, you can reference them in var.networks configurations. For Azure-based external networks, including a resource_id enables one-way peering from var.networks, provided you have sufficient permissions. In the ERD, external_networks links many-to-many with networks through peered_to, route_traffic, and security_rules, with subnets as a one-to-many child.
external_networks = {
on_prem_network = { # π "on_prem_network" external network
address_space = "10.10.0.0/16" # External network address space can be used for
# configuring routes and security rules
subnets = {
on_prem_database = { # π "on_prem_database" external subnet
name = "DatabaseSubnet"
address_space = "10.10.0.0/24" # External subnet address space can be used for
} # configuring routes and security rules
}
}
external_azure_network = { # π "external_azure_network" external network
address_space = "10.20.0.0/16" # External network address space can be used for
# configuring routes and security rules
resource_id = "/subscriptions/12345678..." # External Azure network resource ID enables seamless
# var.networks to var.external_networks peering
subnets = {
external_service = { # π "external_service" subnet
name = "ServiceSubnet"
address_space = "10.20.0.0/24" # External subnet address space can be used for
} # configuring routes and security rules
}
}
}| Field | Description |
|---|---|
address_space |
Required; defines the external networkβs IP range, e.g., 10.10.0.0/16, used in routes and security rules. |
resource_id |
Optional; Azure resource ID for peering from var.networks, e.g., /subscriptions/12345678.... Requires permissions. Defaults to null. |
subnets |
Optional; maps subnets with name (e.g., DatabaseSubnet) and address_space (e.g., 10.10.0.0/24) for detailed routing and security configs. Defaults to {}. |
Terraform variable:
var.virtual_machine_sets
The virtual_machine_sets table configures groups of highly available VMs that share the same role, workload, and availability settings. By default, VMs are spread evenly across Azure availability zones, with custom distribution possible via var.virtual_machine_set_zone_distribution. Related specs like VM count, SKU, and disks are defined in var.virtual_machine_set_specs, maintaining a 1:1 link with virtual_machine_sets and virtual_machine_set_zone_distribution to streamline automation. In the ERD, virtual_machine_sets connects one-to-one with subscriptions, resource_groups, locations, and key_vaults, and one-to-many with nested extensions and data_disks.
virtual_machine_sets = {
database = { # π "database" VM set
key_vault_name = "primary" # π Links to var.key_vaults
location_name = "primary" # π Links to var.locations
resource_group_name = "production" # π Links to var.resource_groups
subscription_name = "production" # π Links to var.subscriptions
shutdown_schedule_name = "evening_shutdown" # π Optional; links to var.virtual_machine_shutdown_schedules
scale_set_name = "shared_vmss" # π Optional; links to var.virtual_machine_scale_sets
name = "db" # Prefix for all VMs in this set
include_deployment_prefix_in_name = true # Apply var.deployment_prefix? Default: false
tags = {
role = "database" # Optional; tags all VMs
}
extensions = [ # Optional
"azure_monitor" # π Links to var.virtual_machine_extensions
]
lock_groups = [ # Optional
"production_lock" # π Links to var.lock_groups
]
maintenance = { # Optional
schedule_name = "guest_updates" # π Optional; links to var.maintenance_schedules
}
os_type = "Windows" # Windows or Linux
os_disk_encryption_set_id = "/subscriptions/12345678..." # Optional; CMK encryption for the OS disk
disk_controller_type = "nvme" # Optional; SCSI or NVMe based on SKU
enable_boot_diagnostics = true # Enable boot diagnostics? Default: false
}
}| Field | Description |
|---|---|
key_vault_name |
Links to a key in var.key_vaults, specifying the key vault for the VM set. |
location_name |
Links to a key in var.locations, setting the Azure region for the VMs. |
resource_group_name |
Links to a key in var.resource_groups, defining the resource group for the VMs. |
subscription_name |
Links to a key in var.subscriptions, tying the VMs to a subscription. |
load_balancer |
Optional; if set, provisions an Azure Load Balancer for the VM set. See Virtual Machine Set Load Balancer for full configuration details. Defaults to null (no load balancer.) |
lock_groups |
Optional; if set, links to keys in var.lock_groups. Specifies the resource lock groups that this VM set belongs to. By default, all child resources including disks and network interfaces inherit these lock groups. |
maintenance.schedule_name |
Optional; if set, links to keys in var.maintenance_schedules. Specifies the maintenance schedule that should be used when applying guest updates for the VMs. |
shutdown_schedule_name |
Optional; if set, links to keys in var.virtual_machine_shutdown_schedules. Applies a shutdown schedule to the VM set. |
scale_set_name |
Optional; if set, links to a key in var.virtual_machine_scale_sets. Allows multiple VM sets to share a single VM Scale Set. If omitted, a dedicated VM Scale Set is automatically created for this VM set. |
name |
Prefixes all VMs in the set, used in their Azure names. |
include_deployment_prefix_in_name |
If true, prepends var.deployment_prefix to resource names. Default: false. |
tags |
Optional; applies key-value tags to all VMs, e.g., role: database. |
extensions |
Optional; lists extensions from var.virtual_machine_extensions to apply. |
os_type |
Specifies the OS: Windows or Linux. |
os_disk_encryption_set_id |
Optional; specifies a disk encryption set ID (e.g., /subscriptions/12345678...) used to encrypt the OS disk with a customer-managed key (CMK). Defaults to null. |
disk_controller_type |
Optional; sets disk controller to SCSI or NVMe based on VM SKU. |
enable_boot_diagnostics |
If true, enables boot diagnostics. Default: false. |
Tip
Lock groups can be overridden on VM set child resources. See data disk groups and network interfaces for more information.
Note
If a virtual_machine_set does not specify a scale_set_name, a dedicated VM Scale Set is automatically created for it. Use virtual_machine_scale_sets only when you need multiple VM sets to share the same scale set.
Terraform variable:
var.virtual_machine_sets.image
The image section within virtual_machine_sets selects the OS image for VMs, ensuring consistency and compliance. It can reference a custom/shared image by ID or an Azure Marketplace image by details like offer and publisher. In the ERD, image is a child of virtual_machine_sets, with a one-to-one relationship.
virtual_machine_sets = {
database = { # π "database" VM set
# Other fields...
image = {
reference = {
offer = "UbuntuServer" # Image offer name
publisher = "Canonical" # Image publisher
sku = "18.04-LTS" # Image edition
version = "latest" # Image version
}
}
}
}
# Or, for a custom image:
# image = {
# id = "/subscriptions/12345678..." # Resource ID of custom/shared image
# }| Field | Description |
|---|---|
id |
Optional; resource ID for a custom or shared image, e.g., /subscriptions/12345678.... |
reference |
Optional; defines a Marketplace image with offer, publisher, sku, and version. |
Terraform variable:
var.virtual_machine_sets.data_disk_groups
The data_disk_groups section within virtual_machine_sets configures groups of data disks attached to VMs in a set, enabling scenarios like disk striping for high-performance workloads (e.g., SQL Server). Each group defines shared properties such as caching, encryption, and source images, with disks assigned contiguous Logical Unit Numbers (LUNs) for consistent attachment order. In the ERD, data_disk_groups is a one-to-many child of virtual_machine_sets, linking to key_vaults for encryption and lock_groups for resource protection. The number of disks and their sizes are specified in var.virtual_machine_set_specs.data_disk_groups, ensuring a one-to-one key alignment between the two tables.
virtual_machine_sets = {
database = { # π "database" VM set
# Other fields...
data_disk_groups = {
data = { # π "data" disk group
caching = "ReadOnly" # ReadOnly caching for performance
enable_public_network_access = false # Disable public access
disk_encryption_set_id = "/subscriptions/12345678..." # Optional; encryption set ID
image = { # Optional; disk source
copy = { # Copy from an existing managed disk
resource_id = "/subscriptions/12345678/resourceGroups/rg/providers/Microsoft.Compute/disks/source-disk"
}
}
lock_groups = [ # Optional; overrides parent VM set lock groups
"data_disk_lock" # π Links to var.lock_groups
]
}
logs = { # π "logs" disk group
caching = "ReadWrite" # ReadWrite caching
enable_public_network_access = false # Disable public access
}
}
}
}| Field | Description |
|---|---|
caching |
Optional; configures caching: None, ReadOnly, or ReadWrite. Defaults to ReadWrite. Optimizes performance for workloads like SQL Server striping. |
disk_encryption_set_id |
Optional; specifies a disk encryption set ID (e.g., /subscriptions/12345678...) from Azure Key Vault for encryption. Defaults to null. |
enable_public_network_access |
Optional; if true, allows public access to disks in the group for specific use cases. Defaults to false for security. |
image |
Optional; defines the disk groupβs source: copy (from a disk/snapshot), import (from a VHD), platform (from a Marketplace image), restore (from a backup/snapshot), or null (empty disks). Defaults to null. |
lock_groups |
Optional; links to keys in var.lock_groups. Specifies lock groups for the disk group, overriding those defined in the parent virtual_machine_sets. Defaults to []. |
Note
Each disk group is assigned contiguous LUNs automatically, starting from the lowest available LUN for the VM set. For example, if the data group has 3 disks and logs has 2, LUNs might be assigned as 0β2 for data and 3β4 for logs. This supports striping configurations for high-performance workloads.
The image field in data_disk_groups specifies the source for disks in the group, supporting various scenarios like copying existing disks, importing VHDs, using Marketplace images, or restoring from backups. Below are examples for each option, using the same fluent syntax as the network_security_rules section.
This configuration copies disks from an existing Azure managed disk or snapshot, useful for replicating pre-configured disk setups.
virtual_machine_sets = {
database = { # π "database" VM set
# Other fields...
data_disk_groups = {
data = { # π "data" disk group
caching = "ReadOnly" # Optimize for read-heavy workloads
image = {
copy = { # Copy from an existing managed disk
resource_id = "/subscriptions/12345678/resourceGroups/rg/providers/Microsoft.Compute/disks/source-disk"
}
}
}
}
}
}This configuration imports disks from a VHD file stored in Azure Blob Storage, ideal for migrating existing disk images.
virtual_machine_sets = {
database = { # π "database" VM set
# Other fields...
data_disk_groups = {
data = { # π "data" disk group
caching = "ReadWrite" # Enable read/write caching
image = {
import = { # Import from a VHD
uri = "https://storage.blob.core.windows.net/vhds/sample.vhd"
secure = true # Perform secure import
}
}
}
}
}
}This configuration uses a platform image from the Azure Marketplace, suitable for standardized disk setups.
virtual_machine_sets = {
database = { # π "database" VM set
# Other fields...
data_disk_groups = {
data = { # π "data" disk group
caching = "ReadOnly" # Optimize for read-heavy workloads
image = {
platform = { # Use a platform image
image_reference_id = "/subscriptions/12345678/resourceGroups/rg/providers/Microsoft.Compute/images/ubuntu-18.04"
}
}
}
}
}
}This configuration restores disks from an Azure Backup snapshot, useful for disaster recovery scenarios.
virtual_machine_sets = {
database = { # π "database" VM set
# Other fields...
data_disk_groups = {
data = { # π "data" disk group
caching = "ReadWrite" # Enable read/write caching
image = {
restore = { # Restore from a backup
resource_id = "/subscriptions/12345678/resourceGroups/rg/providers/Microsoft.Compute/snapshots/backup-snapshot"
}
}
}
}
}
}This configuration creates empty disks, ideal for initializing new storage without pre-existing data.
virtual_machine_sets = {
database = { # π "database" VM set
# Other fields...
data_disk_groups = {
data = { # π "data" disk group
caching = "ReadWrite" # Enable read/write caching
}
}
}
}Terraform variable:
var.virtual_machine_sets.network_interfaces
The network_interfaces section within virtual_machine_sets configures the network connectivity for VMs, linking them to specific VNets and subnets. Each interface specifies a network, subnet, and IP settings, with options for accelerated networking. In the ERD, network_interfaces is a one-to-many child of virtual_machine_sets, with one-to-one links to networks and subnets via network_name and subnet_name, ensuring each VM set connects to the right network topology.
Important
Only one network interface per VM can have accelerated networking enabled (enable_accelerated_networking = true). By default, this feature is enabled. If the VM has multiple network interfaces, you must explicitly indicate which network interfaces should not have accelerated networking enabled (enable_accelerated_networking = false).
virtual_machine_sets = {
database = { # π "database" VM set
# Other fields...
network_interfaces = {
primary_nic = { # π "primary_nic" network interface
network_name = "main" # π Links to var.networks
subnet_name = "subnet_a" # π Links to var.networks.main.subnets
private_ip = "10.0.0.10" # Optional; static IP
private_ip_allocation = "Static" # Optional; static or dynamic
enable_accelerated_networking = true # Optional; boost network performance.
# See __Important__ accelerated networking note above.
lock_groups = [ # Optional; overrides lock groups defined on parent VM set
"nic_lock" # π Links to var.lock_groups
]
}
}
}
}| Field | Description |
|---|---|
network_name |
Required; links to a key in var.networks, specifying the VNet for the interface. |
subnet_name |
Required; links to a subnet key within the specified network_name in var.networks. |
lock_groups |
Optional; if set, links to keys in var.lock_groups. Specifies the resource lock groups that this network interface belongs to. These lock groups override lock groups defined at the parent VM set level. |
private_ip |
Optional; sets a static private IP address, e.g., 10.0.0.10. Defaults to null for dynamic allocation. |
private_ip_allocation |
Optional; defines IP assignment: Static or Dynamic. Defaults to Dynamic. |
enable_accelerated_networking |
Optional; if true, enables accelerated networking for better performance. Defaults to true. |
Terraform variable:
var.virtual_machine_sets.load_balancer
The load_balancer section within virtual_machine_sets provisions an Azure Load Balancer for the VM set, distributing inbound traffic across all VMs in the set. It supports both internal (private) and public frontends, a health probe, and one or more load-balancing rules. Port names in the health probe and rules reference entries in var.network_ports, keeping port definitions consistent across your model.
Important
Exactly one of internal_frontend or public_frontend must be set per load balancer.
An internal load balancer distributes traffic within a VNet, using a private IP on a specified subnet as its frontend.
network_ports = {
https = "443" # π "https" port
}
virtual_machine_sets = {
app = { # π "app" VM set
# Other fields...
load_balancer = {
nic_name = "primary_nic" # π Links to a key in network_interfaces (below)
sku = "Standard" # Optional; Standard (default) or Basic
internal_frontend = { # Private frontend on a VNet subnet
network_name = "main" # π Links to var.networks
subnet_name = "app_subnet" # π Links to var.networks.main.subnets
private_ip_address = "10.0.0.100" # Optional; static private IP. Dynamic if unset.
}
health_probe = {
protocol = "Tcp" # Tcp, Http, or Https
port_name = "https" # π Links to var.network_ports
interval_in_seconds = 15 # Optional; seconds between probes
probe_threshold = 2 # Optional; consecutive failures before unhealthy
}
rules = {
https = { # π "https" load-balancing rule
protocol = "Tcp" # Tcp or Udp
frontend_port_name = "https" # π Links to var.network_ports
backend_port_name = "https" # π Links to var.network_ports
}
}
}
network_interfaces = {
primary_nic = { # π "primary_nic" β referenced by nic_name above
network_name = "main" # π Links to var.networks
subnet_name = "app_subnet" # π Links to var.networks.main.subnets
}
}
}
}A public load balancer exposes the VM set to the internet via a public IP address.
network_ports = {
https = "443" # π "https" port
}
virtual_machine_sets = {
web = { # π "web" VM set
# Other fields...
load_balancer = {
nic_name = "primary_nic" # π Links to a key in network_interfaces (below)
public_frontend = { # Public IP frontend
public_ip_name = "web-pip" # Optional; name for the public IP resource
public_ip_zones = ["1", "2", "3"] # Optional; availability zones for the public IP
idle_timeout_in_minutes = 4 # Optional; idle connection timeout in minutes
ddos_protection_mode = "VirtualNetworkInherited" # Optional; DDoS protection mode
}
health_probe = {
protocol = "Https" # Tcp, Http, or Https
port_name = "https" # π Links to var.network_ports
request_path = "/health" # Optional; required for Http/Https probes
}
rules = {
https = { # π "https" load-balancing rule
protocol = "Tcp"
frontend_port_name = "https" # π Links to var.network_ports
backend_port_name = "https" # π Links to var.network_ports
enable_floating_ip = false # Optional; enable for SQL AlwaysOn, etc.
}
}
}
network_interfaces = {
primary_nic = { # π "primary_nic" β referenced by nic_name above
network_name = "main" # π Links to var.networks
subnet_name = "web_subnet" # π Links to var.networks.main.subnets
}
}
}
}| Field | Description |
|---|---|
nic_name |
Required; links to a key in network_interfaces within this VM set. Specifies which NIC the load balancer backend pool attaches to. |
sku |
Optional; sets the load balancer SKU: Standard or Basic. Defaults to Standard. |
tags |
Optional; applies key-value tags to the load balancer resource. Defaults to {}. |
internal_frontend |
Optional; configures a private frontend. Requires network_name (links to var.networks) and subnet_name (links to a subnet within that network). private_ip_address is optional; defaults to dynamic allocation if unset. |
public_frontend |
Optional; configures a public IP frontend. public_ip_name (optional), public_ip_zones (optional; defaults to ["1", "2", "3"]), idle_timeout_in_minutes (optional; defaults to 4), and ddos_protection_mode (optional; defaults to VirtualNetworkInherited). |
health_probe.protocol |
Required; the probe protocol: Tcp, Http, or Https. |
health_probe.port_name |
Required; links to a key in var.network_ports, specifying the port to probe. |
health_probe.interval_in_seconds |
Optional; seconds between probes. Defaults to 15. |
health_probe.probe_threshold |
Optional; consecutive failures before a VM is marked unhealthy. Defaults to 2. |
health_probe.request_path |
Optional; the HTTP/HTTPS path to probe, e.g., /health. Required when protocol is Http or Https. |
rules |
Required; a map of load-balancing rules. Each rule requires protocol (Tcp or Udp), frontend_port_name (links to var.network_ports), and backend_port_name (links to var.network_ports). |
rules.idle_timeout_in_minutes |
Optional; idle connection timeout per rule. Defaults to 4. |
rules.enable_floating_ip |
Optional; enables floating IP (Direct Server Return) for the rule. Required for scenarios like SQL Server AlwaysOn Availability Groups. Defaults to false. |
Note
Port names in health_probe.port_name, rules.frontend_port_name, and rules.backend_port_name all link to var.network_ports. This keeps port numbers defined in one place and reused consistently across security rules, health probes, and load-balancing rules.
Terraform variable:
var.virtual_machine_set_specs
The virtual_machine_set_specs table defines the sizing and storage specs for each VM set in virtual_machine_sets, linked one-to-one by a shared key. It pairs with virtual_machine_sets and virtual_machine_set_zone_distribution (for custom zone adjustments) to complete the VM setup. In the ERD, virtual_machine_set_specs connects one-to-one with virtual_machine_sets, anchoring compute and storage details.
virtual_machine_set_specs = {
database = { # π "database" VM set
vm_count = 3 # There are 3 VMs in this set
sku_size = "Standard_D4ads_v5" # All VMs are size Standard_D4ads_v5
os_disk = {
disk_size_gb = 128 # OS disk is 128 GiB
storage_account_type = "Premium_LRS" # Can be Standard_LRS, Premium_LRS, StandardSSD_ZRS, or Premium_ZRS
}
}
}| Field | Description |
|---|---|
vm_count |
Optional; sets the number of VMs in the set, e.g., 3. Defaults to 2. |
sku_size |
Required; specifies the VM SKU, e.g., Standard_D4ads_v5, defining compute power. |
os_disk |
Required; configures the OS disk with disk_size_gb (e.g., 128) and storage_account_type (e.g., Premium_LRS, defaults to PremiumV2_LRS). |
Terraform variable:
var.virtual_machine_set_specs.data_disk_groups
The data_disk_groups subsection within virtual_machine_set_specs defines the sizing and storage specifications for data disk groups in virtual_machine_sets.data_disk_groups. Each group specifies the number of disks, their size, and storage type, with optional IOPS settings for performance tuning. Keys must match those in var.virtual_machine_sets.data_disk_groups for a one-to-one relationship. In the ERD, data_disk_groups is a one-to-many child of virtual_machine_set_specs, ensuring consistent disk configurations across VM sets.
virtual_machine_set_specs = {
database = { # π "database" VM set
# Other fields...
data_disk_groups = {
data = { # π "data" disk group
disk_count = 3 # 3 disks in the group
disk_size_gb = 128 # Each disk is 128 GiB
storage_account_type = "Premium_LRS" # Premium locally redundant storage
disk_iops_read_write = 5000 # 5000 IOPS for read/write operations
}
logs = { # π "logs" disk group
disk_count = 2 # 2 disks in the group
disk_size_gb = 256 # Each disk is 256 GiB
storage_account_type = "Premium_LRS" # Premium locally redundant storage
disk_iops_read_only = 3000 # 3000 IOPS for read-only operations
}
}
}
}| Field | Description |
|---|---|
disk_count |
Optional; specifies the number of disks in the group, e.g., 3. Defaults to 1. Useful for striping scenarios like SQL Server. |
disk_size_gb |
Required; sets the size of each disk in the group in gigabytes, e.g., 128. |
storage_account_type |
Optional; specifies the storage type: Standard_LRS, StandardSSD_ZRS, Premium_LRS, PremiumV2_LRS, StandardSSD_LRS, or UltraSSD_LRS. Defaults to PremiumV2_LRS. |
disk_iops_read_write |
Optional; sets IOPS for read/write operations, e.g., 5000. Defaults to null (provider default). |
disk_iops_read_only |
Optional; sets IOPS for read-only operations, e.g., 3000. Defaults to null (provider default). |
Important
Ensure the disk_count aligns with workload requirements, as increasing the number of disks in a group can enhance performance for striped configurations but may increase costs. Verify that storage_account_type supports the chosen IOPS settings, as some types (e.g., UltraSSD_LRS) are required for high IOPS.
Terraform variable:
var.virtual_machine_scale_sets
The virtual_machine_scale_sets table defines named Azure Virtual Machine Scale Sets (Flexible orchestration) that can be shared across multiple virtual_machine_sets. By default, each virtual_machine_set automatically gets its own dedicated VM Scale Set β no entry in this table is required for that behavior. Defining an entry here and referencing it via scale_set_name on one or more virtual_machine_sets allows those VM sets to share the same underlying scale set.
virtual_machine_scale_sets = {
shared_vmss = { # π "shared_vmss" scale set
location_name = "primary" # π Links to var.locations
resource_group_name = "production" # π Links to var.resource_groups
name = "shared-vmss" # Optional; custom name in Azure
include_deployment_prefix_in_name = true # Apply var.deployment_prefix? Default: true
tags = {
purpose = "shared" # Optional; tags the scale set
}
}
}
# Reference the shared scale set from one or more virtual_machine_sets:
virtual_machine_sets = {
app = { # π "app" VM set
# Other fields...
scale_set_name = "shared_vmss" # π Links to var.virtual_machine_scale_sets
}
worker = { # π "worker" VM set
# Other fields...
scale_set_name = "shared_vmss" # π Links to var.virtual_machine_scale_sets
}
}| Field | Description |
|---|---|
location_name |
Links to a key in var.locations, specifying the Azure region for the scale set. |
resource_group_name |
Links to a key in var.resource_groups, defining the resource group for the scale set. |
name |
Optional; custom name for the scale set in Azure. Defaults to an auto-generated name based on the map key if not set. |
include_deployment_prefix_in_name |
If true, prepends var.deployment_prefix to the scale set name. Default: true. |
tags |
Optional; applies key-value tags to the scale set. Defaults to {}. |
Note
If a virtual_machine_set does not specify a scale_set_name, a dedicated VM Scale Set is automatically created for it. Use virtual_machine_scale_sets only when you need multiple VM sets to share the same scale set.
Terraform variable:
var.virtual_machine_set_zone_distribution
The virtual_machine_set_zone_distribution table adjusts the placement of VMs from virtual_machine_sets across Azure availability zones, overriding the default even distribution (across all three zones) set by infra_map_vm_set. It shares a one-to-one relationship with virtual_machine_sets and virtual_machine_set_specs via a common key, used only when custom zone allocations are needed, like for capacity constraints. In the ERD, virtual_machine_set_zone_distribution links one-to-one with virtual_machine_sets, tailoring zonal deployment for each set.
Note
If no zone distribution is configured for a VM set defined in var.virtual_machine_sets, VMs in that set will be distributed evenly across all three availability zones.
virtual_machine_set_zone_distribution = {
primary_bca_web = { # π Links to var.virtual_machine_sets
custom = { # Custom distribution
"1" = 2 # 2 VMs in zone 1
"2" = 8 # 8 VMs in zone 2
}
}
database = { # π Links to var.virtual_machine_sets
even = [ # Distribute VMs evenly across zones 1 and 3
"1",
"3"
]
}
}| Field | Description |
|---|---|
custom |
Optional; maps zone numbers (e.g., "1", "2") to specific VM counts (e.g., 2, 8) for targeted distribution. Defaults to null. |
even |
Optional; lists zones (e.g., ["1", "3"]) for even VM distribution across those zones. Defaults to null. If both custom and even are null, VMs spread evenly across all zones. |
Terraform variable:
var.storage_accounts
The storage_accounts table configures Azure storage accounts to store data such as blobs and files. Each account specifies its location, resource group, and subscription, with options for access tiers and replication. In the ERD, storage_accounts links one-to-one with subscriptions, locations, and resource_groups, and one-to-many with blob_containers and file_shares.
storage_accounts = {
files = { # π Primary key: "files"
location_name = "primary" # π Links to var.locations
resource_group_name = "shared" # π Links to var.resource_groups
subscription_name = "primary" # π Links to var.subscriptions
name = "appfiles"
replication_type = "RAGRS"
}
}| Field | Description |
|---|---|
location_name |
Required; links to a key in var.locations, setting the storage accountβs Azure region. |
resource_group_name |
Required; links to a key in var.resource_groups, defining the storage accountβs resource group. |
subscription_name |
Required; links to a key in var.subscriptions, tying the storage account to a subscription. |
name |
Optional; names the storage account, e.g., appfiles. Defaults to null (auto-generated if unset). |
access_tier |
Optional; sets the access tier: Hot or Cool. Defaults to Hot. |
account_tier |
Optional; sets the performance tier: Standard or Premium. Defaults to Standard. |
account_type |
Optional; specifies the account kind: StorageV2, Storage, BlobStorage, or FileStorage. Defaults to StorageV2. |
replication_type |
Optional; sets data replication: LRS, GRS, RAGRS, ZRS, GZRS, and RAGZRS. Defaults to ZRS. |
allow_http_access |
Optional; if true, enables HTTP access. Defaults to false for security. |
include_deployment_prefix_in_name |
Optional; if true, prepends a deployment prefix to the name. Defaults to true. |
lock_groups |
Optional; lists lock groups for resource protection, e.g., ["main_lock"]. Defaults to []. |
tags |
Optional; applies key-value tags, e.g., { environment = "production" }. Defaults to {}. |
Warning
We strongly recommend that you allow storage account HTTPS access only (allow_http_access = false). This is the default.
Terraform variable:
var.blob_containers
The blob_containers table configures Azure Blob Storage containers within storage accounts to store unstructured data like files or backups. Each container specifies its storage account and name, with an option for public access. In the ERD, blob_containers links one-to-one with storage_accounts via storage_account_name.
blob_containers = {
uploaded_files = { # π Primary key: "uploaded_files"
storage_account_name = "files" # π Links to var.storage_accounts
name = "uploaded-files"
}
}| Field | Description |
|---|---|
storage_account_name |
Required; links to a key in var.storage_accounts, specifying the storage account for the container. |
name |
Required; names the blob container, e.g., uploaded-files. |
enable_public_network_access |
Optional; if true, allows public access to the container. Defaults to false for security. |
Terraform variable:
var.file_shares
The file_shares table configures Azure File Shares within storage accounts for shared file storage accessible via SMB or NFS protocols. Each share specifies its storage account, name, and storage quota, with options for access tier and protocol. In the ERD, file_shares links one-to-one with storage_accounts via storage_account_name.
file_shares = {
uploaded_files = { # π Primary key: "uploaded_files"
storage_account_name = "files" # π Links to var.storage_accounts
name = "uploaded-files"
quota_gb = 1
}
}| Field | Description |
|---|---|
storage_account_name |
Required; links to a key in var.storage_accounts, specifying the storage account for the file share. |
name |
Required; names the file share, e.g., uploaded-files. |
quota_gb |
Required; sets the storage limit in gigabytes, e.g., 1. |
access_tier |
Optional; sets the access tier: Hot, Cool, or TransactionOptimized. Defaults to Hot. |
protocol |
Optional; specifies the access protocol: SMB or NFS. Defaults to SMB. |
Terraform variable:
var.key_vaults
The key_vaults table configures Azure Key Vaults for secure storage of secrets, keys, and certificates, requiring a location, subscription, and resource group as its foundation. Commonly used optional fields like SKU, tags, and network ACLs enhance its setup.
key_vaults = {
primary = { # π "primary" key vault
location_name = "primary" # π Links to var.locations
subscription_name = "main" # π Links to var.subscriptions
resource_group_name = "main_key_vaults" # π Links to var.resource_groups
sku_name = "standard" # Optional; standard or premium
lock_groups = [ # Optional
"production_lock" # π Links to var.lock_groups
]
tags = {
env = "production" # Optional; custom tags
}
network_acls = {
bypass = "AzureServices" # Optional; allow Azure services
default_action = "Allow" # Optional; default access rule
}
}
alt = { # π "alt" key vault
location_name = "alt" # π Links to var.locations
subscription_name = "main" # π Links to var.subscriptions
resource_group_name = "main_key_vaults" # π Links to var.resource_groups
sku_name = "standard" # Optional; standard or premium
lock_groups = [ # Optional
"non_production_lock" # π Links to var.lock_groups
]
tags = {
env = "production" # Optional; custom tags
}
network_acls = {
bypass = "AzureServices" # Optional; allow Azure services
default_action = "Allow" # Optional; default access rule
}
}
}| Field | Description |
|---|---|
location_name |
Required; links to a key in var.locations, setting the vaultβs Azure region. |
subscription_name |
Required; links to a key in var.subscriptions, tying the vault to a subscription. |
resource_group_name |
Required; links to a key in var.resource_groups, defining the vaultβs resource group. |
lock_groups |
Optional; if set, links to keys in var.lock_groups. Specifies the resource lock groups that the vault belongs to. |
sku_name |
Optional; sets the vault SKU: standard or premium. Defaults to standard. |
tags |
Optional; applies key-value tags, e.g., env: production. Defaults to {}. |
network_acls |
Optional; configures network access with bypass (e.g., AzureServices) and default_action (e.g., Allow). Defaults to {}. |
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.