How to Launch EC2 Instance in Existing VPC using Terraform

How to Launch EC2 Instance in Existing VPC using Terraform

How to Launch EC2 Instance in Existing VPC using Terraform

Dear reader, I hope you are doing great. In one of my previous posts, I covered, how to create EC2 instance in existing VPC using CloudFormation.

Today, I will help you launch an EC2 instance in an existing VPC using Terraform. That means instead of creating a new VPC and subnet as part of EC2 creation, we will be using the existing VPC and subnet while launching our instance.

Alright?

Let’s get started.

Don’t want to miss any posts from us? join us on our Facebook group, and follow us on Facebook, Twitter, LinkedIn, and Instagram. You can also subscribe to our newsletter below to not miss any updates from us.

Prerequisite

What’s so special about creating EC2 in existing VPC?

If you launch an EC2 instance from the AWS console, you get to select VPC and a subnet in which you want to create your EC2 instance as you can see in the below screenshot.

How to Launch EC2 Instance in Existing VPC using Terraform 1

However, when you are doing it from CloudFormation or Terraform, there is no VpcId field to specify. You might wonder, how to create your instance in your desired VPC then?

In reality, It’s simple than it sounds…

SubnetId represents a VPC when creating an EC2 instance using Terraform. Therefore you need to specify the SubnetId parameter to launch the instance in VPC.

There are two places where SubnetId can be specified in an aws_instance resource.

  1. On Instance Level
  2. On the Network Interface level

Let’s understand an example for each one of these.

How Subnet Can be Specified?

As I said you can either specify subnet_id at the instance level or network interface level.

Instance Level SubnetId in

resource "aws_instance" "demo_instance" {
  subnet_id   = "subnet-825ca2e9"
  ami                    = "ami-06489866022e12a14"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.demo_sg.id]
}

or

Network Interface Level SubnetId

resource "aws_network_interface" "demo_eni" {
  security_groups = [aws_security_group.demo_sg.id]
  subnet_id   = "subnet-825ca2e9"
  tags = {
    Name = "demo_network_interface"
  }
}

resource "aws_instance" "demo_instance" {
  ami                    = "ami-06489866022e12a14"
  instance_type          = "t2.micro"
  network_interface {
    network_interface_id = aws_network_interface.demo_eni.id
    device_index         = 0
  }
}

Where to specify SubnetId?

Have you got the requirement to attach a network interface to your instance?

Yes? -> Use SubnetId on the interface level

No? -> Use SubnetId on the instance level

Please note that only one out of two can be specified. If you try to use SubnetId on the instance level as well as the network interface level. You will get the below error-

Error: Conflicting configuration arguments

with aws_instance.demo_instance,
on main.tf line 62, in resource “aws_instance” “demo_instance”:
62: resource “aws_instance” “demo_instance” {

“network_interface”: conflicts with subnet_id

How to Launch EC2 Instance in Existing VPC using Terraform 3

Important Note:

If you have specified a network interface, you have to specify your security group at the interface level only. Specifying at the instance level or at both places will give the below error.


Error: Conflicting configuration arguments

with aws_instance.demo_instance,
on main.tf line 62, in resource “aws_instance” “demo_instance”:
62: resource “aws_instance” “demo_instance” {

“network_interface”: conflicts with vpc_security_group_id

Therefore, always keep in mind below points-

  • Using Network Interface -> Use security_groups parameter on the network interface level
  • Not using Network Interface -> Use vpc_security_group_ids parameter on the instance level

Now that we know the basics, let’s go ahead and create an EC2 instance in my existing VPC.

What we are gonna need?

The subnet Id of our existing VPC 🙂

Before we proceed, let’s see how we can create a resource on AWS using Terraform.

How Do You Create a Resource Using Terraform on AWS?

Unlike CloudFormation, you need to install Terraform in your system before you can use it to create a resource on your cloud provider for example Amazon EC2.

Once installed, you configure the way to authenticate with AWS. Then you create your configuration file(filename.tf – they have .tf extension) and use the below set of commands to deploy your resources.

$ terraform init
$ terraform plan
$ terraform apply
$ terraform destroy

I highly recommend you check my step-by-step guide to help you get started with Terraform on AWS in the right way. Here is the link-

Once you go through that post you will already have an idea on-

  • Installing Terraform
  • Creating a Terraform IAM user
  • Setting up AWS CLI to allow Terraform to authenticate to AWS
  • Setting up your workspace using Visual Studio Code(VS Code) IDE
  • Deploying Your First Resource on AWS using Terraform

By this time, I assume you already know how to deploy a resource on AWS using Terraform.

Alright, let’s get started with EC2 Instance creation in an existing VPC and subnet.

Steps to Launch EC2 Instance in Existing VPC using Terraform

  1. Create a Working Directory/Folder
  2. Create your EC2 Instance Configuration File
  3. Initialize Your Directory to Download AWS Plugins
  4. Plan and Deploy

Step 1: Create a Working Directory/Folder

Create a folder in which you’ll keep your terraform configuration file for your EC2 instance.

This is where we’ll keep our configuration file as you can see.

Step 2: Create Configuration File for EC2 instance

Navigate inside the folder and create a new file. You can name it as per your wish, but to keep things simple, I will name it main.tf. All we need to ensure here is that it ends with .tf extension indicating that it’s a terraform file.

I started with a provider declaration specifying that we are using AWS provider. Also, it specifies the credential profile that will be used to authenticate to AWS and the region in which resources are to be created by default.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  required_version = ">= 0.14.9"
}

#Provider profile and region in which all the resources will create
provider "aws" {
  profile = "default"
  region  = "ap-south-1"
}

Now let’s add an EC2 instance in the existing VPC. As we discussed above, here are two different configuration files based on possibilities.

1. With Network Interface

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }
}

