8
votes

Using terraform v0.12.21 and the AWS provider v2.51.0, I'm trying to create some infrastructure from scratch (no previous terraform state).

The goal is to have some publicly-accessible EC2 instances in a single VPC, and I think these are the resources I'd need to accomplish that:

  • VPC
  • Internet gateway in the VPC
  • Subnet in the VPC
  • Route table in the VPC to connect the subnet to the internet gateway
  • Route table association to connect the subnet to the route table
  • A security group in the VPC, which will be set for the instances
  • Multiple EC2 instances

Using this terraform config:

locals {
  office_cidr = ["x.x.x.x/32", "x.x.x.x/32"]
}

provider "aws" {
  region  = var.region
  version = "~> 2.51"
}

resource "aws_vpc" "main" {
  cidr_block       = "10.0.0.0/16"
  instance_tenancy = "default"
}

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id
}

resource "aws_subnet" "main" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
}

resource "aws_route_table" "r" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = aws_subnet.main.cidr_block
    gateway_id = aws_internet_gateway.gw.id
  }
}

resource "aws_route_table_association" "a" {
  subnet_id      = aws_subnet.main.id
  route_table_id = aws_route_table.r.id
}


resource "aws_security_group" "allow_http" {
  name        = "security group"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = local.office_cidr
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = local.office_cidr
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = local.office_cidr
  }
}

resource "aws_instance" "a" {
  ami                         = "ami-xxxxxxxxxxxxxxxxx"
  instance_type               = "t2.micro"
  vpc_security_group_ids      = ["${aws_security_group.allow_http.id}"]
  subnet_id                   = aws_subnet.main.id
  associate_public_ip_address = true
}
resource "aws_instance" "b" {
  ami                         = "ami-xxxxxxxxxxxxxxxxx"
  instance_type               = "t2.micro"
  vpc_security_group_ids      = ["${aws_security_group.allow_http.id}"]
  subnet_id                   = aws_subnet.main.id
  associate_public_ip_address = true
}

When I plan it everything seems OK (only showing the aws_route_table part of the plan output here):

# aws_route_table.r will be created


 + resource "aws_route_table" "r" {
      + id               = (known after apply)
      + owner_id         = (known after apply)
      + propagating_vgws = (known after apply)
      + route            = [
          + {
              + cidr_block                = "10.0.1.0/24"
              + egress_only_gateway_id    = ""
              + gateway_id                = (known after apply)
              + instance_id               = ""
              + ipv6_cidr_block           = ""
              + nat_gateway_id            = ""
              + network_interface_id      = ""
              + transit_gateway_id        = ""
              + vpc_peering_connection_id = ""
            },
        ]
      + vpc_id           = (known after apply)
    }

The aws_subnet.main.cidr_block input for the cidr_block in the route interpolates to "10.0.1.0/24".

But when I apply I get this error:

Error: Error creating route: InvalidParameterValue: Route target is not supported. This route only supports interface and instance targets.
status code: 400, request id: a303e768-69e2-4af0-88d4-e97ebcaeae5d

  on main.tf line 38, in resource "aws_route_table" "r":
  38: resource "aws_route_table" "r" {

By "interface target" is it referring to a network interface? If so, is a network interface automatically created when the VPC is created, or should I be creating a aws_network_interface resource as well and connect the internet gateway to that instead?

Basically, I'd like to know the best practice for creating instances on a subnet which need to have public IP addresses and be publicly accessible, whether any of my resources are not needed, and if I am missing any resources that would typically be included.

But for the purposes of this question: how should I change the aws_route_table resource block, and any other resource blocks, to resolve this error and make it so that my instances can be publicly-accessible?

2

2 Answers

6
votes

If in the route you use internet gateway gateway_id = aws_internet_gateway.gw.id, for such route cidr_block must be 0.0.0.0/0 but not aws_subnet.main.cidr_block

3
votes

change cidr_block to use "0.0.0.0/0" instead of "10.0.1.0/24" work for me. like this :

resource "aws_route_table" "prod-rt" {
vpc_id = aws_vpc.prod-vpc.id

route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.prod-gw.id
}

route {
ipv6_cidr_block        = "::/0"
gateway_id = aws_internet_gateway.prod-gw.id
}

tags = {
Name = "prod-rt"
}
}