Terraform Introduction

In this post we will start learning Terraform by deploying a simple server. Terraform is a tool to build infrastructure as a code.

Terraform code is written in HashiCorp Configuration Language in file with .tf extension.

Setup

To begin with create a folder

  • cd ~/
  • mkdir terraform-example
  • cd terraform-example

In this folder create a file called main.tf. Terraform can work with many cloud provider like AWS, google cloud, azure, digital ocean and many more. In this example we will be using AWS.

In the main file add this section

# Configure the AWS Provider
provider "aws" {
  access_key = "${var.aws_access_key}"
  secret_key = "${var.aws_secret_key}"
  region     = "us-east-1"
}
1
2
3
4
5
6

If you have AWS_ACCESS_KEY and AWS_ACCESS_SECRET as environmental variable then terraform uses those credentials to create resources. So you don't need to have the access_key and secret_key as described in the section above

More information here Terraform Provider.

This code tells the that we will be deploying by default into us-east-1 region. We will get into more about how we use variables in this case the aws_access_key and aws_secret_key later but for now you can pass the aws_key and secret as described above or through environment variable. Terraform will use those to create resources

If you think of any application you can break it down into different components like databases, load balancer, caches, job queue etc. These are the services which cloud providers provide and can be used by any one.

resource "aws_instance" "web" {
  ami  =  "ami-5d496b22"
  instance_type = "t2.micro"

  tags {
    Name = "HelloWorld"
  }
}
1
2
3
4
5
6
7
8

Here we are telling terraform to create a aws_instance with name web this name can be used elsewhere in the terraform code to reference this instance.

We also provide tags in this case we have Name=HelloWorld this is the name you can see in the AWS console.

At this time we can do a dry run of the web instance creating process by running terraform plan the output should look something similar to

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.web
      id:                           <computed>
      ami:                          "ami-5d496b22"
      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"
      instance_state:               <computed>
      instance_type:                "t1.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>
      tags.%:                       "1"
      tags.Name:                    "helloworld"
      tenancy:                      <computed>
      volume_tags.%:                <computed>
      vpc_security_group_ids.#:     <computed>


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

Make sure you look at the +/- to see terraform is doing what its supposed to and then perform terraform apply

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_instance.web: Creating...
  ami:                          "" => "ami-5d496b22"
  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"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t1.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>"
  tags.%:                       "" => "1"
  tags.Name:                    "" => "helloworld"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.web: Still creating... (10s elapsed)
aws_instance.web: Still creating... (20s elapsed)
aws_instance.web: Still creating... (30s elapsed)
aws_instance.web: Creation complete after 36s (ID: i-02388c7fa72b61fc3)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

At this point if you go to aws console and check ec2 instances you should see one instance with helloworld running. And finally we can run terraform destroy to cleanup the resources for this example

$ terraform destroy
provider.aws.region
  The region where AWS operations will take place. Examples
  are us-east-1, us-west-2, etc.

  Default: us-east-1
  Enter a value:

aws_instance.web: Refreshing state... (ID: i-02388c7fa72b61fc3)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - aws_instance.web


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

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_instance.web: Destroying... (ID: i-02388c7fa72b61fc3)
aws_instance.web: Still destroying... (ID: i-02388c7fa72b61fc3, 10s elapsed)
aws_instance.web: Still destroying... (ID: i-02388c7fa72b61fc3, 20s elapsed)
aws_instance.web: Still destroying... (ID: i-02388c7fa72b61fc3, 30s elapsed)
aws_instance.web: Still destroying... (ID: i-02388c7fa72b61fc3, 40s elapsed)
aws_instance.web: Still destroying... (ID: i-02388c7fa72b61fc3, 50s elapsed)
aws_instance.web: Destruction complete after 52s

Destroy complete! Resources: 1 destroyed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

Congratulations, you just created a server using terraform. Given we can checkin this file in github we have complete visibility into our infrastructure.