After learning about kubernetes from kodekloud. I want to take a look at Terraform.
These are my notes that I am taking along the course.
1- Intro:
A- config mgmt: ansible, puppet, saltstack
Design to install and manage sw
B- Server Templating: docker, packer, vagrant.
Pre install sw and dependencies
vm or docker images
immutable infra
C- Provision tools: terraform, cloudformation
deploy immutable infra resources
servers, dbs, net components
multiple providers.
Terraform is available in AWS, GCP, Azure and physical machines. Multiple providers like cloudflare, paloalto, dns, infoblox, grafana, influxdb, mongodb, etc
It uses a declarative code HCL = HashiCorp Config Language: *.tf
Phases: Init, plan and apply.
2- Install and Basics
I am going to use my laptop initially, so I will follow the official instructions using a precompiled binary. So download the zip file (terraform_0.14.3_linux_amd64.zip), unzip and move the binary somewhere active in your path. I decided to use /usr/bin and install autocompletion.
/terraform/test1$ which terraform
/usr/bin/terraform
/terraform/test1$ terraform version
Terraform v0.14.3
provider registry.terraform.io/hashicorp/local v2.0.0
/terraform/test1$ terraform -install-autocomplete
HCL Basics:
<block> <parameters> {
key1 = value1
key2 = value2
}
Examples:
// This one use the resource "local_file". We call it "hello". It creates a file with specific content
$ vim local.tf
resource "local_file" "hello" {
filename = "/tmp/hello-terra.txt"
content = "hello world1"
}
Based on the above:
block_name -> resource
provider type -> local
resource type -> file
resource_name: hello
arguments: filename and content
// The next ones use AWS provider types
$ vim aws-ec2.tf
resource "aws_instance" "webserver" {
ami = "ami-asdfasdf"
instance_type = "t2.micro"
}
$ vim aws-s3.tf
resource "aws_s3_bucket" "data" {
bucket = "webserver-bucket-org-2207"
acl = "private"
}
Deployment process:
0- create *.tf file
1- terraform init --> prepare env / install pluggins, etc
2- terraform plan --> steps to be done // review
3- terraform apply -> execute steps from plan
4- terraform show
Example using “local_file” resource:
/terraform/test1$ terraform init
Initializing the backend…
Initializing provider plugins…
Reusing previous version of hashicorp/local from the dependency lock file
Installing hashicorp/local v2.0.0…
Installed hashicorp/local v2.0.0 (signed by HashiCorp)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
/terraform/test1$
/terraform/test1$ terraform plan
local_file.hello: Refreshing state… [id=c25325615b8492da77c2280a425a3aa82efda6d3]
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:
# local_file.hello will be created
resource "local_file" "hello" { content = "hello world1"
directory_permission = "0777"
file_permission = "0700"
filename = "/tmp/hello-terra.txt"
id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
/terraform/test1$
/terraform/test1$ terraform apply
local_file.hello: Refreshing state… [id=c25325615b8492da77c2280a425a3aa82efda6d3]
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:
# local_file.hello will be created
resource "local_file" "hello" { content = "hello world1"
directory_permission = "0777"
file_permission = "0700"
filename = "/tmp/hello-terra.txt"
id = (known after apply)
}
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: yes
local_file.hello: Creating…
local_file.hello: Creation complete after 0s [id=c25325615b8492da77c2280a425a3aa82efda6d3]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
/terraform/test1$
/terraform/test1$ cat /tmp/hello-terra.txt
hello world1
Update/Destroy:
$ update tf file
$ terraform apply -> apply the changes
or
$ terraform destroy -> shows the destroy plan and then you need to confirm
Providers:
https://registry.terraform.io/
oficial: aws, gcp, local, etc
verified (3rdparty): bigip, heroku, digitalocena
community: activedirectory, ucloud, netapp-gcps
$ terraform init -> show the providers installed
plugin name format:
* registry.terraform.io/hashicorp/local
^ ^ ^
hostname org namespace type
plugins installed in .terraform/plugins
https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file#sensitive_content
main.tf: resource definition
variables.tf: variable declarations
outputs.tf: outouts from resources
provider.tf: providers definition
Variables:
filename
content
prefix
separator
length
* type is optional
type: string "tst"
number 1
bool true/false
any whatever
list ["cat","dog"]
map pet1=cat
object mix of the above
tuple like a list of types
set (it is like a list but can't have duplicate values!)
Examples:
vim varibles.ttf
// List
variable "prefix" {
default = ["Mr", "Mrs", "Sir"] **default is optional!!!
type = list(string)
}
// Map
variable file-content {
type = map(string)
default = {
"state1" = "test1"
"state2" = "test2"
}
}
// Set
variable "prefix" {
default = ["10","11","12"]
type = set(number)
}
// Object
variable "bella" {
type = object({
name = string
age = number
food = list(string)
alive = bool
})
default = {
name = "bella"
age = 21
food = ["pasta", "tuna"]
alive = true
}
}
// Tuple
variable kitty {
type = tuple([string, number, bool)]
default = ["cat", 7, true]
}
Using variables
vim main.tf
resource "random_pet" "my-pet" {
prefix = var.prefix[0]
}
resource local_file my-file {
filename = "/tmp/test1.txt"
content = var.file-content["state1"]
}
Example using vars:
/terraform/vars$ cat variables.tf
variable "filename" {
default = "/tmp/test-var.txt"
type = string
description = "xx"
}
variable "content" {
default = "hello test var"
}
/terraform/vars$ cat main.tf
resource "local_file" "test1" {
filename = var.filename
content = var.content
}
/terraform/vars$
/terraform/vars$ terraform init
Initializing the backend…
Initializing provider plugins…
Finding latest version of hashicorp/local…
Installing hashicorp/local v2.0.0…
Installed hashicorp/local v2.0.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!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
/terraform/vars$
/terraform/vars$ terraform plan
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:
# local_file.test1 will be created
resource "local_file" "test1" { content = "hello test var"
directory_permission = "0777"
file_permission = "0777"
filename = "/tmp/test-var.txt"
id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
/terraform/vars$
/terraform/vars$ 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:
# local_file.test1 will be created
resource "local_file" "test1" { content = "hello test var"
directory_permission = "0777"
file_permission = "0777"
filename = "/tmp/test-var.txt"
id = (known after apply)
}
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: yes
local_file.test1: Creating…
local_file.test1: Creation complete after 0s [id=9f5d7ee95aa30648a2fb6f8e523e0547b7ecb78e]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
/terraform/vars$
/terraform/vars$
/terraform/vars$ cat /tmp/test-var.txt
hello test var
Pass var values:
1- if there is no values for var, when running "terrafom apply" it will ask for the values interactivily!
2- cli params
$ terraform apply -var "filename=/root/test.tst" -var "content=My Test"
3- env vars TF_VAR_xxx=xxx
$ export TF_VAR_filename="/root/test.tst"
$ terraform apply
4- var files:
autoloaded: terraform.tfvars, terraform.tfvars.json, *.auto.tfvars, *.auto.tvars.json
explicit NAME.tfvars
$ cat terraform.tfvars
filename="/root/test.tst"
$ terraform apply
$ terraform -var-file NAME.tfvars
VAR PRECEDENCE: less -> more
1 env vars
2 terraform.tfvars
3 *.auto.tfvars (alphabetic order)
4 -var -r -var-file (cli flags) --> highest priority!!!! it overrides all above options