Terraform Tutorials

What is Terraform ?

The idea behind infrastructure as code (IAC) is that you write and execute code to define, deploy, and update your infrastructure. This represents an important shift in mindset where you treat all aspects of operations as software — even those aspects that represent
hardware (e.g., setting up physical servers).

PTSCODE

Note: All examples are for AWS and assume you have AWS account.

How to install ?

1: Install Terraform from the Terraform HomePage
2: Unzip the downloaded archive.
3: The will extract a single binary called terraform, add to your PATH environment variable.

Verify installation ?

To check if things are working, run the terraform command, and you should see the usage instructions:

VERIFY

Prerequisite

In order for Terraform to be able to make changes in your AWS account, you will need to set the AWS credentials for the IAM user you created earlier as the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. For example, here is how you can do it in a Unix/ Linux/ OS X terminal:

> export AWS_ACCESS_KEY_ID =( your access key id)
> export AWS_SECRET_ACCESS_KEY =( your secret access key)

Introduction

Terraform is written in HarshiCorp Configuration Language file extensions .tf

Terraform can create infrastructure accross a wide variety of platforms or what is called
providers includes AWS, Azure, Google cloud etc.

Major text editor supports syntax highlighting ( Atom , Visual Studio code...)

1: The First step to use terraform is to configure the provider, with which you want t work.

 ## Create a empty directory and put a file in it called main.tf with following content

 provider "aws" {
   region = "eu-central-1"
 }

Above code tells terraform, you are using AWS as provider and you wish to deploy infrastructure in ec-central-1 region

The general syntax of terraform resource is :

  resource "PROVIDER_TYPE" "NAME"
  {
    [CONFIG ...]
  }

where PROVIDER is the name of a provider (eg. aws), TYPE is the type of resources to create in that provider, NAME is an identifier you can use throughout the Terraform code to refer to this resource. CONFIG consists of one or more configuration parameters that are specific to that resource. Will see in detail soon.

Creating a EC2 instance and learning basics

Let's create EC2 machine, deploy single web server.

Example1

Now you can add aws_instance resource to main.tf, which we created earlier.
We will see the detailed explanation of it in comming section

 ## Tell terraform which is the provider

 provider "aws"{
   region ="eu-central-1"
 }

 ## Code to create the aws instance

 resource "aws_instance" "myfirst"{
   ami = "ami-ac442ac3"
   instance_type = "t2.micro"
 }

ami : The Amazon Machine Image to run on the EC2 Instance More Info
instance_type : The type of EC2 instance to run . More Info

Now go to the folder where you created main.tf and run the terraform plan command:

Terraform Plan

Note: If terraform plan gives error, kindly run terraform init command to download aws plugin

terrraformplan

Terraform plan will tell what it will do before making actual changes on provider.
In the above example you can see, terraform will add ec2 resource.

To actually create the instance, we need to run terraform apply command.
Till now we have seen the following commands
1: terraform init
2: terraform plan
3: terraform apply

Terraform apply

Once you execute terraform apply command.

apply

it will ask for approval , kindly enter yes . Or even you can give auto approve argument in command line
terraform apply -auto-approve

Once you approve, it will create the resource. As shown below

Created

Terraform keeps track of all the resource it already created. Let's see how we can change the existing infrastructure. In the above example ec2 resource does not have name tag.

Let's add name tag to the resouce.

## Tell terraform which is the provider

provider "aws"{
  region ="eu-central-1"
}

## Code to create the aws instance

resource "aws_instance" "myfirst"{
  ami = "ami-ac442ac3"
  instance_type = "t2.micro"

  tags{
    Name ="gauraw"
  }
}

Now run terraform plan you will see as this is meta change, it will modify the existing created resource.

Change

Apply the change with terraform apply command

Terraform destroy

You can destroy your infrastructure with terraform destroy command .
Terraform maintains a state file of the resource which it has created. We will see state file in detail in comming sections

