AWS with Terraform Tutorial: AWS VPC (4)

· Updated · 11 min read · Terraform & OpenTofu Tutorials

How to Create, and Manage AWS VPCs with Terraform #

How to configure and use the Terraform aws_vpc resource block to create and manage AWS VPCs.

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 comprehensive OpenTofu and Terraform tutorial guides you step-by-step through creating infrastructure in AWS using Terraform.

Terraform is an Infrastructure as Code (IaC) tool used to provision and manage infrastructure. It helps define and deploy resources across various cloud providers using code, making it easier to maintain and scale infrastructure.Terraform is an Infrastructure as Code (IaC) tool used to provision and manage infrastructure. It helps define and deploy resources across various cloud providers using code, making it easier to maintain and scale infrastructure.
Terraform
Basics
Terraform...
AWS is the world’s leading cloud platform, it is used by a wide range of organizations, from startups to large enterprises, to power their online businesses. AWS offers a wide range of services, including computing, storage, database, networking, analytics, machine learning, and artificial intelligence.AWS is the world’s leading cloud platform, it is used by a wide range of organizations, from startups to large enterprises, to power their online businesses. AWS offers a wide range of services, including computing, storage, database, networking, analytics, machine learning, and artificial intelligence.
AWS
Basics
AWS...
The Terraform official AWS provider acts as an abstraction layer that lets Terraform configurations written in HCL define AWS services and infrastructure using code (IaC). Internally Terraform and the AWS provider handle authentication, and make the necessary AWS API calls to query, create, modify, and destroy the resources.The Terraform official AWS provider acts as an abstraction layer that lets Terraform configurations written in HCL define AWS services and infrastructure using code (IaC). Internally Terraform and the AWS provider handle authentication, and make the necessary AWS API calls to query, create, modify, and destroy the resources.
Terraform
AWS Provider
Terraform...
How to Create, and Manage AWS VPCs with TerraformHow to Create, and Manage AWS VPCs with Terraform
AWS VPC
AWS VPC
How to configure and use the Terraform aws_subnet resource block to create and manage AWS Subnets inside a VPC.How to configure and use the Terraform aws_subnet resource block to create and manage AWS Subnets inside a VPC.
AWS Subnets
AWS Subnets
How to configure and use the Terraform aws_internet_gateway resource block to create and manage AWS Internet Gateway inside a VPC to enable Internet access to and from instances. How to configure and use the Terraform aws_internet_gateway resource block to create and manage AWS Internet Gateway inside a VPC to enable Internet access to and from instances.
AWS Internet
Gateway
AWS Internet...
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.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.
AWS NAT
Gateway
AWS NAT...
How to configure and use the Terraform aws_route_table, aws_route, and aws_main_route_table_association resource blocks to create and manage AWS Routing Tables.How to configure and use the Terraform aws_route_table, aws_route, and aws_main_route_table_association resource blocks to create and manage AWS Routing Tables.
AWS Routing
Tables
AWS Routing...
How to configure and use the Terraform aws_security_group and aws_security_group_rule resource blocks to create and manage AWS Security Groups and secure the infrastructure.How to configure and use the Terraform aws_security_group and aws_security_group_rule resource blocks to create and manage AWS Security Groups and secure the infrastructure.
AWS Security
Groups
AWS Security...
How to configure and use the Terraform aws_key_pair resource block to create and manage AWS Key Pairs for performing SSH Public Key Authentication into EC2 instances.How to configure and use the Terraform aws_key_pair resource block to create and manage AWS Key Pairs for performing SSH Public Key Authentication into EC2 instances.
AWS Key
Pairs
AWS Key...
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.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.
AWS AMIs
AWS AMIs
Using the Terraform aws_instance resource block to configure, launch, and secure EC2 instances.Using the Terraform aws_instance resource block to configure, launch, and secure EC2 instances.
AWS EC2
Instances
AWS EC2...
AWS RDS
AWS RDS
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_route53_delegation_set, aws_route53_zone, and aws_route53_record resource blocks to configure DNS in AWS.
AWS Route 53
(DNS)
AWS Route 53...
Amazon EC2 Auto Scaling groups keep the right number of instances running, replace failed ones and scale with the load.Amazon EC2 Auto Scaling groups keep the right number of instances running, replace failed ones and scale with the load.
AWS Auto
Scaling
AWS Auto...
Elastic Load Balancing distributes the traffic between healthy instances. The tutorial creates an Application Load Balancer with HTTPS.Elastic Load Balancing distributes the traffic between healthy instances. The tutorial creates an Application Load Balancer with HTTPS.
AWS Load
Balancers
AWS Load...
This tutorial shows how to create infrastructure in AWS using Terraform and configure the operating system and applications using Ansible.This tutorial shows how to create infrastructure in AWS using Terraform and configure the operating system and applications using Ansible.
Terraform,
AWS & Ansible
Terraform,...
Modules package resources behind variables and outputs so they can be reused. The tutorial refactors the network into a module.Modules package resources behind variables and outputs so they can be reused. The tutorial refactors the network into a module.
Terraform
Modules
Terraform...
A backend stores the Terraform state. The tutorial uses an encrypted, versioned S3 bucket with state locking.A backend stores the Terraform state. The tutorial uses an encrypted, versioned S3 bucket with state locking.
Terraform
Backends
Terraform...
fmt, validate, TFLint, Trivy, Checkov, terraform-docs, Infracost and pre-commit: check the code before it reaches AWS.fmt, validate, TFLint, Trivy, Checkov, terraform-docs, Infracost and pre-commit: check the code before it reaches AWS.
Terraform
Tools
Terraform...
Run checks, plans and approved applies automatically with GitHub Actions and OIDC, without access keys.Run checks, plans and approved applies automatically with GitHub Actions and OIDC, without access keys.
Terraform
CI/CD
Terraform...
Select a tutorial section 
Select a tutorial sectio...

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.

Prerequisites #

Read the previous sections of the tutorial, listed in the series index at the end of this page.

Terraform AWS Configuration Plan Definition #

Previous sections of this AWS with Terraform guide have covered basic information about Terraform and AWS. Now it is time to create a Terraform Plan.

In an empty directory, create a file named terraform-aws-tutorial.tf with the following two blocks:

# Copyright (C) 2018 - 2023 IT Wonder Lab (https://www.itwonderlab.com)
#
# This software may be modified and distributed under the terms
# of the MIT license.  See the LICENSE file for details.
# -------------------------------- WARNING --------------------------------
# IT Wonder Lab's best practices for infrastructure include modularizing 
# Terraform/OpenTofu configuration. 
# In this example, we define everything in a single file. 
# See other tutorials for best practices at itwonderlab.com
# -------------------------------- WARNING --------------------------------

#-----------------------------------------
# Define Terrraform Providers and Backend
#-----------------------------------------
terraform {
  required_version = "> 1.5"

  required_providers {
    aws = {
      source  = "aws"
      version = "~> 5.0"
    }
  }
}

#-----------------------------------------
# Provider: AWS
#-----------------------------------------
provider "aws" {
  profile         = "ditwl_infradmin"
  default_tags {
    tags = {
      environment = "pro"
      cost_center = "sales-department"
    }
  }
}

The first block defines the Terraform version and the required AWS Terraform provider, specifying the version and the provider (none, Hashicorp, or OpenTofu).

The second block configures the AWS Terraform provider by specifying "ditwl_infradmin" as the AWS CLI profile to use for authentication and a list of tags and values that will be added by default to all the resources created with Terraform.

The AWS CLI profile includes the access key, secret access key, account ID, and the AWS region.

How to create an AWS VPC with Terraform #

The first element that should be created is a VPC.

The VPC is created in the region specified while configuring the AWS Terraform provider (therefore the one defined by the AWS CLI profile "ditwl_infradmin"). This example uses the region us-east-1, located in Northern Virginia, United States.

Region
Region
us-east-1
us-east-1
VPC
VPC
172.21.0.0/19
172.21.0.0/19
Name=ditlw-vpc
Name=ditlw-vpc
environment = pro
environment = pro
cost_center = sales-department
cost_center = sales-depart...
Text is not SVG - cannot display

VPC definition using Terraform, add the following block to the file terraform-aws-tutorial.tf:

# VPC, CIDR Block: 172.21.0.0/19
resource "aws_vpc" "ditlw-vpc" {
  cidr_block = "172.21.0.0/19" #172.21.0.0 - 172.21.31.254
  tags = {
    Name = "ditlw-vpc"
    tool = "Terraform"
  }
}

The Terraform aws_vpc resource block creates a VPC with a network CIDR of 172.21.0.0/19 and the tags Name = "ditlw-vpc" and tool = "Terraform". Additionally the default tags environment = "pro" and cost_center = "sales-department" defined at the AWS Provider block will be automatically added by Terraform.

Other configuration options are available but not needed for a basic VPC.

The VPC properties can be referenced in the Terraform plan using the resource type (aws_vpc), assigned name (ditlw-vpc), and the exported attribute, for example:

  • ID of the VPC: aws_vpc.ditlw-vpc.id
  • Amazon Resource Name (ARN) of VPC: aws_vpc.ditlw-vpc.arn
  • Default route table id: aws_vpc.ditlw-vpc.default_route_table_id

The Tag Name and the resource name can be different but the best practice is to keep the same name.

The VPC ID will be used in the next sections as a parameter to create the AWS Subnets and the Default Routing Table.

Run the Terraform Plan #

Terraform configuration plans can be applied iteratively as new infrastructure needs to be added, modified, or destroyed.

Decide between using Terraform or OpenTofu and using the same tool during all the tutorial sections. You can switch tools to test Terraform and OpenTofu compatibility. The code is compatible with both tools and during the tutorial, OpenTofu will be used to run all commands.

Open a command line shell in the directory where the file terraform-aws-tutorial.tf is located, and run the Terraform or OpenTofu init, plan, and apply commands:

Init using OpenTofu #

The init command needs to be run once to download and initialize the required providers and lock files.

$ tofu init

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.32.1...
- Installed hashicorp/aws v5.32.1 (signed, key ID 0C0AF313E5FD9F80)

Providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://opentofu.org/docs/cli/plugins/signing/

OpenTofu has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that OpenTofu can guarantee to make the same selections by default when
you run "tofu init" in the future.

OpenTofu has been successfully initialized!

You may now begin working with OpenTofu. Try running "tofu plan" to see
any changes that are required for your infrastructure. All OpenTofu commands
should now work.

If you ever set or change modules or backend configuration for OpenTofu,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary

Plan using OpenTofu #

Run tofu plan to generate and review the execution plan. Check each line and value to make sure that corresponds to the desired change. In this case, a VPC will be created (as shown with the + sign) and only a few of its initial properties have been specified (the cidr_block and the tags), with the rest of the properties using default provider values or being known after creation.

$ tofu plan

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_vpc.ditlw-vpc will be created
  + resource "aws_vpc" "ditlw-vpc" {
      + arn                                  = (known after apply)
      + cidr_block                           = "172.21.0.0/19"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags                                 = {
          + "Name" = "ditlw-vpc"
          + "tool" = "Terraform"
        }
      + tags_all                             = {
          + "Name"        = "ditlw-vpc"
          + "cost_center" = "sales-department"
          + "environment" = "pro"
          + "tool"        = "Terraform"
        }
    }

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

─────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so OpenTofu can't guarantee to take exactly these actions if you run "tofu apply" now.

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

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_vpc.ditlw-vpc will be created
  + resource "aws_vpc" "ditlw-vpc" {
      + arn                                  = (known after apply)
      + cidr_block                           = "172.21.0.0/19"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags                                 = {
          + "Name" = "ditlw-vpc"
          + "tool" = "Terraform"
        }
      + tags_all                             = {
          + "Name"        = "ditlw-vpc"
          + "cost_center" = "sales-department"
          + "environment" = "pro"
          + "tool"        = "Terraform"
        }
    }

Plan: 1 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_vpc.ditlw-vpc: Creating...
aws_vpc.ditlw-vpc: Creation complete after 5s [id=vpc-0bed1f6c715e9a909]

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

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

You can now run tofu plan or tofu apply again to check that OpenTofu has not found any new changes to apply.

$ tofu plan
aws_vpc.ditlw-vpc: Refreshing state... [id=vpc-0bed1f6c715e9a909]

No changes. Your infrastructure matches the configuration.

OpenTofu has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

