Create and Access AWS EC2 Instance with Terraform
For this exercise, we will create and access an AWS EC2 using Terraform.
Prerequisites#
- AWS account with access credentials
- Terraform
Writing Terraform configuration files#
Here we have a simple configuration file to create an EC2 instance with an Amazon Linux 2 AMI.
provider "aws" {
profile = "default"
region = "us-east-1"
}
data "aws_ami" "amzn-2" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-ebs"]
}
}
resource "aws_instance" "example" {
ami = data.aws_ami.amzn-2.id
instance_type = "t2.micro"
}
There’s a problem with this though, we can’t access this instance remotely.
Server Access via SSH Key Pair
Before launching an EC2 instance using the management console, you will see the screenshot below:
As explained in the dialog, a key pair allows you to connect to your instance securely. There are three options here: choose an existing key pair, create a new key pair, or proceed without key pair.
If you create a key pair, AWS will store the public key and will let you download the private key. It will not keep a copy of the private key. You cannot proceed without downloading the private key.
If you use an existing key pair, you have to acknowledge that you have access to the private key before you launch.
In the last option, no key pair will be added and you cannot launch the instance unless you acknowledge that you will not be able to connect unless you know the password built into the AMI.
Back to Terraform
Our terraform configuration above does not specify a key pair to use. This is an optional parameter for aws_instance resource . If this is not specified, the instance will not have a key pair which is equivalent to proceed without a key pair option when launching instances in the management console.
Add an aws_key_pair
Resource
To add a key pair to our EC2 instance, we need to create an aws_key_pair resource .
resource "aws_key_pair" "my_key" {
key_name = "my_key"
public_key = file("~/.ssh/id_rsa.pub")
}
This resource requires an existing user-supplied key pair. The config above loads the public key at ~/.ssh/id_rsa.pub in your local machine. You can also specify the public_key as a string just like the example in the documentation .
(If you do not have an existing key pair, check this link on how to create one.)
Add key_name parameter in aws_instance
After creating a key pair resource, we need to use this in our aws_instance. The key pair is defined in the key_name parameter. Updating our config:
resource "aws_instance" "example" {
ami = data.aws_ami.amzn-2.id
instance_type = "t2.small"
key_name = aws_key_pair.my_key.key_name
}
Note that the key_name parameter accepts the key_name (not ID).
Running terraform apply will create the key pair and update our instance forcing a replacement.
Great! Now we have access
Not quite yet. If we try to connect to this resource via SSH using your private key, a connection timeout will happen. We still need to grant access to SSH port 22 using a security group.
Add an aws_security_group resource in our config:
resource "aws_security_group" "example" {
name = "example"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# ALLOW ALL egress
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "example"
}
}
The security group will allow inbound access via port 22 and allow all outbound access anywhere. We then use this security group in our instance configuration:
resource "aws_instance" "example" {
ami = data.aws_ami.amzn-2.id
instance_type = "t2.small"
key_name = aws_key_pair.my_key.key_name
vpc_security_group_ids = [aws_security_group.example.id]
}
Run terraform apply to apply the changes and try it out! You should now be able to connect to your EC2 instance via SSH.