AWS with Terraform Tutorial: AWS NAT Gateway (7)

How to Create, and Manage AWS NAT Gateway with Terraform

How to configure and use the Terraform aws_nat_gateway and aws_eip resource blocks to create and manage AWS NAT Gateway and its corresponding Public IPs inside each availability zone to enable Internet access from instances in private subnets.

Welcome to our tutorial series where we dive into cloud infrastructure deployment using Terraform or OpenTofu on AWS. In this series, the fundamentals are shown, guiding you through the process of minimizing resource usage and simplifying the deployment complexities associated with cloud infrastructure. This tutorial series is a work in progress.

This comprehensive OpenTofu and Terraform tutorial guides you step-by-step through creating infrastructure in AWS using Terraform.

Terraform Basics, AWS Basics, Terraform AWS Provider, AWS VPC, AWS Subnets, AWS Internet Gateway, AWS NAT Gateway, AWS Routing Tables, AWS Security Groups, AWS Key Pairs, AWS AMIs, AWS EC2 Instances, AWS RDS, AWS Route 53 (DNS), AWS Auto Scaling, AWS Load Balancers, Terraform AWS & Ansible, Terraform Modules, Terraform Backends, Terraform Tools, Terraform CI/CD.

Infrastructure as Code (IaC) helps maintain consistency, enables version control, enhances collaboration among teams, allows for easier replication of environments, streamlines the deployment and management of infrastructure boosting efficiency, and reducing errors in managing complex systems.

How to start building AWS infrastructure with Terraform: AWS NAT Gateway

  1. Prerequisites

    Read previous sections of the tutorial: AWS with Terraform Tutorial

  2. AWS NAT Gateway and EIP

    An AWS NAT Gateway is a managed service that allows instances in a private subnet to connect to the Internet while keeping them secure. It provides network address translation (NAT) for outbound traffic, allowing resources in a private subnet to access the internet while maintaining a private IP address.

  3. Terraform AWS Configuration Plan Definition

    Previous sections of the Tutorial have covered basic information about Terraform, AWS Cloud, the Terraform AWS Provider, VPC, Subnets, and Internet Gateway. Now it is time to create the NAT Gateway.

  4. How to create an AWS NAT Gateway and EIP with Terraform

    Each Terraform aws_nat_gateway resource block creates a NAT Gateway and requires an existing Elastic IP (EIP) aws_eip block to use as a Public IP to access the Internet.

  5. Run the Terraform Plan

    Plan, and apply the Terraform plan to create the NAT Gateway in AWS.

  6. NAT Gateways and EIP Cost

    NAT gateways and EIPs have an hourly cost.

  7. Destroying AWS Infrastructure with Terraform

    Removing infrastructure from Terraform Configuration and from the Cloud.

  8. Common Questions About AWS NAT Gateways

    How is NAT Gateway different from NAT instance? Can I resize an AWS NAT Gateway? Why deploy NAT Gateways across multiple Availability Zones?...

  9. Next Steps

    Other tutorials for creating infrastructure in AWS using Terraform.

Prerequisites

Read previous sections of the tutorial:

AWS NAT Gateway and EIP

AWS NAT GW

An AWS NAT Gateway is a managed service that allows instances in a private subnet to connect to the Internet while keeping them secure. It provides network address translation (NAT) for outbound traffic, allowing resources in a private subnet to access the internet while maintaining a private IP address.

AWS Instances in a private subnet only have private IPs. To access the Internet a NAT Gateway, located in a public subnet, is needed.

Elastic IP Address

The NAT Gateway maps the private IPs to an AWS EIP (Elastic IP address). Additionally, an Internet Gateway and proper routing tables are required.

To achieve redundancy each Availability Zone requires its own NAT Gateway.

AWS NAT Gateway

Terraform generates a dependency graph to understand the order in which resources should be created or modified. It helps determine the relationships and dependencies between different resources defined in your Terraform configuration. This ensures that resources are created or modified in the correct order to maintain a consistent infrastructure state. Sometimes Terraform or the provider can’t generate accurate dependency relations and require additional configuration using the depends_on Meta-Argument. For the NAT Gateway, a manual dependency on the Internet Gateway will be established.

