converted_text
converted_text
Terraform is very popular open source tool used for infrastructure provisioning.
It is developed by hashicorp(HCL).
It will allow us to build,destroy,modify infrastrucure in minutes.
it supports lot of cloud and physical platforms.
Providers are nothing but api calls to communicate with the cloud,other infrastructure.
HCL language uses Declarative and can be maintain in version control system.
Every object terraform provisions is called as Resource, a resource can be ec2,s3,iam etc..
Terraform .tf file can be created using any texteditor,notepad++,vi,vim or visual studio etc..
What is a Resource:
Resource is a object that terraform manages.
it can be any file in local machine.ec2.iam,s2,on cloud, database many more things.
HCL Basics:
=========
HCL files consists of block and arguments.
Example:
=======
<block> <parameters> {
key1= value1
key2 = value2
}
Create a file called local.tf the configuration file to create a file in local
filename and contents --> arguments for the local_file resource type
Once we have the terraform resource file then we need to perform below commands
terraform init --> to initliaze the repository and download the dependencies
terraform plan --> dry run to check how it will be create the respource (It will not actually create
them)
terraform apply --> to execute and create the infra based on the configuration
terraform destroy --> to remove/delete the existing infra.
terraform show --> to show/get the details of the resources created
Terraform Provider--> it is api call which is used to communicate with the resources, it can be
aws,gcp,azure or local.
Providers are in three categories
1) Official --> provided by Hashicorp
2) Partner --> third party vendors
3) Community --> individual
When we execute terraoform init it will create a .terraform directory in the working directory
Configuration Directory:
=======================
Main.tf -->main configuration file containing resource definition
variables.tf --> contains varibles declaration
output.tf --> contains outputs from resources
provider.tf --> contains the provider definition
Multiple providers:
==================
variables:
=========
Instead of hardcoding all the variables in the same configuration file we can use variables so that
it can be
reuse again and again by only changing the variables file.
variable block:
==============
variable "filename" {
default =""root/pets.txt" --> Default value
type = --> type of variable
description = --> optional but can define why the varible is used for
}
Type Example
String I love pets
Number 1
bool true/false
any default value
list ["cat","dog"]
map pet1= cat
pet2=dog
object complex data structure
tuple complex data structure
main.tf
reource "random_pet" "my=pet" {
prefix = var.prefix[0]
}
Varibales.tf:
variable "file-content" {
type = map
default = {
"statement1" = "we love pets"
"statement2" = "We love animals"
}
}
main.tf
resource "local_file" "pet" {
filename = "/root/pets.txt"
content = "var.file-content[statement2]"
}
Ex:
Varibale "Bella" {
type = object({
name = string
color = string
age = number
food = list(string)
favorite_pet = bool
})
}
default = {
name = "bella"
color = "brown"
age = 7
food = ["fish","chicken"]
favorite_pet = true
}
Ex:
variable kitty {
type = tuple([string,number,tuple])
default = ["cat", 7,true]
}
Using of variables:
==================
1) By using varibles.tf file
2) By using interactive mode (This will get activated if we dont pass defa;ult value in variable.tf
file)
3) Command line flags
--> terraform apply - var "filename=/root/pets.txt" -var "prefix=MR"
4) Environment variables
--> export TF_VAR_filename="/root.pets.txt"
--> export TF_VAR_prefix= "MR"
--> Set-Item -Path env:TF_VAR_filename -Value 'wild.txt'
terraform apply
5) varibale definition file (Should be end with terraform.tfvars/terraform.tfvars.json)
--> for automatically loaded file name *.auto.tfvars/*.auto.tfvars.json
--> if we are saving the file with other name like varible.tfvars then we need to pass this in CLI
--> terraform apply -var-file varibale.tfvars
Example:
--> main.tf
--> variable.tf
variable filename {
type = string
}
Precedence order:
================
in the above example we have passed all the possible varibles,which will terraform laod first and
which will override ?
Order Option
1 Environment variables
2 Terraform.tfvars
3 *.auto.tfvars(alphabetical order)
4 -var or -var-file (Command line flags)
main.tf
======
resource "local_file" "pet" {
filename = "/root/pets.txt"
content = "My cat is MR.Cat"
}
resource "random_pet" "mypet" {
prefix = "MR"
separator = "."
length = "1"
}
When we execute terraform apply it will create random id with pet name,
now i want to add this pet name in my content file (using output of one resource as input for
another resource).
main.tf
======
resource "local_file" "pet" {
filename = "/root/pets.txt"
content = "My cat is ${random_pet.mypet.id}" (random_pet = resource type,mypet = resource
name, id = attribute)
}
resource "random_pet" "mypet" {
prefix = "MR"
separator = "."
length = "1"
}
Resource Dependencies:
=====================
From the above main.tf we have local_file which is dependent on random_pet resource.
We are not mentioning that anywhere but still terraform will figure that out, we call them as
implicit dependecy.
Still we can define the dependency explicit by ourself using "depends_on" module
Output variables:
=================
These are used to display the output of the resources.
Ex:
resource "random_pet" "mypet" {
prefix = "MR"
separator = "."
length = "1"
}
output my-pet {
value = random_pet.my-pet.id
description = optional name
}
when we use terraform apply we can see the id as output.
we can use terraform output command to see the output of the resource.
Terraform state:
================
Terraform state file will have the complete record of the infra created by terraform.
State file is considered as a blue print of all the resources terraform manages.
terraform.tfstate will be the name of the file and this will created only after using terraform apply
command.
When we excute terraform apply then terraform will check for the state file config and main.tf
configuration and make the changes.
If both the files are in sync and we are again trying to execute terraform apply then terraform will
not make the changes but show
"Terraform has compared your real infrastructure against your configuration and found no
differences, so no changes are needed."
Terraform Commands:
==================
Terraform init --> to initiliaze terraform and download the dependecies for the resources.
Terraform plan --> To dry run or show how terraform will be executing the resource file.
Terraform apply --> To execute and make changes of the resource file.
Terraform output --> to print the output present in the resource file
Terraform validate --> to check the syntax is correct or not
Terraform fmt (format) --> to correct the format of the configuration file
Terraform show --> to display the current state of the infrastructure.
Terraform providers --> to see the list of providers used in configuration file
Terraform refresh --> used to sync terraform with real world infrastructure
Terraform graph --> to create visual representation of dependency
Lifecycle rules:
===============
We can configure lifecycle rules to our resource file.
Terraform will destroy the file before creating a new file by default.
We can create a file before destroy by using the lifecycle rules.
lifecylce {
create_before_destory = true
}
}
lifecylce {
prevent_destory = true
}
}
This will be only helpful if we are using terraform apply command, if we use terraform destroy
then it will destory the resources.
If we want to ignore the changes which has been by third party tool or manually then we can use
the ignore_change
Data sources:
===========
Apart from terraform we have multiple other tools where the infra can be created.
Ex: ansible,salt,puppet,bash script,manual process.
for example if we want terraform to read the content of the file which has been created by any
other tool.
main.tf
======
Meta-Arguments:
==============
Meta arguments are used if we want to create multiple resources.
Meta arguments can be used within any resource block to change the behaviour of the
resources.
Examples for meta arguments:
1) Depends_on
2) lifecycle rules
3) Count
4) For_each
Example of count:
================
If we use count as 3 then it will create 3 files with pet[0],pet[1],pet[2]
This is not the idela way to use because these are getting replaced.
variables.tf
variable "filename" {
default = [
"pets.txt"
"cats.txt"
"dogs.txt"
]
}
Still we have problem in the above configuration,if in future the list of varibles then we need to
change the count value manually.
to avoid this we can use the inbuilt lenth function in terraform.
variable "filename" {
default = [
"pets.txt"
"cats.txt"
"dogs.txt"
]
}
But when we want to update/destroy any one file then we will see un wanted results in count as
count will store the output in list and works on index number.
Example of for_each:
====================
main.tf:
variables.tf
============
variable "filename" {
type=set(string) --> list type will throw error for_each argument.
default = [
"pets.txt"
"cats.txt"
"dogs.txt"
]
}
or if you want to use list varibale then we can change the main.tf with toset inbuilt function.
main.tf:
variables.tf
============
variable "filename" {
default = [
"pets.txt"
"cats.txt"
"dogs.txt"
]
}
Count will store the output as list and identified based on indexnumber
foreach store the output as map and identified based on filename.
Version Constraints:
===================
Changing in terraform providers version may get us into incompatability issues.
By default terraform will always try to downlaod the latest version of provider available from
registry.
To make sure to use the specific version provider we can add the provider block in configuration.
Example:
=======
terraform {
required_providers {
local = {
source = "hashicorp/local"
version = "2.3.0"
}
}
}
Example script to create iam user with policy attached to the user:
===================================================================
we can also use them by saving the template in seperate file and call that file in our main.tf.
Example:
=======
admin-policy.json
=================
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "1234567890",
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
main.tf:
======
State locking is used to lock the state file so that no two users can execute the state file at the
same point of time.
bucket = "s3backend"
acl = "private"
}
attribute {
name = "LockID"
type = "S"
}
}
Terraform Provisioners:
=======================
Terraform provisioners allow us to execute command,scripts on remote machines or
local place were terraform is installed.
1) Remote provisioner
This is used to execute commands at the run time on remote machines.
2) Local provisioner
This is used to execute commands at the run time on local machine. (means where terraform is
installed)
}
}
We can use local provider after creating/destroying respource.
}
}
If the script failed then terraform apply command will also throw error.
if we want the resource to be completed if the script is failed then we can use on_failure module.
}
}
if for any reason you have installed manually in ec2 and you want that to be replaced in next
apply
then we can manually mark that resource as taint in terraform so that it will be replaced next
time when use apply.
terraform taint aws_instance.webserver
Debugging:
=========
terraform apply will provide us the logs/cause of the issue,
but still if we want to dig deeper then we need to export a varibale
export TF_LOG=TRACE
Set-Item -Path env:TF_LOG -value "TRACE"
export TF_LOG_PATH=/tmp/terraform.log
Set-Item -Path env:TF_LOG_PATH -value "terraform.log"
Terraform import:
================
Terraform import is used to import the existing infrastructure in terraform state file.
Once import is done then we cna be able to create/delete and manage the infrastructure.
In order to import any resource we need to write the resource details in configuration file.
example:
module "dev-webserver" {
source = "../aws_instance"
ami = "ami-02f3f602d23f1659d"
}
Terraform workspaces:
====================
Workspace can be used if we have multiple project/environments using the same configuration.
Workspace commands:
==================
terraform workspace new projectA --> to create a workspace names projectA
terraform workspace list --> to list the workspaces available
terraform workspace selecr projectA --> to swtich to specific workspace
Example:
main.tf:
=======
resource "aws+instance" "webserver"
ami = "var.ami"
instance_type = "t2.micro"
}
variable.tf:
===========
variable "ami" {
type = map
default = {
"ProjectA" = "ami-02f3f602d23f1659d"
"ProjectB" = "ami-02f3f602d23f1659d"
}
}
when using workspaces state files will be created in the main directory
under a forlder "terraform.tfstate.d"