Create an Elastic Container Cluster on AWS with Terraform — Part 1
When I first joined Tourlane and started learning about AWS I had an information overload. There were so many terms and acronyms like: VPC, subnet, security groups, IAM roles, load balancer, ECS and way more. It took me some time to get used to them and Terraform helped me with that.
Terraform is an amazing tool from Hashicrop for configuring and launching infrastructure across a variety of providers. It enables you to manage your infrastructure as code, that is consistent and can be reused for building complicated infrastructure, such a elastic container cluster(ECS) on AWS.
In this post we will cover the first steps for creating an ECS. Before we begin, make sure to install the Terraform CLI.
This blog post will be in two parts, in this first one we will explain how to:
- Create an Amazon Virtual Private Cloud (VPC)
- Create an Internet Gateway
- Create a Public Subnet
- Create a Routing Table
- Associate the Routing Table to the Subnet
- Create Security groups for the VPC
Before we start provisioning our VPC we need to create a directory (let’s called it ecs-test
) where will host our terraform code, and inside it we will create a file (let’s call itmain.tf
) for writing our first terraform script.
Configure provider, region and save terraform state on the cloud
Before we start writing our resources we should provide credentials via the AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
, environment variables, representing our AWS Access Key and AWS Secret Key, respectively.
$ export AWS_ACCESS_KEY_ID="anaccesskey"
$ export AWS_SECRET_ACCESS_KEY="asecretkey"
Then, we use AWS as a provider and set our region to eu-west-1
, by adding those lines on the top of the file.
provider "aws" {
region = "eu-west-1"
}
It is very important, especially when you are working within a team, to save the terraform state in the cloud so everyone can access it. In our case we will store it on a S3 bucket called terraform
with the key ecs-test
by adding the following commands.
terraform {
backend "s3" {
bucket = "terraform"
key = "ecs-test"
region = “eu-west-1”
}
}
Create our VPC
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags {
Name = "test"
}
}
All terraform code has the above format, we specify a recourse we want to provision, we provide a name and a block with all the attributes.
In this case, We specified the resource to be aws_vpc
with the name main
. The only setting required for creating the VPC is to specify a cidr_block
. At the end we optionally tag our resource with the name test
. We will use test
as a tag in all resources in this post, so we can quickly pull up all of the resources related to these Terraform scripts within AWS.
Next step is, to create an Internet Gateway. This will allow us to create an interface between our VPC and the internet.
resource "aws_internet_gateway" "main-gw" {
vpc_id = "${aws_vpc.main.id}"
tags {
Name = "test"
}
}
As you can see we are linking our internet getaway to our VPC by using the Terraform’s variable format ${aws_vpc.main.id}
. The order of the resource doesn’t matter, terraform is smart enough to handle all the dependencies.
Next step, is to create a Subnet so our ECS cluster will have container instances registered to it.
resource "aws_subnet" "main" {
vpc_id = "${aws_vpc.main.id}"
cidr_block = "10.0.1.0/24"
tags {
Name = "test"
}
map_public_ip_on_launch = true
}
We link again our VPC, we define a cidr_block
and we map map_public_ip_on_launch= true
to indicate that instances that will be launched into the subnet will be assigned a public IP address.
The next step is to create a route table.
resource "aws_route_table" "main" {
vpc_id = "${aws_vpc.main.id}"
route {
cidr_block = "0.0.0.0/0"
gateway_id = "${aws_internet_gateway.main-gw.id}"
}
tags {
Name = "test"
}
}
Now, we are more used of Terraform’s syntax, so we can clearly see that we are linking again the VPC, and we create a router block to route all the request to our internet gateway.
The next step for creating our VPC is to associate our route table with our Subnet, after this point we are almost ready.
resource "aws_route_table_association" "main" {
subnet_id = "${aws_subnet.main.id}"
route_table_id = "${aws_route_table.rt.id}"
}
The last step is to Create security groups for our VPC, we will create 3 security groups. That they will allow:
- Our VPC to have access to the internet.
- All incoming traffic to our VPC.
- All the traffic inside our VPC.
resource "aws_security_group" "internet" {
name = "internet"
description = "Allow access to internet"
vpc_id = "${aws_vpc.main.id}"
egress {
from_port = 0
to_port = 0
protocol = -1
cidr_blocks = ["0.0.0.0/0"]
}
}resource "aws_security_group" "incoming" {
name = "incoming"
description = "Allow all incoming trafic"
vpc_id = "${aws_vpc.main.id}"
ingress {
from_port = 0
to_port = 0
protocol = -1
cidr_blocks = ["0.0.0.0/0"]
}
}resource "aws_security_group" "local" {
name = "local"
description = "Allow trafic from itself"
vpc_id = "${aws_vpc.main.id}"
ingress {
from_port = 0
to_port = 0
protocol = -1
self = true
}
egress {
from_port = 0
to_port = 0
protocol = -1
self = true
}
}
We have already created all the resource, and now our infrastructure looks like the following:
Run our script
We wrote all the terraform code that we needed, but that is not enough. We need to apply those changes to see the results.
First cd
to the directory you created earlier, and run $ terraform init
for initialising our terraform project. Second step, is to check if everything set up correctly by running $ terraform plan
.
Everything should be fine, we have no errors so lets apply our changes by executing the command $ terraform apply
That was it!!!
In few minutes and with few lines of code we provision and configure out VPC and all the related resources on AWS with Terraform.
Important: The most common mistake when we are writing terraform code, we forget to commit and push code to our version control system. Don’t forget that especially when you are working within a team.
Part 2 is coming soon…