Terraform AWS Configuration Plan Definition

Previous sections of this AWS with Terraform guide have covered basic information about Terraform and AWS and have configured and used the AWS Terraform provider to create a VPC, four subnets, and an Internet Gateway.

It is time to create the NAT Gateway. Keep adding Terraform blocks to the terraform-aws-tutorial.tf created in previous sections.

How to Create an AWS NAT Gateway and EIP with Terraform

Each Terraform aws_nat_gateway resource block creates a NAT Gateway and requires an existing aws_eip block that creates an Elastic IP (EIP) to use as a Public IP to access the Internet.

Elastic IPs are Public IPs associated with the AWS account. Once requested from AWS, the assigned IP doesn't change (unless released and removed from the AWS Account). Having a fixed public IP is useful as it can be used outside AWS for firewall authorization or as a DNS Type A record.

NAT Gateway definition using Terraform, add the following blocks to the file terraform-aws-tutorial.tf:

# NAT Gateway Public Availability Zone: A
resource "aws_nat_gateway" "ditwl-ngw-za-pub" {
  subnet_id = aws_subnet.ditwl-sn-za-pro-pub-00.id
  allocation_id = aws_eip.ditwl-eip-ngw-za.id

  tags = {
    Name = "ditwl-ngw-za-pub"
  }

  depends_on = [aws_internet_gateway.ditwl-ig]
}

# EIP for NAT Gateway in AZ A
resource "aws_eip" "ditwl-eip-ngw-za" {
  domain   = "vpc"

  tags = {
    Name = "ditwl-eip-ngw-za"
  }
}

# NAT Gateway Public Availability Zone: B
resource "aws_nat_gateway" "ditwl-ngw-zb-pub" {
  subnet_id = aws_subnet.ditwl-sn-zb-pro-pub-04.id
  allocation_id = aws_eip.ditwl-eip-ngw-zb.id

  tags = {
    Name = "ditwl-ngw-zb-pub"
  }

  depends_on = [aws_internet_gateway.ditwl-ig]
}

# EIP for NAT Gateway in AZ B
resource "aws_eip" "ditwl-eip-ngw-zb" {
  domain   = "vpc"

  tags = {
    Name = "ditwl-eip-ngw-zb"
  }  
}

NAT Gateway Public Availability Zone A

Named ditwl-ngw-za-pub, is created inside the subnet ditwl-sn-za-pro-pub-00 created in the previous tutorial, using its Terraform reference aws_subnet.ditwl-sn-za-pro-pub-00.id

A dependency is added specifying that this NAT Gateway depends on the existence of the Internet Gateway, created in the previous tutorial and identified with its Terraform name aws_internet_gateway.ditwl-ig.

The EIP is defined right after the NAT although Terraform will create the EIP before attempting to create the NAT Gateway as it is an explicit dependency (a parameter to the NAT Gateway block).

This aws_nat_gateway will be used as a target in the routing table for private subnets in availability zone A using its Terraform type and name: aws_nat_gateway.ditwl-ngw-za-pub.

NAT Gateway Public Availability Zone B

Named ditwl-ngw-zb-pub, is created inside the subnet ditwl-sn-zb-pro-pub-04 created in the previous tutorial, using its Terraform reference aws_subnet.ditwl-sn-zb-pro-pub-04.id

A dependency is added specifying that this NAT Gateway depends on the existence of the Internet Gateway, created in the previous tutorial and identified with its Terraform name aws_internet_gateway.ditwl-ig.

This aws_nat_gateway will be used as a target in the routing table for private subnets in availability zone B using its Terraform type and name: aws_nat_gateway.ditwl-ngw-zb-pub.

Run the Terraform Plan

Open a command line shell at the same location where the terraform-aws-tutorial.tf file is located, and, run the Terraform or OpenTofu plan, and apply the commands.

Plan using OpenTofu

Run tofu plan to generate and review the execution plan. Check each line and value to make sure that it corresponds to the desired change.

The VPC, Subnets, and the Internet Gateway were already created in the previous Terraform execution so now only the new NAT Gateways will be created. Terraform or OpenTofu show Refreshing state for each of the existing elements and the planned actions for the changes.

