Terraform

Terraform: https://github.com/hashicorp/terraform

Terraform provider: https://github.com/terraform-providers

The Terraform Book: https://github.com/turnbullpress/tfb-code

Terraform up&running: https://github.com/brikis98/terraform-up-and-running-code

Install Terraform on Linux

To install Terraform on a 64-bit Linux host we can download the zipped binary file. We can use wget or curl to get the file from the download site.

$ cd /tmp
$ wget https://releases.hashicorp.com/terraform/0.12.16/terraform_0.12.16_linux_amd64.zip

$ unzip terraform_0.12.16_linux_amd64.zip
$ sudo mv terraform /usr/local/bin
$ sudo chown -R root:root /usr/local/bin/terraform

$ terraform -v
Terraform v0.12.16

 

How does Terraform know what API calls to make? The answer is that you create Terraform configurations, which aretext files that specify what infrastructure you want to create. These configurations are the “code” in “infrastructureas code.”

Chef and Ansible encourage a procedural style in which you write code that specifies, step by step, how to achievesome desired end state. Terraform, CloudFormation, SaltStack, Puppet, and Open Stack Heat all encourage a moredeclarative style in which you write code that specifies your desired end state, and the IaC tool itself is responsiblefor figuring out how to achieve that state.

Use the terraform output command to list all outputs without applying any changes:

$ terraform output
public_ip = 54.174.13.5

And you can run terraform output <OUTPUT_NAME> to see the value of a specific output called <OUTPUT_NAME>:

$ terraform output public_ip
54.174.13.5

 

Terraform Syntax

  • terraform init
    • pulls down the specific providers that we need for the project
    • can run multiple times
  • terraform plan
    • shows diffs between the existing infrastructure that is in place on whatever platforms.
  • terraform apply
    • run diffs if there are any changes to apply
    • read template and try to create infrastructure into the platform
  • terraform destroy
    • destroys all  resources created in the platform
  • terraform validate
    • validates terraform file
  • terraform fmt
    • cleans up messy formats
  • terraform graph
    • install dependency GraphViz
    • terraform graph | dot -Tsvg > graph.svg
    • terraform graph | dot -Tpng > graph.png
  • terraform workspace list
  • terraform state list
    • lists all resources in the state file
  • terraform show
    • prints a complete state in a human-readable format

Terraform Getting Started

  • Resources are components of your infrastructure. Each resource belongs to a provider and the type of the resource is suffixed with the provider name. The tags parameter is a map of tags for the instance.
resource "provider-name_resource-type" "resource-name" {
  parameter_name = parameter_value
}

# Provider configuration 
provider "aws" {
   region = "eu-central-1" } 
# Resource configuration 
resource "aws_instance" "hello-instance" {
   ami = "ami-9bf712f4"
   instance_type = "t2.micro"
   tags {
     Name = "hello-instance"
   }
 }
  • After terraform apply command, terraform stores the state of all the resources it created to a file with the .tfstate extension in the same directory. The format of the state file is simple json. Losing the state file means losing control of your environment through Terraform.
  • Modules in terraform are used to group multiple resources. You can reuse this grouping multiple times. You can also configure modules with variables, and modules can return output that you can pass to other resources and modules.
    • To Terraform, every directory containing configuration is automatically a module. Using modules just means referencing that configuration explicitly. References to modules are created with the module block.
    • Modules look just like resources only without a type. Each module requires a name. The module name must be unique in the configuration.
    • Modules only have one required attribute: the module’s source. The source tells Terraform where to find the module’s source code. You can store modules locally in your filesystem or remotely in repositories such as GitHub.
    • You can specify a module multiple times in a configuration by giving it a new name but specifying the same source.
  • Variables are defined with the variable keyword, followed by the variable name and optional default value inside curly braces. To use the variable, you need to reference it via a special var keyword, as follows: ${var.my_variable}.
    • Unlike in programming languages, variables in Terraform are more like input data for your templates: you define them before using the template. During the Terraform run, you have zero control over variables. The values of variables never change; you can’t modify them inside the template.
    • There are three types of variables you can set:
      • the string variables (default ones)
      • the map variables
      • the list variables
        • There is a very nice place where we can use lists in our templates: security group.
    • You can only interactively set the string variables; for map and list, you have to use other methods.
  • It is a common pattern to split variables, template, and outputs into three different files. As you might remember, Terraform loads all files with the .tf extension from the current folder, so you don’t need to do any extra steps to join these three files.
  • With the default value in place, Terraform won’t ask for the value interactively anymore. It will pick default value unless other sources of variables are present.
variable "region" {
   description = "AWS region. Changing it will lead to loss of complete stack."
   default = "eu-central-1"
}
  • Data sources are very similar to regular resources. The main difference is that they are read-only.
  • Terraform configuration files
    • When Terraform runs inside a directory it will load any Terraform configuration files. Any non-configuration files are ignored and Terraform will not recurse into any sub-directories. Each file is loaded in alphabetical order, and the contents of each configuration file are appended into one configuration.
    • Terraform then constructs a DAG, or Directed Acyclic Graph, of that configuration. The vertices of that graph— its nodes—are resources—for example, a host, subnet, or unit of storage; the edges are the relationships, the order, between resources. For example, a network may be required before a host can be created in order to assign it an IP address. The graph determines this relationship and then ensures Terraform builds your configuration in the right order to satisfy this.
  • To create the S3 bucket to store the Terraform state
    1. Write Terraform code to create the S3 bucket and DynamoDB table and deploy the code with a local backend.
    2. Go back to the Terraform code, add a remote backend configuration to it to use the newly created S3 bucket and DynamoDB table, and run terraform init to copy your local state to S3.
  • The backend block in Terraform does not allow you to use any variables or references. This means that you need to manually copy and paste the S3 bucket name, region, DynomoDB table name, etc. into every one of your Terraform modules.
  • Terraform workspaces allow you to store your Terraform state in multiple, separate, named workspaces. Terraformstarts with a single workspace called “default,” and if you never explicitly specify a workspace, the defaultworkspace is the one you’ll use the entire time. To create a new workspace or switch between workspaces, you use theterraform workspace commands.
    • terraform workspace show
    • terraform workspace new example1
    • terraform workspace new example2
    • terraform workspace select example1