This post is about provisioning Amazon Web Services EC2 instances using Terraform IaaS, we can create reproducible infrastructure for Dev, UAT, SIT, and Production environments using automation of Terraform scripts. Terraform allows you to split your configuration into as many files as you wish.
We can execute these same scripts against multiple clouds providers, Microsoft Azure, Amazon Web Services, GCP etc. Terraform as infrastructure as code tool, makes this task simple and easy to perform. We can use Terraform to use Infrastructure as Code to provision and manage any cloud, infrastructure, or service.
Terraform infrastructure is configured and provision using language, HCL – HashiCorp Configuration Language. Below are the most commonly used commands by HCL infra provisioning.
Commands | Purpose |
INIT | Initialize the working directory |
PLAN | To execute the plan for the resources managed by .tf files |
APPLY | Build or changes the infrastructure as code which is defined |
VERSION | Prints of the Terraform versions |
DESTROY | Destroy the infrastructure managed by Terraform |
VALIDATE | Validate the terraform files against the targetted schema |
GRAPH | Outputs the visual graph of Terraform resources. |
There can be multiple reason for the client to go for Multi-Cloud approach:-
- Cost Considerations,
- Vendor diversity,
- Vendor leverage,
- Desire to use unique services,
- Need for a particular region [Low latency],
Prerequisites
- Install AWS Command Line Interface from here – https://aws.amazon.com/cli/
- AWS – Access Key and Secret keys for your account. – https://aws.amazon.com/iam/
- Install Azure CLI from here from – https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
- Install VS Code – optional
- Download Terraform binaries, I have installed windows binaries 64 bits.
Once you download terraform binaries, please ensure to have environment variables setup. I have set up my variables, considering I have placed binary in the C folder. Run a version check on the command prompt in the below screenshot.


Implementation – Demo for AWS provisioning
To keep the length of the post limited, since most of the code is very similar. I will limit this demo to AWS. The similar approach can be adopted for Azure. Terraform has separate providers for Microsoft Azure and they can be used to configure infrastructure in Microsoft Azure using the Azure Resource Manager API’s.
More info here – https://www.terraform.io/docs/providers/azurerm/index.html
This configuration provisions infrastructure on Amazon Web Service. I will post the .tf file below for AWS which needed to be executed using AWS access keys and secret access keys.
I have added Azure Terraform plugin, as a Visual Studio Code plugin for IntelliSense but you can use any other tool for the same.

Note – AWS Access Key and AWS Secret Access Key should be configured on the host running this Terraform configuration.
export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Below is the code required to provision for AWS provider:-
provider “aws” {
region = “eu-west-1”
}
module “aws_vpc” {
source = “terraform-aws-modules/vpc/aws”
version = “1.5.1”
name = “${var.configuration_name}-vpc”
cidr = “10.0.0.0/16”
enable_dns_hostnames = true
enable_dns_support = true
azs = [“eu-west-1a”, “eu-west-1b”, “eu-west-1c”]
public_subnets = [“10.0.101.0/24”, “10.0.102.0/24”, “10.0.103.0/24”]
}
module “aws_asg” {
source = “terraform-aws-modules/autoscaling/aws”
version = “2.0.0”
name = “${var.configuration_name}-asg”
image_id = “${data.aws_ami.amazon_linux.id}”
instance_type = “t2.nano”
security_groups = [“${aws_security_group.sg.id}”]
user_data = “${data.template_file.web_server_aws.rendered}”
load_balancers = [“${module.aws_elb.this_elb_id}”]
root_block_device = [
{
volume_size = “8”
volume_type = “gp2”
},
]
vpc_zone_identifier = “${module.aws_vpc.public_subnets}”
health_check_type = “EC2”
min_size = 3
max_size = 3
desired_capacity = 3
wait_for_capacity_timeout = 0
}
module “aws_elb” {
source = “terraform-aws-modules/elb/aws”
version = “1.4.1”
name = “elb”
subnets = [“${module.aws_vpc.public_subnets}”]
security_groups = [“${aws_security_group.sg.id}”]
internal = false
listener = [
{
instance_port = “80”
instance_protocol = “HTTP”
lb_port = “80”
lb_protocol = “HTTP”
},
]
health_check = [
{
target = “HTTP:80/”
interval = 30
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 5
},
]
}
resource “aws_security_group” “sg” {
name = “${var.configuration_name}-sg”
description = “security group for ${var.configuration_name}”
vpc_id = “${module.aws_vpc.vpc_id}”
ingress {
from_port = 80
to_port = 80
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}
egress {
from_port = 0
to_port = 65535
protocol = “udp”
cidr_blocks = [“0.0.0.0/0”]
}
egress {
from_port = 0
to_port = 65535
protocol = “tcp”
cidr_blocks = [“0.0.0.0/0”]
}
}
data “aws_ami” “amazon_linux” {
most_recent = true
filter {
name = “name”
values = [“amzn-ami-hvm-*-x86_64-gp2”]
}
filter {
name = “owner-alias”
values = [“amazon”]
}
}
data “template_file” “web_server_aws” {
template = “${file(“${path.module}/web-server.tpl”)}”
vars {
cloud = “aws”
}
}
data “aws_availability_zones” “available” {
state = “available”
}
Commands to be executed for Terraform.
- Initialise Terraform :
terraform init
- Execute a plan :
terraform plan -out=1.tfplan
- Execute an Apply :
terraform apply 1.tfplan
- Destroy if you are done with the task in hand and you no longer need the resources.
Upcoming Demo – Azure provisioning
This is pending for another post, I will put this as demo with screenshots in a separate post.