You can modify the cost_center tag, add a new one (owner = "IT Wonder Lab"), and then run tofu plan or tofu apply again. This way, OpenTofu will adjust the VPC, ensuring that the necessary changes in AWS align with the Terraform code.

This example demonstrates an in-place update, where the infrastructure is modified without the need to destroy and recreate it. Be aware that some changes require infrastructure destruction (destroy and create).

$ tofu apply
aws_vpc.ditlw-vpc: Refreshing state... [id=vpc-0bed1f6c715e9a909]

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

OpenTofu will perform the following actions:

  # aws_vpc.ditlw-vpc will be updated in-place
  ~ resource "aws_vpc" "ditlw-vpc" {
        id                                   = "vpc-0bed1f6c715e9a909"
      ~ tags                                 = {
            "Name"        = "ditlw-vpc"
          - "cost_center" = "sales-department" -> null
            "tool"        = "Terraform"
        }
      ~ tags_all                             = {
          ~ "cost_center" = "sales-department" -> "marketing-department"
          + "owner"       = "IT Wonder Lab"
            # (3 unchanged elements hidden)
        }
        # (14 unchanged attributes hidden)
    }

Plan: 0 to add, 1 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_vpc.ditlw-vpc: Modifying... [id=vpc-0bed1f6c715e9a909]
aws_vpc.ditlw-vpc: Modifications complete after 5s [id=vpc-0bed1f6c715e9a909]

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

Terraform shows an in-place update that:

  • Removes (-) the tag “cost_center” from “sales-department” to null:- "cost_center" = "sales-department" -> null
  • Changes (~) the tags_all (a default tag defined at the AWS Provider level) “cost_center” from “sales-department” to “marketing-department”:~ "cost_center" = "sales-department" -> "marketing-department"
  • And, adds (+) a new tag “owner” with the value “IT Wonder Lab”:+ "owner" = "IT Wonder Lab"

Common Questions About AWS VPC #

What IP range should be used for a VPC? #

When planning your Virtual Private Cloud (VPC) network CIDR (Classless Inter-Domain Routing), consider the following:

  • Size: Choose a CIDR block size that provides enough IP addresses for your resources but avoids wasting address space.
  • Subnetting: Plan your subnets within the VPC wisely, considering the number of subnets needed, their size, and the future scalability.
  • Overlap Avoidance: Ensure there’s no overlap with other networks to prevent routing issues. It’s common to avoid using the same CIDR block as other networks you might connect to.
  • Future Growth: Plan for future growth and expansion by choosing a CIDR block that allows for additional subnets and addresses.
  • Reserved Addresses: Each subnet reserves a few IP addresses for AWS use:
    • Network address (first IP, .0): the base network address.
    • VPC router (second IP, .1): reserved for the VPC router.
    • DNS server (third IP, .2): reserved for the Amazon DNS server.
    • Future use (fourth IP, .3): reserved by AWS for future use.
    • Broadcast address (last IP): reserved, although broadcast is not supported in a VPC.
    • Additional Addresses for AWS services. For example, Amazon EKS (see the EKS tutorial) needs to have at least 6 IP addresses available but at least 16 IPs are recommended.

Peering or VPNs: If you plan to connect VPCs or use VPNs, ensure that the CIDR blocks don’t overlap with other clouds, existing VPCs, on-premises data centers, and LAN networks.

Private IP addresses are free to use but proper planning is required for routing across the organization.

How many VPCs do you need? #

The number of VPCs and most importantly the services that each VPC provides have an impact on the cost of the Cloud.

Data Transfer Costs for Common Architectures :

  • Data transfer over VPC Peering connections is free within the same Availability Zone (AZ)
  • Data transfer over a VPC Peering connection that crosses Availability Zones is charged.
  • In RDS Multi-AZ replication between the primary and standby instances does not incur additional data transfer charges, but access from EC2 instances to the RDS instances in different availability zones does.

For small companies, consider each VPC as a data center with its own network, security and costs. Start with one VPC per environment (or one for production and one for the rest) and add more only when there is a reason, such as isolation, compliance or different accounts.

Next Steps #

Continue with AWS Subnets, or see the full series index.

#AWS #AWS Terraform Tutorial #AWS VPC #OpenTofu #Terraform