$ tofu plan
aws_vpc.ditlw-vpc: Refreshing state... [id=vpc-0bed1f6c715e9a909]
aws_internet_gateway.ditwl-ig: Refreshing state... [id=igw-033b206763b59357e]
aws_subnet.ditwl-sn-za-pro-pub-00: Refreshing state... [id=subnet-07753bf540026684d]
aws_subnet.ditwl-sn-za-pro-pri-02: Refreshing state... [id=subnet-096bf79e4bab2e1c4]
aws_subnet.ditwl-sn-zb-pro-pri-06: Refreshing state... [id=subnet-0f5662bd40a070e55]
aws_subnet.ditwl-sn-zb-pro-pub-04: Refreshing state... [id=subnet-0d34cee7300e9fa45]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

OpenTofu will perform the following actions:

  # aws_eip.ditwl-eip-ngw-za will be created
  + resource "aws_eip" "ditwl-eip-ngw-za" {
      + domain               = "vpc"
      ...
      + public_ip            = (known after apply)
      + tags                 = {
          + "Name" = "ditwl-eip-ngw-za"
        }
      + tags_all             = {
          + "Name"        = "ditwl-eip-ngw-za"
          + "cost_center" = "marketing-department"
          + "environment" = "pro"
          + "owner"       = "IT Wonder Lab"
        }
      + vpc                  = (known after apply)
    }

  # aws_eip.ditwl-eip-ngw-zb will be created
  + resource "aws_eip" "ditwl-eip-ngw-zb" {
      + domain               = "vpc"
      ...
      + public_ip            = (known after apply)
      + tags                 = {
          + "Name" = "ditwl-eip-ngw-zb"
        }
      + tags_all             = {
          + "Name"        = "ditwl-eip-ngw-zb"
          + "cost_center" = "marketing-department"
          + "environment" = "pro"
          + "owner"       = "IT Wonder Lab"
        }
      + vpc                  = (known after apply)
    }

  # aws_nat_gateway.ditwl-ngw-za-pub will be created
  + resource "aws_nat_gateway" "ditwl-ngw-za-pub" {
      + allocation_id                      = (known after apply)
      + association_id                     = (known after apply)
      + connectivity_type                  = "public"
      ...
      + subnet_id                          = "subnet-07753bf540026684d"
      + tags                               = {
          + "Name" = "ditwl-ngw-za-pub"
        }
      + tags_all                           = {
          + "Name"        = "ditwl-ngw-za-pub"
          + "cost_center" = "marketing-department"
          + "environment" = "pro"
          + "owner"       = "IT Wonder Lab"
        }
    }

  # aws_nat_gateway.ditwl-ngw-zb-pub will be created
  + resource "aws_nat_gateway" "ditwl-ngw-zb-pub" {
      + allocation_id                      = (known after apply)
      + association_id                     = (known after apply)
      + connectivity_type                  = "public"
      ...
      + subnet_id                          = "subnet-0d34cee7300e9fa45"
      + tags                               = {
          + "Name" = "ditwl-ngw-zb-pub"
        }
      + tags_all                           = {
          + "Name"        = "ditwl-ngw-zb-pub"
          + "cost_center" = "marketing-department"
          + "environment" = "pro"
          + "owner"       = "IT Wonder Lab"
        }
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Apply the changes using OpenTofu

Run tofu apply to generate and apply the execution plan. OpenTofu will generate a new plan and ask for confirmation before applying the changes. Review again the changes and answer yes or no to apply the changes in AWS.

$ tofu apply
aws_vpc.ditlw-vpc: Refreshing state... [id=vpc-0bed1f6c715e9a909]
aws_internet_gateway.ditwl-ig: Refreshing state... [id=igw-033b206763b59357e]
aws_subnet.ditwl-sn-za-pro-pri-02: Refreshing state... [id=subnet-096bf79e4bab2e1c4]
aws_subnet.ditwl-sn-za-pro-pub-00: Refreshing state... [id=subnet-07753bf540026684d]
aws_subnet.ditwl-sn-zb-pro-pub-04: Refreshing state... [id=subnet-0d34cee7300e9fa45]
aws_subnet.ditwl-sn-zb-pro-pri-06: Refreshing state... [id=subnet-0f5662bd40a070e55]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

OpenTofu will perform the following actions:

  # aws_eip.ditwl-eip-ngw-za will be created
  + resource "aws_eip" "ditwl-eip-ngw-za" {
    ...
    }

  # aws_eip.ditwl-eip-ngw-zb will be created
  + resource "aws_eip" "ditwl-eip-ngw-zb" {
    ...
    }

  # aws_nat_gateway.ditwl-ngw-za-pub will be created
  + resource "aws_nat_gateway" "ditwl-ngw-za-pub" {
    ...
    }

  # aws_nat_gateway.ditwl-ngw-zb-pub will be created
  + resource "aws_nat_gateway" "ditwl-ngw-zb-pub" {
    ...
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  OpenTofu will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_eip.ditwl-eip-ngw-za: Creating...
aws_eip.ditwl-eip-ngw-zb: Creating...
aws_eip.ditwl-eip-ngw-za: Creation complete after 2s [id=eipalloc-09d067ed40aa0a4b0]
aws_nat_gateway.ditwl-ngw-za-pub: Creating...
aws_eip.ditwl-eip-ngw-zb: Creation complete after 2s [id=eipalloc-01af98f4b5057cc20]
aws_nat_gateway.ditwl-ngw-zb-pub: Creating...
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [10s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [10s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [20s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [20s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [30s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [30s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [40s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [40s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [50s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [50s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [1m0s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [1m0s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [1m10s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [1m10s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [1m20s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [1m20s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still creating... [1m30s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [1m30s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Creation complete after 1m39s [id=nat-0d7980bc4c9f1623f]
aws_nat_gateway.ditwl-ngw-zb-pub: Still creating... [1m40s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Creation complete after 1m50s [id=nat-05b3376011cb51399]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed

Review the result, it should be 4 (resource) added, 0 changed, 0 destroyed.

Check using the AWS web Console that the NAT Gateways and the EIPs have been created:

NatGateways VPC Console

If you don't see the NAT gateway check on the right top corner that the Region is N. Virginia that corresponds to us-east-1.

Click on the Public IPs to navigate to the EIP console and see its properties.

NAT Gateways and EIP Cost

NAT gateways are specialized instances that have a running cost, AWS charges for each “NAT Gateway-hour" that each gateway is provisioned and available, additionally, each GB of data processed is changed separately.

AWS EIPs are also hourly charged (starting February 1, 2024) whether in use or not.

Destroying AWS Infrastructure with Terraform

In Terraform, anything following the # on a line is treated as a comment and is ignored by Terraform during execution.

When a resource block is removed or commented from a Terraform configuration file, in the next execution Terraform will destroy the element in the Cloud.

Take this opportunity to comment on the Terraform blocks inside the terraform-aws-tutorial.tf file that creates the NAT Gateways and the EIPs. Add an # on each line to comment on the 4 blocks or use a block comment /*

# # NAT Gateway Public Availability Zone: A
# resource "aws_nat_gateway" "ditwl-ngw-za-pub" {
#   subnet_id = aws_subnet.ditwl-sn-za-pro-pub-00.id
#   allocation_id = aws_eip.ditwl-eip-ngw-za.id

#   tags = {
#     Name = "ditwl-ngw-za-pub"
#   }

#   depends_on = [aws_internet_gateway.ditwl-ig]
# }

# # EIP for NAT Gateway in AZ A
# resource "aws_eip" "ditwl-eip-ngw-za" {
#   domain   = "vpc"

#   tags = {
#     Name = "ditwl-eip-ngw-za"
#   }
# }

# # NAT Gateway Public Availability Zone: B
# resource "aws_nat_gateway" "ditwl-ngw-zb-pub" {
...
/*
# NAT Gateway Public Availability Zone: A
resource "aws_nat_gateway" "ditwl-ngw-za-pub" {
  subnet_id = aws_subnet.ditwl-sn-za-pro-pub-00.id
  allocation_id = aws_eip.ditwl-eip-ngw-za.id

  tags = {
    Name = "ditwl-ngw-za-pub"
  }

  depends_on = [aws_internet_gateway.ditwl-ig]
}

...

# EIP for NAT Gateway in AZ B
resource "aws_eip" "ditwl-eip-ngw-zb" {
  domain   = "vpc"

  tags = {
    Name = "ditwl-eip-ngw-zb"
  }  
}
*/

Now, apply the changes in the Cloud by running tofu apply to generate and apply the execution plan:

$ tofu apply
aws_nat_gateway.ditwl-ngw-zb-pub: Refreshing state... [id=nat-05b3376011cb51399]
aws_nat_gateway.ditwl-ngw-za-pub: Refreshing state... [id=nat-0d7980bc4c9f1623f]
aws_eip.ditwl-eip-ngw-zb: Refreshing state... [id=eipalloc-01af98f4b5057cc20]
aws_eip.ditwl-eip-ngw-za: Refreshing state... [id=eipalloc-09d067ed40aa0a4b0]
aws_vpc.ditlw-vpc: Refreshing state... [id=vpc-0bed1f6c715e9a909]
aws_internet_gateway.ditwl-ig: Refreshing state... [id=igw-033b206763b59357e]
aws_subnet.ditwl-sn-za-pro-pub-00: Refreshing state... [id=subnet-07753bf540026684d]
aws_subnet.ditwl-sn-za-pro-pri-02: Refreshing state... [id=subnet-096bf79e4bab2e1c4]
aws_subnet.ditwl-sn-zb-pro-pri-06: Refreshing state... [id=subnet-0f5662bd40a070e55]
aws_subnet.ditwl-sn-zb-pro-pub-04: Refreshing state... [id=subnet-0d34cee7300e9fa45]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  - destroy

OpenTofu will perform the following actions:

  # aws_eip.ditwl-eip-ngw-za will be destroyed
  # (because aws_eip.ditwl-eip-ngw-za is not in configuration)
  - resource "aws_eip" "ditwl-eip-ngw-za" {
      - allocation_id        = "eipalloc-09d067ed40aa0a4b0" -> null
      - association_id       = "eipassoc-0a73a6aa8c1a3e887" -> null
      - domain               = "vpc" -> null
      - id                   = "eipalloc-09d067ed40aa0a4b0" -> null
      - network_border_group = "us-east-1" -> null
      - network_interface    = "eni-0fc6a8a09b59458e5" -> null
      - private_dns          = "ip-172-21-0-190.ec2.internal" -> null
      - private_ip           = "172.21.0.190" -> null
      - public_dns           = "ec2-3-232-192-205.compute-1.amazonaws.com" -> null
      - public_ip            = "3.232.192.205" -> null
      - public_ipv4_pool     = "amazon" -> null
      - tags                 = {
          - "Name" = "ditwl-eip-ngw-za"
        } -> null
      - tags_all             = {
          - "Name"        = "ditwl-eip-ngw-za"
          - "cost_center" = "marketing-department"
          - "environment" = "pro"
          - "owner"       = "IT Wonder Lab"
        } -> null
      - vpc                  = true -> null
    }

  # aws_eip.ditwl-eip-ngw-zb will be destroyed
  # (because aws_eip.ditwl-eip-ngw-zb is not in configuration)
  - resource "aws_eip" "ditwl-eip-ngw-zb" {
      - allocation_id        = "eipalloc-01af98f4b5057cc20" -> null
      - association_id       = "eipassoc-0771a263deb9c67ad" -> null
      - domain               = "vpc" -> null
      - id                   = "eipalloc-01af98f4b5057cc20" -> null
      - network_border_group = "us-east-1" -> null
      - network_interface    = "eni-08c2f941edd62d0cb" -> null
      - private_dns          = "ip-172-21-5-164.ec2.internal" -> null
      - private_ip           = "172.21.5.164" -> null
      - public_dns           = "ec2-107-21-204-41.compute-1.amazonaws.com" -> null
      - public_ip            = "107.21.204.41" -> null
      - public_ipv4_pool     = "amazon" -> null
      - tags                 = {
          - "Name" = "ditwl-eip-ngw-zb"
        } -> null
      - tags_all             = {
          - "Name"        = "ditwl-eip-ngw-zb"
          - "cost_center" = "marketing-department"
          - "environment" = "pro"
          - "owner"       = "IT Wonder Lab"
        } -> null
      - vpc                  = true -> null
    }

  # aws_nat_gateway.ditwl-ngw-za-pub will be destroyed
  # (because aws_nat_gateway.ditwl-ngw-za-pub is not in configuration)
  - resource "aws_nat_gateway" "ditwl-ngw-za-pub" {
      - allocation_id                      = "eipalloc-09d067ed40aa0a4b0" -> null
      - association_id                     = "eipassoc-0a73a6aa8c1a3e887" -> null
      - connectivity_type                  = "public" -> null
      - id                                 = "nat-0d7980bc4c9f1623f" -> null
      - network_interface_id               = "eni-0fc6a8a09b59458e5" -> null
      - private_ip                         = "172.21.0.190" -> null
      - public_ip                          = "3.232.192.205" -> null
      - secondary_allocation_ids           = [] -> null
      - secondary_private_ip_address_count = 0 -> null
      - secondary_private_ip_addresses     = [] -> null
      - subnet_id                          = "subnet-07753bf540026684d" -> null
      - tags                               = {
          - "Name" = "ditwl-ngw-za-pub"
        } -> null
      - tags_all                           = {
          - "Name"        = "ditwl-ngw-za-pub"
          - "cost_center" = "marketing-department"
          - "environment" = "pro"
          - "owner"       = "IT Wonder Lab"
        } -> null
    }

  # aws_nat_gateway.ditwl-ngw-zb-pub will be destroyed
  # (because aws_nat_gateway.ditwl-ngw-zb-pub is not in configuration)
  - resource "aws_nat_gateway" "ditwl-ngw-zb-pub" {
      - allocation_id                      = "eipalloc-01af98f4b5057cc20" -> null
      - association_id                     = "eipassoc-0771a263deb9c67ad" -> null
      - connectivity_type                  = "public" -> null
      - id                                 = "nat-05b3376011cb51399" -> null
      - network_interface_id               = "eni-08c2f941edd62d0cb" -> null
      - private_ip                         = "172.21.5.164" -> null
      - public_ip                          = "107.21.204.41" -> null
      - secondary_allocation_ids           = [] -> null
      - secondary_private_ip_address_count = 0 -> null
      - secondary_private_ip_addresses     = [] -> null
      - subnet_id                          = "subnet-0d34cee7300e9fa45" -> null
      - tags                               = {
          - "Name" = "ditwl-ngw-zb-pub"
        } -> null
      - tags_all                           = {
          - "Name"        = "ditwl-ngw-zb-pub"
          - "cost_center" = "marketing-department"
          - "environment" = "pro"
          - "owner"       = "IT Wonder Lab"
        } -> null
    }

Plan: 0 to add, 0 to change, 4 to destroy.

Do you want to perform these actions?
  OpenTofu will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_nat_gateway.ditwl-ngw-za-pub: Destroying... [id=nat-0d7980bc4c9f1623f]
aws_nat_gateway.ditwl-ngw-zb-pub: Destroying... [id=nat-05b3376011cb51399]
aws_nat_gateway.ditwl-ngw-zb-pub: Still destroying... [id=nat-05b3376011cb51399, 10s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still destroying... [id=nat-0d7980bc4c9f1623f, 10s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still destroying... [id=nat-05b3376011cb51399, 20s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still destroying... [id=nat-0d7980bc4c9f1623f, 20s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still destroying... [id=nat-05b3376011cb51399, 30s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still destroying... [id=nat-0d7980bc4c9f1623f, 30s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still destroying... [id=nat-0d7980bc4c9f1623f, 40s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Still destroying... [id=nat-05b3376011cb51399, 40s elapsed]
aws_nat_gateway.ditwl-ngw-zb-pub: Destruction complete after 44s
aws_eip.ditwl-eip-ngw-zb: Destroying... [id=eipalloc-01af98f4b5057cc20]
aws_eip.ditwl-eip-ngw-zb: Destruction complete after 2s
aws_nat_gateway.ditwl-ngw-za-pub: Still destroying... [id=nat-0d7980bc4c9f1623f, 50s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Still destroying... [id=nat-0d7980bc4c9f1623f, 1m0s elapsed]
aws_nat_gateway.ditwl-ngw-za-pub: Destruction complete after 1m6s
aws_eip.ditwl-eip-ngw-za: Destroying... [id=eipalloc-09d067ed40aa0a4b0]
aws_eip.ditwl-eip-ngw-za: Destruction complete after 5s

Apply complete! Resources: 0 added, 0 changed, 4 destroyed.

Review the result, it should be 0 (resource) added, 0 changed, 4 destroyed. Terraform has destroyed the two EIPs and the NAT Gateways because the cloud resources were not present in the configuration. AWS stops charging resource usage or availability once the resource is destroyed.

Common Questions About AWS NAT Gateways

When to use a NAT Gateway?

When resources in a private subnet need to access the internet for tasks such as downloading software updates, fetching data from external APIs, or accessing external services.

In a multi-tier architecture with public and private subnets, the private subnet might need to access the Internet while still being protected from direct incoming traffic, the NAT Gateway acts as a barrier between the private instances and the public Internet, enhancing security by avoiding direct exposure of private instances.

Applications that initiate outbound connections and require consistent source IP addresses for tasks such as accessing third-party APIs or external services. The NAT Gateway uses a static Elastic IP address, having a fixed source IP allows firewall and access control authorization.

NAT is also useful when compliance standards mandate secure handling of outbound Internet traffic.

How is NAT Gateway different from NAT instance?

NAT Gateway is a managed service, offering higher availability and scalability compared to a manually configured NAT instance.

Can I resize an AWS NAT Gateway?

No, AWS NAT Gateway sizes are fixed. A NAT gateway supports 5 Gbps of bandwidth and automatically scales up to 100 Gbps and can process one million packets per second and automatically scales up to ten million packets per second. If your user case requires more bandwidth, split your resources into multiple subnets and create multiple NAT Gateways. Each IPv4 address can support up to 55,000 simultaneous connections to each unique destination and is limited to having 2 Elastic IP addresses attached although a limit increase can be requested.

Why deploy NAT Gateways across multiple Availability Zones?

It provides high availability. If one Availability Zone experiences issues, the others can still handle outbound traffic.

What security measures should be taken with NAT Gateway?

Configure security groups to allow only necessary outbound traffic and update route tables in private subnets to direct traffic to the NAT Gateway.

How to monitor AWS NAT Gateway?

Monitor using AWS CloudWatch for data transfer and performance. Enable logging for activity tracking and troubleshooting.

Next Steps

This tutorial series is a work in progress and will have these sections:

Terraform Basics, AWS Basics, Terraform AWS Provider, AWS VPC, AWS Subnets, AWS Internet Gateway, AWS NAT Gateway, AWS Routing Tables, AWS Security Groups, AWS Key Pairs, AWS AMIs, AWS EC2 Instances, AWS RDS, AWS Route 53 (DNS), AWS Auto Scaling, AWS Load Balancers, Terraform AWS & Ansible, Terraform Modules, Terraform Backends, Terraform Tools, Terraform CI/CD.

AWS with Terraform: The Essential Guide: Sections

Leave a Reply

Your email address will not be published. Required fields are marked *


Related Cloud Tutorials

Securing your Infrastructure: Encrypting Terraform State Files with OpenTofu
Using the Terraform aws_route53_delegation_set, aws_route53_zone, and aws_route53_record resource blocks to configure DNS in AWS.
Using the Terraform aws_db_instance resource block to configure, launch, and secure RDS instances.
How to use the Terraform aws_instance resource block to configure, launch, and secure EC2 instances.
How to configure and use the Terraform aws_ami data source block to find and use AWS AMIs as templates (root volume snapshot with operating system and applications) for EC2 instances.
Javier Ruiz Cloud and SaaS Expert

Javier Ruiz

IT Wonder Lab tutorials are based on the diverse experience of Javier Ruiz, who founded and bootstrapped a SaaS company in the energy sector. His company, later acquired by a NASDAQ traded company, managed over €2 billion per year of electricity for prominent energy producers across Europe and America. Javier has over 25 years of experience in building and managing IT companies, developing cloud infrastructure, leading cross-functional teams, and transitioning his own company from on-premises, consulting, and custom software development to a successful SaaS model that scaled globally.

Are you looking for cloud automation best practices tailored to your company?

linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram