Terraform 1
Command 1
Files 1
Commands 2
Target resources: to deploy/destroy specific resources in the existing stack 2
Terraform Variables 2
Varibale passing Flow with modules and multi env 2
Type constructor 3
1. List: 3
2. Tuple 3
3. Set 3
4. Map 3
5. Object 3
Modules 4
Locks 5
What: 5
How: 6
Locks in the cloud 6
Problem Scenarios and the Force Unlock Command 6
Backend configuration 6
Working with states 6
Managing workspace 6
Workspace commands 6
Troubleshoot 6
Callouts 6
1. Install Terraform steps 6
2. Create a clean project and file 7
4. Commands 7
5. Reference resources 7
6. Folders and files 7
7. Outputs 8
8. Variable 8
Edge Scenarios Questions 8
Drawbacks 10
Terraform with Kubernetes 10
Terraform
- Create and maintain infrastructure and resources with Terraform
Command
- Terraform init: installs all the plugins (in the .terraform file) to run our code
- Terraform will download the binary software required by further respective providers to communicate with that respective provider-dependent cloud provider.
- Terraform fmt: format the template
- Terraform validate: validate the template // syntax
- Terraform plan: this is where you review changes and choose whether to simply accept them.
- Teraform plan -out testplan
- Terraform apply: this is where you accept changes and apply them against real infrastructure.
- Terraform show: to show details of deployed resources
- Terraform state list: to see the list of resources that are deployed
- Terraform destroy: this is where to destroy all your created infrastructure
Files
- .terraform:
- install all the plugins to run code
- is a local cache where Terraform retains some files required for subsequent operations against this configuration
- Terraform.tfstate:
- represents all of the states for terraform. Keep track of everything we create(that way if we modify something; ex: modify tag, it needs to be able to check what is the current state and configurations)
- Resource we create in a state file
- Terraform.lock.hcl
- lock file for various items that Terraform caches in the . terraform subdirectory of your working directory
- Terraform automatically creates or updates the dependency lock file each time you run the terraform init command.
- You should include this file in your version control repository so that you can discuss potential changes to your external dependencies via code review
Commands
- Terraform state list: shows resource state list
- Terraform state show: shows resources details(physical id’s, tags, version, etc)
- Terraform output: print output
Target resources: to deploy/destroy specific resources in the existing stack
- Terrafrom apply -target NameOfTheResource
Terraform Variables
Load variables to terraform by below files
- terraform.tfvars - Auto load variables from this file
Load variable in below order
- Environment variable
- terraform.tfvars file; if present
- terraform.tfvars.json file; if present
- Any *auto.tfvars or *auto.tfvars.json
- -var and -var-file
Varibale passing Flow with modules and multi env
Flow:
Dev.tfvars → root module → child module
- Workspace Selection
- Load Variable Definitions: Next, Terraform loads the variable definitions from the variables.tf (or similar) files in the root module's directory and in the child module directories if they exist.
- Load Variable Values: Terraform then loads the values for these variables from an environment-specific .tfvars file you specify when running terraform apply or terraform plan. You specify it with the -var-file flag.
- Pass Variables to Root Module: Terraform uses these variable values within your root module where the variables are referenced. For example, when you call a child module
- Pass Variables to Child Module: Finally, within the child module, referenced variables are substituted with these values in the corresponding resources
Type constructor
List:
- A list is an ordered collection of items of the same type. Ex: list(string)
- The list can contain duplicates.
- In terms of creating VMs, imagine you have a list of VM names: ["vm1", "vm2", "vm2", "vm3"]
- Here "vm2" appears twice; that's okay in a list. Lists in Terraform maintain the order of elements, which is important when you use count as the order of creation depends on this list's order.
Tuple
- A tuple is used when you want to define an ordered list of elements of possibly different types. Ex: tuple([string, number, bool])
- An instance of this tuple type might look like ["vm1", "Standard_D2s_v3", "us-west-2"].
Set
- A set is similar to a list, except it does not contain duplicate values and it does not maintain order.
- In the case of VM creation: ["vm1", "vm2", "vm3"], If you try to add another "vm1", Terraform will reject it because a set can't contain duplicates.
Map
- A map is a collection of key-value pairs.
- For VM creation, you might have a map where the key is a hostname and the value is VM size:
{ "vm1" = "Standard_D2s_v3" "vm2" = "Standard_E2s_v3" "vm3" = "Standard_F2s_v2" } |
- Here, "vm1", "vm2", "vm3" are keys, and "Standard_D2s_v3", "Standard_E2s_v3", "Standard_F2s_v2" are the respective values.
Object
- An object allows you to define a structured data type with named attributes.
- Each attribute can have its own type. This is ideal if you need to manage complex configurations. For VM creation:
object({ hostname = string vm_size = string region = string }) |
- An instance of this object type might look like {"hostname" = "vm1", "vm_size" = "Standard_D2s_v3", "region" = "us-west-2"}
Constructor | Description | Works with Count | Works with For_each | Example Use Case |
List
| An ordered collection of items all of the same type. | Yes | Yes, but not recommended due to unpredictable ordering. | Define a number of similar resources based on length of list. |
Type | An ordered collection of items, each item could potentially be a different type. | Yes | Yes, but not recommended due to unpredictable ordering. | To instantiate a set number of resources with definite ordering. |
Set | An unordered collection of unique items, all of the same type. Order is not guaranteed. | No | Yes | Define a number of unique resources without worrying about order. |
Map
| A collection of key-value pairs. | No | Yes | Define resources where each has some unique configuration tied to the key. |
object
| A single complex structured collection with named keys.
| Not directly, unless contained in a list or set Not directly, unless contained in a list or set | Not directly, unless contained in a list or set Not directly, unless contained in a list or set
| Define a complex object like VM configuration parameters. |
Modules
- It’s a container for multiple resources that are used together
- The main way to package and reuse resource configs within Terraform
- Types
- Root module: consists of all the resources in main.tf file
- Child module: called by root module
- Publish modules: loaded from public and private registry
- Anyone who has access to this terraform module you created, can use it to spin up the same resources in their code
Locks
What:
- It’s about protecting Terraform state files(locally or cloud) against concurrency issue
- Concurrency issues might happen when multiple people in a large team are trying to apply changes to infrastructure simultaneously.
- Example: If person A and person B both try to apply changes at roughly the same time, without communication between them, the changes by person B might overwrite the changes made by person A, or vice versa. This can lead to inconsistencies and potential loss of data.
How:
- Terraform's solution is to lock the state file whenever it is being modified. Any other operations trying to apply changes at the same moment will find the file locked and will need to wait until it's available again.
Locks in the cloud
- This state lock is achieved in Azure Blob storage using the "lease" concept. A lease is like a lock that gives the client exclusive write access to the blob for the duration of the lease.
Problem Scenarios and the Force Unlock Command
- Sometimes, the Terraform operation might fail or get interrupted, like from a network issue or an unexpected server shutdown. When this happens, the lease (lock) might not get properly released, preventing future operations.
- To handle this scenario, you can manually remove the lock with the terraform force-unlock command. However, this is risky because you must be absolutely certain that no operations are currently using the state file.
Backend configuration
Working with states
- CLI command to manipulate state data
State Commands
- Terraform state list
- Terraform state show NameOfTheState
Managing workspace
- To manage and create workspaces, to manage multiple non-overlapping groups of resources with the same configuration
Workspace commands
- Terraform workspace list: list of workspaces
- Terraform workspace new NAME: create a new workspace
- Terrafrom workspace select NAME: switch to your workspace
- Terraform init
- Terraform fmt -recursive
- Terraform init
- Terraform validate
- Terraform plan: review of deployment
Troubleshoot
- Terraform version
- Export TF_LOG_CORE=TRACE
- Export TF_LOG_PROVIDER=TRACE
- EXPORT TF_LOG_PATH=logs.txt
- Terraform refresh
Callouts
1. Install Terraform steps
- install homebrew - package manager tool for mac os. used to install all sorts of softwares
- /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- install terraform
- brew install terraform
- terraform -v
2. Create a clean project and file
- Under the project, folder create file --> main.tf
- in the main.tf file, start writing your code
- Provider
- resource ("provider_resource" "NAME")
4. Commands
- terraform init // it will look at the config in the .tf file and download the plugin based on the provider specified in the main.tf file
- terraform plan // review changes
- terraform apply //
- terraform destroy // delete entire resources in the main.tf, you can delete individual resources as well
- terraform destroy -target ResourceName
5. Reference resources
- provider_resource.name.id // to reference other resource
6. Folders and files
- .terraform // when we initialize terraform, it installs the necessary plugins to run our code into this folder
- terraform.tfstate // contains all off the state in the terraform. saves the current states of the deployed resources. so when you update anything, terraform compares the version to the current state mentioned in this file. if the updated component is not there, it will create it
7. Outputs
- to print out resource values such as public_ip
8. Variable
- description
- default
- type
- sensitive
- ways of supplying variable value
- at the command prompt // terraform apply -var "var=value"
- referance varibale file // terraform apply -var-file NAME
- variable list
Edge Scenarios Questions
- We have resources in main.tf file, someone updated/added resources in the resource group/CloudFormation; we want these resources in the cloud but not in the main.tf
- Terraform refresh
- This will update and bring manually created resources into the terraform.tfstate file. So you don’t need to include it in the main.tf file.
- It updates the state file to match the real infrastructure(ex: changed AWS instance type from micro to small from the console. So refresh will update the state file with this changes)
- We have existing Terraform infrastructure created in Azure/AWS; now, one particular resource needs to be re-created, when we do the next apply.
- Terraform Taint “resource name”
- This informs terraform that a particular object has become degraded or damaged and needs to be replaced in the next apply
- Null resources: it is like a tool used to do specific tasks that do not create or modify any real part of your project.
When:
- It's useful for performing actions that are triggered by changes in other parts of your project.
Examples
- Running a local script:
- You can use null_resource to run a script on your local machine whenever certain parts of your set-up change.
- For example, you might want to add a line to a log every time a new server is created.
- Executing a command on a remote server:
- You could use null_resource to trigger a command on an existing server when something in your project changes.
- For example, suppose you have a server where you wish to upload a script or software only if the software script locally has changed.
- Debugging:
- null_resource can be used to output debugging information.
- For example, you could set it to print the values of certain variables whenever they change.
- State file
- What: holds the metadata of your cloud infra. When you apply your terraform, it will create a state file holding your infra details.
- Store & Secure:
- terraform Backend - backends define where terraform’s state snapshots are stored. Store it on the cloud. ex: S3, blob
- Lost state file
- It will duplicate your infra if you deploy. So you can either use Import to get into your state file
- How to resolve a large team working on the same code base, writing/pushing terraform code at the same time
- Have a remote state(S3). So people don’t write it locally
- Use lock to your state file so people won’t override at the same time
- Use version control and branching strategy to solve multiple people working on the same code base
- Terraform module
- If you make an update/new version to your terraform module - some of the code base that using your terraform module is no longer compatible with this new version, how would you solve this problem
- So you can have multiple versions of the modules
- When Callar calls the module it can specifically refer to the older version instead of the latest
- Types of META-Argument and Benefit
- Meta arguments change, the default behavior of terraform configuration
- Depends_on
- Count (to create 10 EC2 instance),
- For_each (loop: key,val),
- Provider (cloud platform),
- Lifecycle
- Create before destroy
- Prevent destroy
- Ignore changes
- if it can’t update, then it will destroy and recreate the object
- Dynamic block
- It lets you repeatedly create multiple blocks based on a list or a map.
- You use dynamic blocks in Terraform when you want to create multiple similar resources or attributes but don't want to write out each one manually.
- Examples
- Creating multiple security group rules: Suppose you have a list of different ports you want to open in a security group. You could write a separate ingress block for each port in your aws_security_group, or you could use a 'dynamic' block:
- In this example, there will be an ingress block created for each port number in the open_ports list. If we didn't use a 'dynamic' block, we would have to manually write out 3 separate ingress blocks.
- Creating multiple AWS instances: Suppose you want to create multiple AWS instances with different instance types. You can use a dynamic block for this purpose.
- In this example, an AWS instance is created for each entry in the instances map. Without the 'dynamic' block, we would need to add separate aws_instance blocks for each different instance_type.
- Who creates terraform.tfstate.backup
- automatically created by terraform when you run terraform destroy
- helps you to restore the previous state of your infrastructure
Drawbacks
- No error handling
- HCL language specific unlike Pulumi
- Does not support script generation
- The backends are not accessible through the variable file
Terraform with Kubernetes
- Create a Kubernetes cluster using kind
- Kind create cluster --name EnterName --config file.yaml
- Configure kubectl to interact with Kubernetes Cluster
- Kubctl cluster-info --context EnterName
- Confirm if the cluster is created
- Kind get clusters
- Use kubectl to get information from our cluster to use in our variable file
- Kubectl config view --minify --flatten --context EnterName
- Get the details and add it to the variable file
- Host
- Client cert
- Client key
- Cluster ca cert
- Now we have what we need to allow terraform to communicate with our Kubernetes cluster
- Terraform command
- Terraform init
- Terraform plan
- Terarform apply
- Kubctl get deployment // to see the resource is created
Callouts
- Create cluster
- Get the details about that cluster so that terraform can communicate with it and provision resources
- Provision resources(nginx) using terraform