Managing Azure NAT Gateway with Terraform
Learn how to set up and manage Azure NAT Gateway using Terraform, including outbound connectivity and IP configuration
Managing Azure NAT Gateway with Terraform
Azure NAT Gateway provides outbound internet connectivity for resources in your virtual network. This guide demonstrates how to set up and manage NAT Gateway using Terraform.
Video Tutorial
Learn more about managing Azure NAT Gateway with Terraform in this comprehensive video tutorial:
Prerequisites
- Azure CLI configured with appropriate permissions
- Terraform installed (version 1.0.0 or later)
- Resource group created
- Understanding of networking concepts
Project Structure
terraform-azure-natgateway/
├── main.tf
├── variables.tf
├── outputs.tf
├── modules/
│ └── natgateway/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── configs/
└── settings.json
NAT Gateway Configuration
Create modules/natgateway/main.tf
:
# Public IP Prefix
resource "azurerm_public_ip_prefix" "main" {
name = "${var.project_name}-pip-prefix"
location = var.location
resource_group_name = var.resource_group_name
prefix_length = 30
zones = ["1", "2", "3"]
tags = var.tags
}
# Public IP
resource "azurerm_public_ip" "main" {
name = "${var.project_name}-pip"
location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Static"
sku = "Standard"
zones = ["1", "2", "3"]
tags = var.tags
}
# NAT Gateway
resource "azurerm_nat_gateway" "main" {
name = "${var.project_name}-natgw"
location = var.location
resource_group_name = var.resource_group_name
sku_name = "Standard"
idle_timeout_in_minutes = 10
zones = ["1", "2", "3"]
tags = var.tags
}
# NAT Gateway Public IP Association
resource "azurerm_nat_gateway_public_ip_association" "main" {
nat_gateway_id = azurerm_nat_gateway.main.id
public_ip_address_id = azurerm_public_ip.main.id
}
# NAT Gateway Public IP Prefix Association
resource "azurerm_nat_gateway_public_ip_prefix_association" "main" {
nat_gateway_id = azurerm_nat_gateway.main.id
public_ip_prefix_id = azurerm_public_ip_prefix.main.id
}
# Virtual Network
resource "azurerm_virtual_network" "main" {
name = "${var.project_name}-vnet"
address_space = ["10.0.0.0/16"]
location = var.location
resource_group_name = var.resource_group_name
tags = var.tags
}
# Subnet
resource "azurerm_subnet" "main" {
name = "workload-subnet"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.0.1.0/24"]
}
# NAT Gateway Subnet Association
resource "azurerm_subnet_nat_gateway_association" "main" {
subnet_id = azurerm_subnet.main.id
nat_gateway_id = azurerm_nat_gateway.main.id
}
# Network Security Group
resource "azurerm_network_security_group" "main" {
name = "${var.project_name}-nsg"
location = var.location
resource_group_name = var.resource_group_name
security_rule {
name = "AllowHTTPSOutbound"
priority = 100
direction = "Outbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = "*"
destination_address_prefix = "Internet"
}
security_rule {
name = "DenyAllInbound"
priority = 4096
direction = "Inbound"
access = "Deny"
protocol = "*"
source_port_range = "*"
destination_port_range = "*"
source_address_prefix = "*"
destination_address_prefix = "*"
}
tags = var.tags
}
# NSG Association
resource "azurerm_subnet_network_security_group_association" "main" {
subnet_id = azurerm_subnet.main.id
network_security_group_id = azurerm_network_security_group.main.id
}
# Route Table
resource "azurerm_route_table" "main" {
name = "${var.project_name}-rt"
location = var.location
resource_group_name = var.resource_group_name
route {
name = "ToInternet"
address_prefix = "0.0.0.0/0"
next_hop_type = "Internet"
}
tags = var.tags
}
# Route Table Association
resource "azurerm_subnet_route_table_association" "main" {
subnet_id = azurerm_subnet.main.id
route_table_id = azurerm_route_table.main.id
}
# Example VM Scale Set using NAT Gateway
resource "azurerm_linux_virtual_machine_scale_set" "main" {
name = "${var.project_name}-vmss"
resource_group_name = var.resource_group_name
location = var.location
sku = "Standard_B2s"
instances = 2
admin_username = "adminuser"
admin_ssh_key {
username = "adminuser"
public_key = file("~/.ssh/id_rsa.pub")
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
network_interface {
name = "nic"
primary = true
ip_configuration {
name = "internal"
primary = true
subnet_id = azurerm_subnet.main.id
}
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
tags = var.tags
}
## Monitoring Configuration
1. **Diagnostic Settings**
```hcl
resource "azurerm_monitor_diagnostic_setting" "natgateway" {
name = "${var.project_name}-diag"
target_resource_id = azurerm_nat_gateway.main.id
log_analytics_workspace_id = var.log_analytics_workspace_id
metric {
category = "AllMetrics"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
}
# NAT Gateway Alerts
resource "azurerm_monitor_metric_alert" "snat_connections" {
name = "${var.project_name}-snat-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_nat_gateway.main.id]
description = "Alert when SNAT connections are high"
criteria {
metric_namespace = "Microsoft.Network/natGateways"
metric_name = "TotalConnectionCount"
aggregation = "Average"
operator = "GreaterThan"
threshold = 50000
}
action {
action_group_id = var.action_group_id
}
}
resource "azurerm_monitor_metric_alert" "dropped_packets" {
name = "${var.project_name}-dropped-packets-alert"
resource_group_name = var.resource_group_name
scopes = [azurerm_nat_gateway.main.id]
description = "Alert when packets are being dropped"
criteria {
metric_namespace = "Microsoft.Network/natGateways"
metric_name = "DroppedPackets"
aggregation = "Total"
operator = "GreaterThan"
threshold = 1000
}
action {
action_group_id = var.action_group_id
}
}
Flow Logs Configuration
- Network Watcher and Flow Logs
resource "azurerm_network_watcher_flow_log" "natgateway" {
network_watcher_name = var.network_watcher_name
resource_group_name = var.resource_group_name
network_security_group_id = azurerm_network_security_group.main.id
storage_account_id = var.storage_account_id
enabled = true
retention_policy {
enabled = true
days = 30
}
traffic_analytics {
enabled = true
workspace_id = var.log_analytics_workspace_id
workspace_region = var.location
workspace_resource_id = var.log_analytics_workspace_resource_id
interval_in_minutes = 10
}
}
Best Practices
-
Performance
- Size appropriately
- Monitor connections
- Configure timeouts
- Use zones
-
High Availability
- Use multiple zones
- Configure failover
- Monitor health
- Scale resources
-
Security
- Configure NSGs
- Enable logging
- Monitor traffic
- Review policies
-
Cost Optimization
- Monitor usage
- Right-size gateway
- Optimize IPs
- Review metrics
Conclusion
You’ve learned how to set up and manage Azure NAT Gateway using Terraform. This setup provides:
- Outbound connectivity
- IP management
- Traffic monitoring
- High availability
Remember to:
- Monitor connections
- Review configurations
- Update policies
- Maintain performance