Setting Up Infrastructure on AWS With Terraform (Part 1)

Posted on 21 November 2022 Reading time: 7 min read
Setting Up Infrastructure on AWS With Terraform (Part 1)

This primer is written to help those new to Infrastructure-as-code get their feet wet, setting up infrastructure with Terraform on AWS

Infrastructure as code (iaC) allows the person responsible for building servers and provisioning the server with everything that it needs to function. It also let’s you define every step that is required to set up resources in a way that can be easily readable. One major advantage of iaC over normal ways of provisioning infrastructure is that it allows the author (s) to define all the resources to be created, changed or destroyed only once and used to create the required resources multiple times to create one, a dozen, hundred or thousands of resources.

Another major advantage of using iaC over conventional means of creating infrastructure is that rather than relying on someone’s notes, which may change over time or get missing, configurations can be saved into version control and share among individuals or teams.

Terraform

According Terraform’s own documentation,

Terraform is HashiCorp’s infrastructure as code tool. It lets you define resources and infrastructure in human-readable, declarative configuration files, and manages your infrastructure’s lifecycle. Using Terraform has several advantages over manually managing your infrastructure.

Installation

Please see link to install Terraform in your operating system https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)

Building Our First Infrastructure on AWS

In this first exercise, we will be provisioning an EC2 instance on AWS. An EC2 instance on AWS is a virtual machine that can run any service and it is based on images available for different operating systems. For this exercise, we will be building an Ubuntu based EC2 instance.

To follow along, you need to have installed Terraform. Verify that this is running by executing this command in your terminal.

terraform —version

Make sure that the version is the most recent version. At the time of this writing, the current version is 1.3.5. Also make sure that you have installed the AWS cli tool and have configured your aws credentials. With that out of the way, let’s get started!

Create a folder in a location you can easily remember and change directory to that location. For beginners, I recommend a code editor like VSCode and also recommend that you install the official Terraform plugin. This will make things easier for you, I promise!

Let’s write our first terraform configuration and I will try to explain as we go along.

In the new folder you created, create a file called main.tf

  terraform {
    required_providers {
      aws = {
        source  = "hashicorp/aws"
        version = "~> 4.16"
      }
    }
  
    required_version = ">= 1.0.11"
  }
  
  provider "aws" {
    region  = "eu-west-2"
  }
  
  resource "aws_instance" "web_server" {
    ami           = "ami-04842bc62789b682e"
    instance_type = "t2.micro"
  
    tags = {
      Name = "ExampleWebServer"
    }
  }

The terraform block contains the settings that Terraform will use to provision your infrastructure. The most important item here is the required_providers. This is used to tell Terraform which provider to use and will determine where your resources will be created. In this case, we want to create an EC2 instance in AWS so our provider is aws as declared in the terraform block. The provider is a plugin which Terraform uses to create and manage our resources. The resource block takes two arguments; r_esource type_ and resource name. In our example above, our resource type is aws_instance and the resource name is web_server

The first thing we have to do is to initialise the directory in which we have created our terraform project. This allows Terraform to download and install the providers which we have defined in our configuration - in this case, aws

From the command line, run the following command;

terraform init

If all goes well, you should see something that looks like the following;

Initializing the backend…

Initializing provider plugins…

- Finding hashicorp/aws versions matching ”~> 4.16”…

- Installing hashicorp/aws v4.40.0…

- Installed hashicorp/aws v4.40.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider

selections it made above. Include this file in your version control repository

so that Terraform can guarantee to make the same selections by default when

you run “terraform init” in the future.

Terraform has been successfully initialized!

Whoop! We are now on our way to creating our first resource. To ensure that your configuration syntax is correct, you can run the following command;

terraform-primer terraform validate
    
Success! The configuration is valid.

Next we tell terraform to apply our configuration with the apply command. This should come as no surprise since Terraform uses declarative commands;

terraform apply

Once we run the above command, terraform will print out it’s execution plan. It tells you what actions it will take to create the infrastructure that you have defined in your configuration. It will however request that you confirm if you are happy with the changes. If you confirm, it goes ahead and makes the changes but if you decline, it will not make any change.

Let’s go ahead and confirm that we are happy with the execution plan.

If all goes well, you should see the following;

aws_instance.web_server: Creating…

aws_instance.web_server: Still creating… [10s elapsed]

aws_instance.web_server: Still creating… [20s elapsed]

aws_instance.web_server: Still creating… [30s elapsed]

aws_instance.web_server: Creation complete after 32s [id=i-0df0104334a4d8fc1]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Whoop! You have just created your first Infrastructure on AWS! Log in to your AWS console, navigate to your EC2 page and you should see your ExampleWebServer already running.

One important thing to note here. When you executed terraform apply terraform created a terraform.tfstate in your directory. This is what terraform uses to track changes to your infrastructure so be careful not to delete this file! Ideally it is always better to store terraform state in a remote storage like AWS S3 especially when working in a team but that is beyond the scope of this primer. You can inspect current state by running terraform show

Another great feature of terraform is that because it keeps track of what was created, when you run the terraform destroy command it removes all the resources that it created according to your configuration. This means if you have other resources that you created outside of terraform, they will remain untouched.

Configuration Changes

Let’s make a change to the configuration above and let’s see how terraform handles that. Our EC2 instance was created with Ubuntu 20.04 which was configured in our resource using its ami but we’ve decided that we want to upgrade to Ubuntu 22.04. What do we do? Easy! All we need to do is change the image id to ami-0f540e9f488cfa27d which is for Ubuntu 22.04.

Once you have changed it, run terraform apply again. Terraform will create another execution plan telling you the changes it wants to make. In this case, it will destroy our current EC2 instance and replace it with a new one provisioned with the new AMI that we configured

Destroy Infrastructure As mentioned earlier, because Terraform keeps track of its state, when you decide to remove all the resources you created, it only removes what it created based on your configuration. Let’s go ahead and remove the EC2 instance we created. Run the command terraform destroy

You should see the execution plan and the summary;

Plan: 0 to add, 0 to change, 1 to destroy.

Once you confirm, terraform will go ahead and remove the EC2 instance we created.

We have only just scratched the surface of what we can do with terraform. In the next part of this series, we will explore provisioning multiple EC2 instances with a load balancer.