destory

Deploy Cluster of Web Server

Let's understand terraform in more detail, with an example

Example 1

Terraform Variable

Terraform allow you to define input variables. The syntax for declaring a variable is

variable "NAME"{
  [CONGIG ...]
}

The body of the variable can contain three parameters, all of them optional:

description
Used to define the description for the variable, used only of understanding the meaning of the variable.

default
There are number of ways value can be provided to the variable.
- Command Line ( using -var option)
- via a file ( using the var-file option)
- environment variable ( TF_VAR_<variable_name> )

if there is no default value, Terraform will interactively prompt the user for one.

type
Must be one of "string", "list" or "map". Terraform will try to guess based on default value. If default value is not present Terraform will assume the variable is a string.

## list example
  variable "list_example"{
    description ="An example of a list in terraform"
    type = "list"
    default = [1,2,3]
  }

## Map Example
  variable "map_example" {
    description ="An example for map"
    type = "map"
    default = {
      key1 = "value1"
      key2 = "value2"
      key3 = "value3"
    }
  }

## String example
 variable "server_port" {
   description = "The port the server will use for HTTP request"
 }

## If the default value is not present and variable is not populated. Terraform will prompt

terraform plan -var server_port="8080"

Terraform output variable

Terraform also allows you to define output variable with the following syntax:

  output "NAME" {
    value  = VALUE
  }

  ## can be used to output the value, so that we do not have check in provider manually

Webserver cluster and dependency graph

Create a file var.tf, file contain's terraform variable which we will use in script

variable "server_port" {
  description = "The port the server will use for HTTP requests"
  default     = 8080
}

Create a file main.tf which contains below mentioned code.

## define the provider

provider "aws" {
  region = "us-east-1"
}


## Launch configuration to create ec2 machine
resource "aws_launch_configuration" "example" {
  image_id        = "ami-40d28157"
  instance_type   = "t2.micro"
  security_groups = ["${aws_security_group.instance.id}"]

  user_data = <<-EOF
              #!/bin/bash
              echo "Hello, World" > index.html
              nohup busybox httpd -f -p "${var.server_port}" &
              EOF

  lifecycle {
    create_before_destroy = true
  }
}


## AWS aws_autoscaling_group
resource "aws_autoscaling_group" "example" {
  launch_configuration = "${aws_launch_configuration.example.id}"
  availability_zones   = ["${data.aws_availability_zones.all.names}"]

  load_balancers    = ["${aws_elb.example.name}"]
  health_check_type = "ELB"

  min_size = 2
  max_size = 10

  tag {
    key                 = "Name"
    value               = "terraform-asg-example"
    propagate_at_launch = true
  }
}

resource "aws_security_group" "instance" {
  name = "terraform-example-instance"

  ingress {
    from_port   = "${var.server_port}"
    to_port     = "${var.server_port}"
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  lifecycle {
    create_before_destroy = true
  }
}

data "aws_availability_zones" "all" {}

resource "aws_elb" "example" {
  name               = "terraform-asg-example"
  availability_zones = ["${data.aws_availability_zones.all.names}"]
  security_groups    = ["${aws_security_group.elb.id}"]

  listener {
    lb_port           = 80
    lb_protocol       = "http"
    instance_port     = "${var.server_port}"
    instance_protocol = "http"
  }

  health_check {
    healthy_threshold   = 2
    unhealthy_threshold = 2
    timeout             = 3
    interval            = 30
    target              = "HTTP:${var.server_port}/"
  }
}

resource "aws_security_group" "elb" {
  name = "terraform-example-elb"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

To check the dependency graph execute terraform graph command, to check how the resources will get created

Understanding folder structure

Folder structure

.terraform
Folder which has terraform plugin, created via terraform init command. Do not checkin into repository
.tfstate and .tfstate.backup
File is created by terraform to maintain the state of infrastructure. We will see the state file in detail.