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