How to create aws_instance with existing VPC?

Viewed 2323

Is it possible to create an EC2 instance while reusing already existing VPC?

Running the following code yields Error launching source instance: VPCIdNotSpecified: No default VPC for this user. GroupName is only supported for EC2-Classic and default VPC. (status code: 400):

data "aws_security_groups" "my_tib_sg" {
  tags = {
    Name = "my-security-group"
  }
}

resource "aws_instance" "nginx" {
  ami                    = data.aws_ami.aws-linux.id
  instance_type          = "t2.micro"
  key_name               = var.key_name
  vpc_security_group_ids = [data.aws_security_groups.my_tib_sg.id]

  # more, irrelevant stuff...
}

FWIU from the error, the aws_instance block requires a reference to my VPC, which basically exists in my security group. Besides, I can't find a way to refer a VPC in an aws_instance block.

Updating code per answers:

I updated the code per answers below:

data "aws_security_groups" "my_tib_sg" {
  tags = {
    Name = "my-tib-sg"
  }
}

data "aws_subnet" "my_subnet" {
  tags = {
    Name = "my-tib-subnet-1"
  }
}

resource "aws_network_interface" "my_ani" {
  subnet_id = data.aws_subnet.my_subnet.id
  private_ips = ["10.0.0.10"]

  tags = {
    Name = "my-tib-ani"
    by = "TF_TF"
  }
}

resource "aws_instance" "nginx" {
  ami                    = data.aws_ami.aws-linux.id
  instance_type          = "t2.micro"
  key_name               = var.key_name
  vpc_security_group_ids = [data.aws_security_groups.my_tib_sg.id]

  network_interface {
    network_interface_id = aws_network_interface.my_ani.id
    device_index = 0
  }

  connection {
    type        = "ssh"
    host        = self.public_ip
    user        = "ec2-user"
    private_key = file(var.private_key_path)

  }

  provisioner "remote-exec" {
    inline = [
      "sudo yum install nginx -y",
      "sudo service nginx start"
    ]
  }
}

But the error changes to "network_interface": conflicts with vpc_security_group_ids.

(needless to mention: both my_subnet and my_tib_sg use same VPC)

3 Answers

I typically use the subnet_id parameter, directly on the aws_instance resource:

data "aws_security_groups" "my_tib_sg" {
  tags = {
    Name = "my-tib-sg"
  }
}

data "aws_subnet" "my_subnet" {
  tags = {
    Name = "my-tib-subnet-1"
  }
}

resource "aws_instance" "nginx" {
  ami                    = data.aws_ami.aws-linux.id
  instance_type          = "t2.micro"
  key_name               = var.key_name
  vpc_security_group_ids = [data.aws_security_groups.my_tib_sg.ids[0]]

  # specify the subnet_id here
  subnet_id              = data.aws_subnet.my_subnet.id

  # more, irrelevant stuff...
}

Yes, you can add a new EC2 instance to an existing VPC.

You should provide the subnet_id to aws_instance. You would typically pass that into Terraform as a parameter, rather than hard-coding its value into your template.

Note: the subnet ID implicitly indicates the actual VPC (because a subnet only exists in one VPC).

Is it possible to create an EC2 instance while reusing already existing VPC?

yes you can create an ec2 instance with an existing VPC. You can use a Data Source: aws_vpc to query existing VPC and then further reference the same in your resource like Resource: aws_instance below:

variable "vpc_id" {}

data "aws_vpc" "selected" {
  id = var.vpc_id
}

resource "aws_subnet" "example" {
  vpc_id            = data.aws_vpc.selected.id
  availability_zone = "us-west-2a"
  cidr_block        = cidrsubnet(data.aws_vpc.selected.cidr_block, 4, 1)
}

resource "aws_security_group" "allow_tls" {
  name        = "allow_tls"
  description = "Allow TLS inbound traffic"
  vpc_id      = data.aws_vpc.selected.id

  ingress {
    description = "TLS from VPC"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [aws_vpc.main.cidr_block]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "allow_tls"
  }
}

resource "aws_network_interface" "foo" {
  subnet_id   = aws_subnet.example.id
  private_ips = ["172.16.10.100"]
  security_groups = [aws_security_group.allow_tls.id]

  tags = {
    Name = "primary_network_interface"
  }
}


resource "aws_instance" "foo" {
  ami           = "ami-005e54dee72cc1d00" # us-west-2
  instance_type = "t2.micro"

  network_interface {
    network_interface_id = aws_network_interface.foo.id
    device_index         = 0
  }

  credit_specification {
    cpu_credits = "unlimited"
  }
}
Related