Getting Started with Terraform

Now that we have Terraform installed, let us see what it is actually capable of. Terraform is an Infrastructure automation tool and works with AWS, GCP (Google Cloud), Azure, Alibaba Cloud etc

For working with different platforms, Terraform actually uses plugins and providers. These allow for Terraform access to your cloud infrastructure

As an example, for accessing my AWS infrastructure, I will be creating a *.tf file with the provider info

My *.tf file looks like this

cat aws.tf 
provider "aws" {
access_key = "My_Access_Key"
secret_key = "My_Secret_Key"
region = "My_Region"
}
resource "aws_instance" "example" {
ami = "ami-b374d5a5"
instance_type = "t2.micro"
}

Points to note:

  • aws.tf is my file that I created
  • provider “aws” tells Terraform what provider to use
  • access_key and secret_key allow Terraform access to my AWS instance
  • region is the region on AWS where my infrastructure is located
  • I am creating an EC2 instance using the ami “ami-b374d5a5”
  • The instance type is t2.micro

Now, once I save the file, I am free to run the file. This will essentially use the aws provider, access AWS in the specified region using the access_key and secret_key, and create an EC2 instance of type t2.micro using the ami that is specified! Pretty cool!

Let’s see this in action

ayan@Epoch:~/terraform$ terraform apply An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols:   + create Terraform will perform the following actions:   + aws_instance.example       id:                           <computed>       ami:                          "ami-b374d5a5"       arn:                          <computed>       associate_public_ip_address:  <computed>       availability_zone:            <computed>       cpu_core_count:               <computed>       cpu_threads_per_core:         <computed>       ebs_block_device.#:           <computed>       ephemeral_block_device.#:     <computed>       get_password_data:            "false"       host_id:                      <computed>       instance_state:               <computed>       instance_type:                "t2.micro"       ipv6_address_count:           <computed>       ipv6_addresses.#:             <computed>       key_name:                     <computed>       network_interface.#:          <computed>       network_interface_id:         <computed>       password_data:                <computed>       placement_group:              <computed>       primary_network_interface_id: <computed>       private_dns:                  <computed>       private_ip:                   <computed>       public_dns:                   <computed>       public_ip:                    <computed>       root_block_device.#:          <computed>       security_groups.#:            <computed>       source_dest_check:            "true"       subnet_id:                    <computed>       tenancy:                      <computed>       volume_tags.%:                <computed>       vpc_security_group_ids.#:     <computed> Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions?   Terraform will perform the actions described above.   Only 'yes' will be accepted to approve.   Enter a value: 

Now, we need to type in “yes” and check the AWS infra build itself!

Enter a value: yes aws_instance.example: Creating...   ami:                          "" => "ami-b374d5a5"   arn:                          "" => "<computed>"   associate_public_ip_address:  "" => "<computed>"   availability_zone:            "" => "<computed>"   cpu_core_count:               "" => "<computed>"   cpu_threads_per_core:         "" => "<computed>"   ebs_block_device.#:           "" => "<computed>"   ephemeral_block_device.#:     "" => "<computed>"   get_password_data:            "" => "false"   host_id:                      "" => "<computed>"   instance_state:               "" => "<computed>"   instance_type:                "" => "t2.micro"   ipv6_address_count:           "" => "<computed>"   ipv6_addresses.#:             "" => "<computed>"   key_name:                     "" => "<computed>"   network_interface.#:          "" => "<computed>"   network_interface_id:         "" => "<computed>"   password_data:                "" => "<computed>"   placement_group:              "" => "<computed>"   primary_network_interface_id: "" => "<computed>"   private_dns:                  "" => "<computed>"   private_ip:                   "" => "<computed>"   public_dns:                   "" => "<computed>"   public_ip:                    "" => "<computed>"   root_block_device.#:          "" => "<computed>"   security_groups.#:            "" => "<computed>"   source_dest_check:            "" => "true"   subnet_id:                    "" => "<computed>"   tenancy:                      "" => "<computed>"   volume_tags.%:                "" => "<computed>"   vpc_security_group_ids.#:     "" => "<computed>" aws_instance.example: Still creating... (10s elapsed) aws_instance.example: Still creating... (20s elapsed) aws_instance.example: Still creating... (30s elapsed) aws_instance.example: Still creating... (40s elapsed) aws_instance.example: Creation complete after 43s (ID: i-065b6f952bd9dc3e0) Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Point to note anything with the (+) is actually added to the infrastructure and anything with a (-) is removed. We see one resource has been added and this looks like this on the AWS side of things

The resource being initialized
Infrastructure ready

Now, looking in the Terraform directory, we see that we have a tfstate file and a tfstate backup! These files allow for versioning to be done – as this contains all the changes that have gone in while creating the infrastructure

{     "version": 3,     "terraform_version": "0.11.11",     "serial": 9,     "lineage": "XXXXXX",     "modules": [         {             "path": [                 "root"             ],             "outputs": {},             "resources": {                 "aws_instance.example": {                     "type": "aws_instance",                     "depends_on": [],                     "primary": {                         "id": "i-065b6f952bd9dc3e0",                         "attributes": {                             "ami": "ami-b374d5a5",                             "arn": "arn:aws:ec2:us-east-1:XXXX:instance/i-065b6f952bd9dc3e0",                             "associate_public_ip_address": "true",                             "availability_zone": "us-east-1c",                             "cpu_core_count": "1",                             "cpu_threads_per_core": "1",                             "credit_specification.#": "1",                             "credit_specification.0.cpu_credits": "standard",                             "disable_api_termination": "false",                             "ebs_block_device.#": "0",                             "ebs_optimized": "false",                             "ephemeral_block_device.#": "0",                             "get_password_data": "false",                             "iam_instance_profile": "",                             "id": "i-XXX",                             "instance_state": "running",                             "instance_type": "t2.micro",                             "ipv6_addresses.#": "0",                             "key_name": "",                             "monitoring": "false",                             "network_interface.#": "0",                             "network_interface_id": "eni-0706ca617cd9e0458",                             "password_data": "",                             "placement_group": "",                             "primary_network_interface_id": "XXX",                             "private_dns": "ip-172-31-92-107.ec2.internal",                             "private_ip": "XXX",                             "public_dns": "XXX",                             "public_ip": "3.86.77.62",                             "root_block_device.#": "1",                             "root_block_device.0.delete_on_termination": "true",                             "root_block_device.0.iops": "100",                             "root_block_device.0.volume_id": "XXX",                             "root_block_device.0.volume_size": "8",                             "root_block_device.0.volume_type": "gp2",                             "security_groups.#": "1",                             "security_groups.3814588639": "default",                             "source_dest_check": "true",                             "subnet_id": "subnet-0b9ba03e45f4d23d1",                             "tags.%": "0",                             "tenancy": "default",                             "volume_tags.%": "0",                             "vpc_security_group_ids.#": "1",                             "vpc_security_group_ids.XXX": "sg-XXX"                         },                         "meta": {                             "e2bfb730-ecaa-11e6-8f88-XXX": {                                 "create": 600000000000,                                 "delete": 1200000000000,                                 "update": 600000000000                             },                             "schema_version": "1"                         },                         "tainted": false                     },                     "deposed": [],                     "provider": "provider.aws"                 }

I have hashed out some of the data – but this should give you a pretty good starting point for version control and future provisioning!

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous post Terraform
Next post Terminating or destroying a build