provider "aws" {
  profile = "default"
  region  = "ap-south-1"
}

resource "aws_security_group" "demo_sg" {
  name        = "demo_eni_sg"
  description = "Demo Security Group for CK"

  ingress {
    description = "Allow Inbound HTTP"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "Allow Inbound HTTPS"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "Allow SSH"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

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

  tags = {
    Name = "demo-sg"
  }
}

resource "aws_network_interface" "demo_eni" {
  security_groups = [aws_security_group.demo_sg.id]
  subnet_id   = "subnet-825ca2e9"
  tags = {
    Name = "demo_network_interface"
  }
}

resource "aws_instance" "demo_instance" {
  ami                    = "ami-06489866022e12a14"
  instance_type          = "t2.micro"
  network_interface {
    network_interface_id = aws_network_interface.demo_eni.id
    device_index         = 0
  }
}

2. Without Network Interface

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }
}

provider "aws" {
  profile = "default"
  region  = "ap-south-1"
}

resource "aws_security_group" "demo_sg" {
  name        = "demo_eni_sg"
  description = "Demo Security Group for CK"

  ingress {
    description = "Allow Inbound HTTP"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "Allow Inbound HTTPS"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "Allow SSH"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

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

  tags = {
    Name = "demo-sg"
  }
}

resource "aws_instance" "demo_instance" {
  subnet_id   = "subnet-825ca2e9"
  ami                    = "ami-06489866022e12a14"
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.demo_sg.id]
}

Take anyone from the above configuration file. Change the ami, subnet_id, instance_type and security group details as per your need. And save the file. We are ready to deploy.

Step 3: Initialize Your Directory to Download AWS Plugins

Every time you create a new terraform project, you need to initialize the folder/directory. This basically means you are downloading relevant codes/plugins for your mentioned provider which in our case is AWS. We will use terraform init command for the same.

terraform init

Hit enter and you will see-

How to Launch EC2 Instance in Existing VPC using Terraform 2

Your wording directory gets initialized with the provider-related code and is ready to deploy a resource.

Step 4: Plan and Deploy the EC2 Instance

The configuration file is created and the directory is initialized. That means we are all ready to deploy our instance in the existing VPC.

Now, if you want, you can run the command terraform plan to see what’s actually being created.

terraform plan

Using terraform plan shows what you are going to create. However, to keep things simple, I just run terraform apply. Ideally, terraform runs terraform plan every time you hit the command terraform apply. Once you review the plan and confirm yes then only resources will be created.

Terraform will look for .tf file and show you what’s being created.

Review the output and if all is fine say yes to the instance creation.

Once you terraform apply and hit enter, within a few seconds your EC2 instance with ENI gets created in the existing VPC you need tor subnet you have provided.

successful Ec2 with ENI in VPC

Clean Up

Finally, if you are doing this exercise for learning purposes, you can clean up by destroying the created resource.

terraform destroy

Type yes, and hit enter

Once you hit enter, your resources get destroyed. Once done, this is how you see the destruction complete message.

destroyed

Conclusion:

In this post, we learnt to launch EC2 instance in existing VPC using Terraform. We also learnt some important points such as-

  • subnet_id represents a VPC when creating an instance
  • subnet_id can go either with instance or interface.
  • You can not specify the subnet at the instance and interface level. When you have a network interface, it must go with the interface.
  • Similarly, the security group goes with the network interface as well in case one is there.

I hope you found this post helpful. Feel free to drop your questions in the comment section.

Enjoyed the content?

Subscribe to our newsletter below to get awesome AWS learning materials delivered straight to your inbox.

Don’t forget to motivate me by-

  • Adding a comment below on what you liked and what can be improved.
  • Follow us on
  • Share this post with your friends

Suggested Read:

Leave a Reply

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