Terraform Basics Part 1
Creating EC2 instances in a managed way using terraform
Intro
In this blog we are going to take a look at Terraform. Terraform is tool that enables you to manage your cloud infrastructure in an auditable and programmatic way. In this initial post we are going to go through the most basic application, creating and spinning up an EC2 instance. Future posts will build on this for other applications
Many people think Terraform is just a bunch of config files, but rather than thinking of it as config files it is more helpful to think of it as a programming language. You can define lists, maps (similar to python dictionaries), strings, and perform actions using values in those variables.
Variables
For example, Here's how I could define a map, where I may store different ami's for different region.
variable "AMIS" {
type = map(string)
default = {
us-east-1 = "ami-0ac80df6eff0e70b5",
us-east-2 = "ami-31432143214213435"
}
}
Then in terrarorm console get that value using:
var.AMIS.us-east-1
So this is how we can get and store different configuration options. But Terraform is not just variables. You also have ways of running your code to deploy things. For example terraform plan
shows you what it would do if you deployed. terraform apply
deploys your options and terraform destroy
destroys all your infrastructure defined.
But what is it applying? So far all we have done is define a variable. Let's define an EC2 instance.
Actions
resource "aws_instance" "web" {
ami = "${lookup(var.AMIS, var.AWS_REGION)}"
instance_type = "t2.micro"
}
From the above we can see we have most of what we need to launch an EC2 instance. We define an AMI by looking up the AWS_Region variable from the AMIS variable we defined above.
Full EC2 setup
You may have noticed, there's a few things missing from the above. For example, how does it connect to AWS? How do you give it the credentials without putting them in github? We will create 4 files that gets a good organized setup for the full thing.
- instance.tf: This will be the actual command that defined the EC2 instance we want to create
- vars.tf: We can define all the variables we will need here
- provider.tf: This will have the command needed to connect to our AWS account
- terraform.tfvars: This will store our aws credentials
vars.tf
First we will define all the variables we need. You may notice I do not put any values in the the credentials. This is on purpose - best practice is to keep access keys out of github. We will define these in a different file.
You can see we also set a default AWS_REGION as well as AMIs to use. I am only setting 1, but you can make as complicated of a map variable as you want with multiple regions, different types of instances (maybe a Deep learning ami, and a random forest ami, and a generally compute ami).
variable "AWS_ACCESS_KEY" {}
variable "AWS_SECRET_KEY" {}
variable "AWS_REGION" {
default = "us-east-1"
}
variable "AMIS" {
type = map(string)
default = {
us-east-1 = "ami-0ac80df6eff0e70b5"
}
}
terraform.tfvars
This is a pretty simple file where we define the values for our credentials. The important thing is to add this file to the gitignore so that it does not get put in the github reposity (for security reason). It just holds your credentials, for example it may be.
AWS_ACCESS_KEY = "ABCDE12345FGHI6789"
AWS_SECRET_KEY = "abc123def456+789ghi983klm
instance.tf
Now finally we are ready to launch our instance. We have our region, our credentials, and are connected to aws. Naturally we could have 100 different instances defined in this same way for different regions and instance types and it will automatically create them all, but for now we will just create 1 and stay within the free-tier.
resource "aws_instance" "web" {
ami = "${lookup(var.AMIS, var.AWS_REGION)}"
instance_type = "t2.micro"
}
You will notice I am using the lookup funciton. This is looking up the var.AWS_REGION from the var.AMIS variable. We set the default region to us-east-1 in the vars.tf file. And it uses that to lookup that key in the AMIS variable, which is a map of strings.