terraform-aws-modules/terraform-aws-vpc

repository·master·Indexed 25 days ago

https://github.com/terraform-aws-modules/terraform-aws-vpc

An AWS VPC Terraform module that automates the creation and management of complex VPC architectures, including subnets, NAT Gateways, NACLs, and integration with AWS services like IPAM and Transit Gateway. It supports IPv6 dualstack and IPv6-only configurations, VPC Flow Logs (to S3 or CloudWatch), and VPC block public access options with exclusions.

Tokens
18K
Snippets
30
Records
113
Agent score
84%

What's inside terraform-aws-vpc

  1. Use the AWS VPC Endpoints sub-module

    master

    The vpc-endpoints sub-module allows you to create both Interface and Gateway VPC endpoints on AWS. You define endpoints using an endpoints map where each key represents a service and the value contains the specific configuration for that service type.

    To use this module, provide the vpc_id and a map of endpoints. You can configure different settings for Interface endpoints (using subnet_ids and subnet_configurations) and Gateway endpoints (using service_type = "Gateway" and route_table_ids).

    module "endpoints" {
      source = "terraform-aws-modules/vpc/aws//modules/vpc-endpoints"
    
      vpc_id             = "vpc-12345678"
      security_group_ids = ["sg-12345678"]
    
      endpoints = {
        s3 = {
          # interface endpoint
          service             = "s3"
          tags                = { Name = "s3-vpc-endpoint" }
        },
        dynamodb = {
          # gateway endpoint
          service         = "dynamodb"
          service_type    = "Gateway"
          route_table_ids = ["rt-12322456", "rt-43433343", "rt-11223344"]
          tags            = { Name = "dynamodb-vpc-endpoint" }
        },
        sns = {
          service               = "sns"
          subnet_ids            = ["subnet-12345678", "subnet-87654321"]
          subnet_configurations = [
            {
              ipv4      = "10.8.34.10"
              subnet_id = "subnet-12345678"
            },
            {
              ipv4      = "10.8.35.10"
              subnet_id = "subnet-87654321"
            }
          ]
          tags = { Name = "sns-vpc-endpoint" }
        },
        sqs = {
          service             = "sqs"
          private_dns_enabled = true
          security_group_ids  = ["sg-987654321"]
          subnet_ids          = ["subnet-12345678", "subnet-87654321"]
          tags                = { Name = "sqs-vpc-endpoint" }
        },
      }
    
      tags = {
        Owner       = "user"
        Environment = "dev"
      }
    }
  2. Configure AWS Flow Logs to S3 or CloudWatch

    master

    This example demonstrates how to enable VPC Flow Logs using several different configurations via the flow-log module. You can configure flow logs to be sent to:

    • CloudWatch Logs: Using a CloudWatch log group and IAM role created by the module.
    • CloudWatch Logs (External): Using an existing, externally managed CloudWatch log group and IAM role.
    • S3 Bucket (Text): Sending logs to an S3 bucket in text format.
    • S3 Bucket (Parquet): Sending logs to an S3 bucket in Parquet format.

    Requirements

    • terraform >= 1.5.7
    • aws provider >= 6.28
    $ terraform init
    $ terraform plan
    $ terraform apply
  3. Remove gateway endpoint route table associations in v3.x

    master

    When upgrading to v3.x, route table associations for gateway endpoints (like S3 or DynamoDB) are now managed directly within the VPC endpoint sub-module via the provided map of maps. You must remove the standalone aws_vpc_endpoint_route_table_association resources from your Terraform state to avoid conflicts.

    # Remove existing route table association resources from state
    terraform state rm 'module.vpc.aws_vpc_endpoint_route_table_association.intra_dynamodb[0]'
    terraform state rm 'module.vpc.aws_vpc_endpoint_route_table_association.private_dynamodb[0]'
    terraform state rm 'module.vpc.aws_vpc_endpoint_route_table_association.public_dynamodb[0]'
  4. Assign existing Elastic IPs to NAT Gateways

    master

    To prevent the destruction of a VPC from releasing Elastic IPs, allocate aws_eip resources outside the VPC module and pass them in using reuse_nat_ips = true and external_nat_ip_ids.

    resource "aws_eip" "nat" {
      count = 3
    
      vpc = true
    }
    
    module "vpc" {
      source = "terraform-aws-modules/vpc/aws"
    
      # The rest of arguments are omitted for brevity
    
      enable_nat_gateway  = true
      single_nat_gateway  = false
      reuse_nat_ips       = true                    # <= Skip creation of EIPs for the NAT Gateways
      external_nat_ip_ids = "${aws_eip.nat.*.id}"   # <= IPs specified here as input to the module
    }
  5. Assign VPC CIDR from AWS IPAM

    master

    To use an AWS IPAM Pool for CIDR assignment, you must 'preview' the CIDR using aws_vpc_ipam_preview_next_cidr because the module needs to know subnet CIDRs during the plan phase. You cannot use ipv4_netmask_length directly due to race conditions with terraform plan.

    # Find the pool RAM shared to your account
    data "aws_vpc_ipam_pool" "ipv4_example" {
      filter {
        name   = "description"
        values = ["*mypool*"]
      }
    
      filter {
        name   = "address-family"
        values = ["ipv4"]
      }
    }
    
    # Preview next CIDR from pool
    data "aws_vpc_ipam_preview_next_cidr" "previewed_cidr" {
      ipam_pool_id   = data.aws_vpc_ipam_pool.ipv4_example.id
      netmask_length = 24
    }
    
    data "aws_region" "current" {}
    
    # Calculate subnet cidrs from previewed IPAM CIDR
    locals {
      partition       = cidrsubnets(data.aws_vpc_ipam_preview_next_cidr.previewed_cidr.cidr, 2, 2)
      private_subnets = cidrsubnets(local.partition[0], 2, 2)
      public_subnets  = cidrsubnets(local.partition[1], 2, 2)
      azs             = formatlist("${data.aws_region.current.name}%s", ["a", "b"])
    }
    
    module "vpc_cidr_from_ipam" {
      source            = "terraform-aws-modules/vpc/aws"
      name              = "vpc-cidr-from-ipam"
      ipv4_ipam_pool_id = data.aws_vpc_ipam_pool.ipv4_example.id
      azs               = local.azs
      cidr              = data.aws_vpc_ipam_preview_next_cidr.previewed_cidr.cidr
      private_subnets   = local.private_subnets
      public_subnets    = local.public_subnets
    }
  6. Upgrade from v3.x to v4.x

    master

    When upgrading from version 3.x to 4.x, note the following breaking changes and requirement updates:

    Requirements

    • Terraform Version: Minimum required version is now 1.0.
    • AWS Provider Version: Minimum required version is now 4.x (specifically 4.35.0 or later).

    Backwards Incompatible Variable Changes

    • Removed: assign_ipv6_address_on_creation. Use the subnet-specific equivalent instead (e.g., public_subnet_assign_ipv6_address_on_creation).
    • Removed: enable_classiclink (no longer supported by AWS).
    • Removed: enable_classiclink_dns_support (no longer supported by AWS).

    Default Value Changes

    • map_public_ip_on_launch now defaults to false.
    • enable_dns_hostnames now defaults to true.
    • enable_dns_support now defaults to true.
    • manage_default_security_group now defaults to true.
    • manage_default_route_table now defaults to true.
    • manage_default_network_acl now defaults to true.
    • Outputs: The default fallback value for outputs has changed from an empty string ("") to null.

    Naming Changes

    • If a specific name is not provided, the default names for the default security group, route table, and network ACL now append -default to the VPC name.
  7. Verify VPC Block Public Access settings via AWS CLI

    master

    After deploying with Terraform, you can verify the configuration using the AWS CLI.

    To check the block public access options:

    aws ec2 --region <your-region> describe-vpc-block-public-access-options

    To check specific exclusions, first obtain the exclusion ID from your Terraform outputs, then run:

    aws ec2 --region <your-region> describe-vpc-block-public-access-exclusions --exclusion-ids <exclusion-id>
  8. Use the module wrapper with Terraform

    master

    You can use the wrapper module directly in Terraform to manage multiple VPC instances using a single module block. Use the defaults block for shared configuration and the items block to define individual instances and their unique parameters. The wrapper supports all arguments provided by the root VPC module.

    module "wrapper" {
      source = "terraform-aws-modules/vpc/aws//wrappers"
    
      defaults = {
        create = true
        tags = {
          Terraform   = "true"
          Environment = "dev"
        }
      }
    
      items = {
        my-item = {
          # any argument supported by the module
        }
        my-second-item = {
          # any argument supported by the module
        }
      }
    }