Terraform Notes
Terraform Notes
com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Table of Contents
====================================================================================================
1
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.4.1 : Using Command Line Arguments: 36
4.4.2 : Using Environment Variables: 36
5.0 : How Does Terraform Work ?: 38
5.1 : Some Basic Commands : 40
5.2 : Task : Create repos on github using Terraform 41
6.0 Tasks : Use Aws Provider and perform Sub task tasks : 69
6.1.0 : Create Aws Instance only. 69
6.2.0 : Create key pair for our instance and assign to it 72
6.3.0 : Create Security Group for our instance and assign to it 78
Dynamic Blocks : 83
6.4.0 : Create Security Group with use of ingress dynamic block & then assign to instance 83
Terraform Taint or Terraform replace : 87
6.5.0 : Pass userdata in aws instance. 89
7.0: Provisioners : 91
7.0.1 : Use of file provisioner 92
7.0.2 : Use of local-exec provisioner 100
Categories of Provisioners: 103
7.0.3 : Use of remote-exec provisioner 105
8.0: Data Sources : 110
8.0.1: Task : Use Data source to fetch ami id from aws 111
8.0.2: Task : Use Data source and create instance 117
9.0 : Version Constraints 121
9.0.1: Task : Use version constraint 121
10.0 : Terraform graph 122
11.0 : Terraform workspace 123
12.0 : Terraform Module 126
12.0.1 : Task : Create Module and use it in creation of Instance 126
12.0.2 : Task : How to return some output from module block like print aws instance Public_ip 133
13.0 : Terraform Backend 135
====================================================================================================
2
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
What is a Terraform Backend? 135
Types of Terraform Backends 135
Why Use a Remote Backend? 135
Basic example of configuring an S3 backend: 138
13.0.1 : Task : Configure aws for remote backend and state locking 139
13.0.2: What happens if multiple people perform Terraform operations concurrently? 144
13.0.3: What if multiple environments (Workspaces) 144
13.0.4: Terraform migrate ( migrating remote backend or state file ) 147
14.0 : Misc Things 151
14.1: Conditional Expressions 151
14.2: Multiple Providers 155
14.3 : Multiple Region or Multiple Accounts 155
14.3 : How to use , depends_on 157
Ref. & Source code : 158
—-----------------------------------------------------------------------------------------------
====================================================================================================
3
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Terraform is an open-source infrastructure as code (IaC) tool that allows you to define and manage cloud and
on-premises infrastructure using a human-readable configuration file. It enables you to version, manage, and deploy
infrastructure resources across multiple cloud providers, such as AWS, Azure, Google Cloud, and more.
1.0.1 : Terraform
====================================================================================================
4
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
○ terraform apply: Creates or updates infrastructure resources as defined in the configuration files.
○ terraform destroy: Deletes infrastructure resources defined in the configuration files.
5. Execution Plans:
○ Terraform provides an execution plan that shows what actions will be taken before making any changes, helping
understand the impact of changes.
6. Declarative Language:
○ Using HCL (HashiCorp Configuration Language), you declare what you want the infrastructure to look like, and
Terraform figures out how to achieve that state.
1.0.2: Ansible
1. Configuration management:
○ Ansible is used to manage the configuration of operating systems and applications, ensuring they meet the desired
state.
2. Needs various modules to maintain state:
○ Ansible requires the use of different modules to manage and maintain the state of the infrastructure and
configurations. While it doesn’t maintain a global state file like Terraform, it uses modules to ensure the desired state is
achieved for each task.
3. Not as robust as Terraform for infrastructure creation:
○ While Ansible can provision infrastructure, it is not as powerful or specialized as Terraform for creating complex
infrastructure from scratch. Ansible excels more in post-provisioning configuration management.
4. Agentless:
○ Ansible doesn’t require any agents to be installed on the managed nodes. It uses SSH for communication, making it
easy to set up and use.
5. Playbooks:
○ Using YAML syntax, Ansible playbooks define the desired state of systems and the steps to achieve that state.
6. Orchestration:
○ Ansible can orchestrate complex tasks that involve multiple servers and services.
====================================================================================================
5
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
1.0.3: Which One to Choose: Terraform or Ansible for Infrastructure as Code (IaC)?
● While Ansible can provision infrastructure, it is not as powerful or specialized as Terraform for managing complex
infrastructure lifecycles and dependencies.
● Ansible is mainly designed for configuration management, focusing on managing the state and configuration of software and
systems.
====================================================================================================
6
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
2.0 : Installation
One more thing I'm using , VS code & I am going to install HashiCorp terraform plugin ( Optional )
====================================================================================================
7
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
3.0 : Terraform Block Structure
first.tf
output "hello" {
value = "hello world"
}
In Terraform, a block is a container for one or more related configurations. Blocks are used to define various aspects of your
infrastructure and can be of different types, such as resource, variable, output, provider, etc.
output Block : The output block is used to define values that are to be displayed
value Attribute : The value attribute within an output block specifies the actual value that will be output.
====================================================================================================
8
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
vishal@vishalk17:~/Documents/Learn/Terraform/hello-world$ ls
first.tf
Changes to Outputs:
+ hello = "hello world"
You can apply this plan to save these new output values to the Terraform state, without changing any real
infrastructure.
─────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly
these actions if you run "terraform
apply" now.
The terraform plan command is used to create an execution plan, which shows what actions Terraform will take to reach the
desired state defined in your configuration files. It does not make any changes to real infrastructure. Instead, it provides a preview of
what will happen when you apply the configuration.
====================================================================================================
9
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
3.0.2 : Task: Write Hello World Terraform Configurations in JSON Format
first.tf.json
{
"output" : {
"hello" : {
"value": "hello vishal"
}
}
}
vishal@vishalk17:~/Documents/Learn/Terraform/hello-world-json$ ls
first.tf.json
vishal@vishalk17:~/Documents/Learn/Terraform/hello-world-json$ terraform plan
Changes to Outputs:
+ hello = "hello vishal"
You can apply this plan to save these new output values to the Terraform state, without changing any real
infrastructure.
─────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly
these actions if you run "terraform
apply" now.
====================================================================================================
10
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
3.0.3 : Task : Multiple Block in single terraform file
multiple.tf
output "first_block" {
value = "this is block1"
}
output "block2" {
value = "this is block2"
}
vishal@vishalk17:~/Documents/Learn/Terraform/multiple-block$ ls
multiple.tf
Changes to Outputs:
+ block2 = "this is block2"
+ first_block = "this is block1"
You can apply this plan to save these new output values to the Terraform state, without changing any real
infrastructure.
─────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly
these actions if you run "terraform
apply" now.
====================================================================================================
11
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.0 : Variables & Built-In-functions:
output "admin_user_is" {
value = "${var.admin_user}" # Referring to variable "admin_user"
}
vishal@vishalk17:~/Documents/Learn/Terraform/variable$ ls
print_admin_user.tf
vishal@vishalk17:~/Documents/Learn/Terraform/variable$ terraform plan
var.admin_user
Enter a value: vishalk17
Changes to Outputs:
+ admin_user_is = "vishalk17"
You can apply this plan to save these new output values to the Terraform state, without changing any real
infrastructure.
─────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly
these actions if you run "terraform
====================================================================================================
12
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
apply" now.
Variables can also be placed in separate files. Terraform will automatically load and apply all .tf files in the same directory.
print_admin_user.tf
output "admin_user_is" {
value = "${var.admin_user}" # Referring to variable "admin_user"
}
output "Pass_is" {
value = "${var.your_password}"
}
variables.tf
variable "your_password" {}
vishal@vishalk17:~/Documents/Learn/Terraform/variable$ ls
print_admin_user.tf variables.tf
vishal@vishalk17:~/Documents/Learn/Terraform/variable$ terraform plan
var.admin_user
Enter a value: vishalk17
var.your_password
====================================================================================================
13
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Changes to Outputs:
+ Pass_is = "my-pass"
+ admin_user_is = "vishalk17"
You can apply this plan to save these new output values to the Terraform state, without changing any real
infrastructure.
─────────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly
these actions if you run "terraform
apply" now.
Changes to Outputs:
+ Pass_is = "chinu"
+ admin_user_is = "vishalk17"
====================================================================================================
14
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.0.2 : Task : Variable : Read user Input , pass value using command , set default value for variable | print Output
xyz.tf
output "name" {
value = "${var.name}"
}
output "designation" {
value = "Designation is : ${var.designation}"
}
output "learning" {
value = "You Learning : ${var.learning}"
}
variables.tf
variable "name" {
default = "vishalk17" #default value if not Provided
}
variable "designation" {}
variable "learning" {
default = "cybersecurity" #default value if not Provided
}
====================================================================================================
15
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
vishal@vishalk17:~/Documents/Learn/Terraform/multi_variables$ ls
variables.tf xyz.tf
vishal@vishalk17:~/Documents/Learn/Terraform/multi_variables$ terraform plan
var.designation
Enter a value: DevOps
Changes to Outputs:
+ designation = "Designation is : DevOps"
+ learning = "You Learning : cybersecurity"
+ name = "vishalk17"
You can apply this plan to save these new output values to the Terraform state, without changing any real
infrastructure.
====================================================================================================
16
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Override one of Default value and pass one of value using command and other one keep Default
Changes to Outputs:
+ designation = "Designation is : DevOps"
+ learning = "You Learning : chinu"
+ name = "vishalk17"
You can apply this plan to save these new output values to the Terraform state, without changing any real
infrastructure.
====================================================================================================
17
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.1.0 : Types of Variable:
In Terraform, the type argument in the variable block specifies the data type of the variable. Defining a variable's type helps
Terraform understand what kind of value it should expect, which can help with validation, documentation, and avoiding errors.
Variable Types
output "name" {
value = "Your Name is ${var.admin_name}"
}
output "age" {
value = "Your Age is ${var.age}"
}
====================================================================================================
18
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
vars.tf
variable "admin_name"{
type = string
default = "admin"
}
variable "age" {
type = number
}
Check 1 : Age variable data type is number , what if we provide anything other than number.
Changes to Outputs:
+ name = "Your Name is admin"
You can apply this plan to save these new output values to the Terraform state, without changing
any real infrastructure.
╷
│ Error: Invalid value for input variable
│
│ on vars.tf line 6:
│ 6: variable "age" {
====================================================================================================
19
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
│
│ Unsuitable value for var.age set using an interactive prompt: a number is required.
Conclusion: other than number is not acceptable as type of age variable is number
Check 2: Provide the correct input according to the data types we set.
Changes to Outputs:
+ age = "Your Age is 16"
+ name = "Your Name is admin"
You can apply this plan to save these new output values to the Terraform state, without changing
any real infrastructure.
──────────────────────────────────────────────────────────────────────────
───────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take
exactly these actions if you run "terraform
apply" now.
====================================================================================================
20
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.1.2 : Task: use of list type in variable
main.tf
output "user_names" {
value = "Current User is ${var.names[0]}" # From list take first value i.e., [0]
}
var.tf
variable "names" {
type = list
}
Changes to Outputs:
+ user_names = "Current User is vishal"
Changes to Outputs:
+ user_names = "Current User is vishal"
====================================================================================================
21
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.2: Built-in Functions :
In Terraform, functions are built-in capabilities that allow you to transform and combine data within your
configurations. These functions can be categorized into several types based on their functionality.
Ref.: https://developer.hashicorp.com/terraform/language/functions
====================================================================================================
22
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Here are some of examples of functions :
String Functions:
upper("hello") // "HELLO"
lower("HELLO") // "hello"
join Joins elements of a list into a single string with a specified separator.
====================================================================================================
23
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Numeric Functions:
max(5, 10, 3) // 10
min(5, 10, 3) // 3
Collections Functions:
====================================================================================================
24
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
File Functions:
timestamp() // "2024-07-26T14:58:00Z"
tonumber("42") // 42
====================================================================================================
25
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.2.1: Task: Use Join Function with variable
main.tf
output "user_names" {
value = "Current User is ${join("+++", var.names)}"
}
====================================================================================================
26
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
var.tf
variable "names" {
type = list
default = ["vishal", "chinu","toffe" ]
}
Changes to Outputs:
+ user_names = "Current User is vishal+++chinu+++toffe"
You can apply this plan to save these new output values to the Terraform state, without
changing any real infrastructure.
─────────────────────────────────────────────────────────────────────
──────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to
take exactly these actions if you
run "terraform apply" now.
====================================================================================================
27
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.2.2: Task: Use Multiple Functions with variables
main.tf
# join Joins elements of a list into a single string with a specified separator.
output "user_names" {
value = "Current User is ${join("----->", var.names)}"
}
output "upperTitle_names" {
value = "upperTitle_names are ${upper(var.names[0])} and ${title(var.names[1])}"
}
output "Name_encoded_base64" {
value = "Name_encoded_base64 User is ${base64encode(var.names[0])}"
}
var.tf
variable "names" {
type = list
default = ["vishal", "chinu","toffe" ]
}
====================================================================================================
28
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Changes to Outputs:
+ Name_encoded_base64 = "Name_encoded_base64 User is dmlzaGFs"
+ upperTitle_names = "upperTitle_names are VISHAL and Chinu"
+ user_names = "Current User is vishal----->chinu----->toffe"
You can apply this plan to save these new output values to the Terraform state, without changing any real
infrastructure.
─────────────────────────────────────────────────────────────────────────────────
──────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly
these actions if you
run "terraform apply" now.
====================================================================================================
29
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.2.3: Task: Use of Map Variable
variable "price" {
type = map
default = {
"Mobile" = "50k"
"Laptop" = "85k"
}
}
# lookup retrieves the value of a single element from a map, given its key.
# If the given key does not exist, the given default value is returned instead.
output "Price_of_Laptop" {
value = "Price of Laptop is ${lookup(var.price, "Laptop")}"
}
Changes to Outputs:
+ Price_of_Laptop = "Price of Laptop is 85k"
====================================================================================================
30
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.2.4: Task: Use of Map Variable Dynamically
map.tf
variable "price" {
type = map
default = {
"Mobile" = "50k"
"Laptop" = "85k"
}
}
variable "item" {
type = string
}
# lookup retrieves the value of a single element from a map, given its key.
# If the given key does not exist, the given default value is returned instead.
output "Prices" {
value = "Price of ${var.item} is ${lookup(var.price, "${var.item}")}"
}
====================================================================================================
31
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Changes to Outputs:
+ Prices = "Price of Mobile is 50k"
—----------------------
Changes to Outputs:
+ Prices = "Price of Laptop is 85k"
====================================================================================================
32
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
In Terraform, .tfvars files are used to set variable values separately from the main configuration files. This allows for better
organization and reuse of configurations across different environments.
main.tf
# map collection of key-value pairs.A collection of key-value pairs.
variable "price" {
type = map
}
variable "item" {
type = string
}
variable "my_key" {
type = string
}
# lookup retrieves the value of a single element from a map, given its key.
# If the given key does not exist, the given default value is returned instead.
output "Prices" {
value = "Price of ${var.item} is ${lookup(var.price, "${var.item}")}"
}
output "key" {
value = "Key is ${var.my_key}"
}
====================================================================================================
33
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
prod.tfvars
price = {
"Mobile" = "50k"
"Laptop" = "85k"
}
item = "Mobile"
my_key = "7abcd"
Here, I have provided all the values in a separate file called prod.tfvars.
vishal@vishalk17:~/Documents/Learn/Terraform/tfvars_first$ ls
main.tf prod.tfvars
Changes to Outputs:
+ Prices = "Price of Mobile is 50k"
+ key = "Key is 7abcd"
====================================================================================================
34
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.4.0 : Alternative Ways to Pass Variables :
Besides using .tfvars files, you can pass variables in other ways:
main.tf
variable "price" {
type = map
}
variable "item" {
type = string
}
variable "my_key" {
type = string
}
# lookup retrieves the value of a single element from a map, given its key.
# If the given key does not exist, the given default value is returned instead.
output "Prices" {
value = "Price of ${var.item} is ${lookup(var.price, "${var.item}")}"
}
output "key" {
value = "Key is ${var.my_key}"
}
====================================================================================================
35
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
4.4.1 : Using Command Line Arguments:
Or
Changes to Outputs:
+ Prices = "Price of Laptop is 90k"
+ key = "Key is 54"
====================================================================================================
36
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Changes to Outputs:
+ Prices = "Price of Laptop is 90k"
+ key = "Key is 1234"
====================================================================================================
37
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
5.0 : How Does Terraform Work ?:
Core Workflow:
Configuration:
====================================================================================================
38
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Initialization:
● When you run terraform init, Terraform initializes the working directory by downloading necessary plugins and setting up
the environment.
Planning:
● Running terraform plan compares the current state of your infrastructure with the desired state defined in your
configuration files.
● Terraform creates an execution plan, outlining the changes required to reach the desired state.
Applying Changes:
● Running terraform apply executes the plan and creates or modifies infrastructure resources based on the changes
outlined in the plan.
State Management:
● Terraform maintains a state file (terraform.tfstate) to track the current state of your infrastructure.
● This file is crucial for Terraform to understand the existing resources and determine the necessary changes.
Key Components:
Configuration Files: Define the desired state of your infrastructure using HCL syntax.
Terraform Core: The core engine that interprets configuration, creates plans, and applies changes.
Providers: Plugins that interact with specific cloud platforms or services (e.g., AWS, Azure, GCP).
State File: Stores information about the current state of your infrastructure.
====================================================================================================
39
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
5.1 : Some Basic Commands :
Terraform Providers
● terraform providers: Lists the Terraform providers that will be used in the current directory.
● terraform init: Initializes the Terraform working directory, installing any necessary plugins.
● terraform plan: create an execution plan for your Terraform configuration files. It provides a detailed preview of the changes Terraform
will make to your infrastructure to achieve the desired state defined in your configuration files.
● terraform validate: Validates the Terraform configuration files for syntax and correctness.
● terraform refresh: Updates the Terraform state file to match the current infrastructure.
● terraform show: provide a human-readable output of the Terraform state or plan file. It helps you to understand the current state of
your infrastructure or review the planned changes before applying them.
● terraform console: Opens an interactive Terraform console allows you to query and evaluate Terraform expressions, inspect the
current state, and interact with your Terraform configuration in real-time.
● terraform fmt: Automatically formats the Terraform configuration files for readability and consistency.
====================================================================================================
40
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
5.2 : Task : Create repos on github using Terraform
- So, we need one of Provider , In our case its Github , as we are going to create repos on github
- Visit https://registry.terraform.io/browse/providers and search if there is any github Provider
====================================================================================================
41
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
- Click on Documentations
====================================================================================================
42
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
- I have added like this.
====================================================================================================
43
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
main.tf
## main configuration of terraform ##
staging.tfvars
## Variable values ##
====================================================================================================
44
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
variables.tf
## Store variables here ##
variable "github_token" {
type = string
sensitive = true
}
====================================================================================================
45
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
So , after terraform init. Command it has created one file and one of directory
vishal@vishalk17:~/Documents/Learn/Terraform/providers/github$ tree -a
.
├── main.tf
├── staging.tfvars
├── variables.tf
├── .terraform
│ └── providers
│ └── registry.terraform.io
│ └── hashicorp
====================================================================================================
46
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
│ └── github
│ └── 6.2.3
│ └── linux_amd64
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ └── terraform-provider-github_v6.2.3
├── .terraform.lock.hcl
.terraform: This directory is created by Terraform to store the plugins and modules required for your project. It includes
downloaded provider binaries and other necessary files.
.terraform.lock.hcl: This file is created by Terraform to lock the versions of the providers used in your project. It ensures that
the same versions of providers are used consistently, avoiding unexpected changes when you run terraform init in the future.
● terraform fmt: Automatically formats the Terraform configuration files for readability and consistency.
Before
====================================================================================================
47
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
After :
● terraform validate: Validates the Terraform configuration files for syntax and correctness.
====================================================================================================
48
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
terraform plan: create an execution plan for your Terraform configuration files. It provides a detailed preview of the
changes Terraform will make to your infrastructure to achieve the desired state defined in your configuration files.
● Compares State: Compares current infrastructure state with the desired state. current state is usually stored in a state file
(terraform.tfstate).
● No Changes Applied: Only shows the plan; does not apply changes.
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the
following symbols:
+ create // it will going to create as per configs
====================================================================================================
49
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
+ allow_merge_commit = true
+ allow_rebase_merge = true
+ allow_squash_merge = true
+ archived = false
+ default_branch = (known after apply)
+ delete_branch_on_merge = false
+ description = "My first repo"
+ etag = (known after apply)
+ full_name = (known after apply)
+ git_clone_url = (known after apply)
+ html_url = (known after apply)
+ http_clone_url = (known after apply)
+ id = (known after apply)
+ merge_commit_message = "PR_TITLE"
+ merge_commit_title = "MERGE_MESSAGE"
+ name = "first_repository_terraform"
+ node_id = (known after apply)
+ primary_language = (known after apply)
+ private = (known after apply)
+ repo_id = (known after apply)
+ squash_merge_commit_message = "COMMIT_MESSAGES"
+ squash_merge_commit_title = "COMMIT_OR_PR_TITLE"
+ ssh_clone_url = (known after apply)
+ svn_url = (known after apply)
+ topics = (known after apply)
+ visibility = "public"
+ web_commit_signoff_required = false
====================================================================================================
50
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
51
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
+ web_commit_signoff_required = false
─────────────────────────────────────────────────────────────────────────────────
──────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly
these actions if you
run "terraform apply" now.
====================================================================================================
52
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
After Terraform Apply :
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the
following symbols:
+ create
====================================================================================================
53
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
54
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
+ merge_commit_message = "PR_TITLE"
+ merge_commit_title = "MERGE_MESSAGE"
+ name = "second_repository_terraform"
+ node_id = (known after apply)
+ primary_language = (known after apply)
+ private = (known after apply)
+ repo_id = (known after apply)
+ squash_merge_commit_message = "COMMIT_MESSAGES"
+ squash_merge_commit_title = "COMMIT_OR_PR_TITLE"
+ ssh_clone_url = (known after apply)
+ svn_url = (known after apply)
+ topics = (known after apply)
+ visibility = "public"
+ web_commit_signoff_required = false
github_repository.second_repository_terraform: Creating...
github_repository.first_repository_terraform: Creating...
github_repository.first_repository_terraform: Still creating... [10s elapsed]
github_repository.second_repository_terraform: Still creating... [10s elapsed]
====================================================================================================
55
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
—-------------------------------------
terraform show: provide a human-readable output of the Terraform state or plan file. It helps you to understand the current state
of your infrastructure or review the planned changes before applying them.
====================================================================================================
56
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
allow_merge_commit = true
allow_rebase_merge = true
allow_squash_merge = true
allow_update_branch = false
archived = false
default_branch = "main"
delete_branch_on_merge = false
description = "My first repo"
etag =
"W/\"446ad0b721fbbdf91d87a9f157051edb1bf8390cb5cbbc8aef3677cd95ba09de\""
full_name = "vishalk17/first_repository_terraform"
git_clone_url = "git://github.com/vishalk17/first_repository_terraform.git"
has_discussions = false
has_downloads = false
has_issues = false
has_projects = false
has_wiki = false
homepage_url = null
html_url = "https://github.com/vishalk17/first_repository_terraform"
http_clone_url = "https://github.com/vishalk17/first_repository_terraform.git"
id = "first_repository_terraform"
is_template = false
merge_commit_message = "PR_TITLE"
merge_commit_title = "MERGE_MESSAGE"
name = "first_repository_terraform"
node_id = "R_kgDOMb2Nlw"
primary_language = null
private = false
repo_id = 834506135
squash_merge_commit_message = "COMMIT_MESSAGES"
====================================================================================================
57
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
squash_merge_commit_title = "COMMIT_OR_PR_TITLE"
ssh_clone_url = "[email protected]:vishalk17/first_repository_terraform.git"
svn_url = "https://github.com/vishalk17/first_repository_terraform"
topics = []
visibility = "public"
vulnerability_alerts = false
web_commit_signoff_required = false
security_and_analysis {
secret_scanning {
status = "enabled"
}
secret_scanning_push_protection {
status = "enabled"
}
}
}
# github_repository.second_repository_terraform:
resource "github_repository" "second_repository_terraform" {
allow_auto_merge = false
allow_merge_commit = true
allow_rebase_merge = true
allow_squash_merge = true
allow_update_branch = false
archived = false
default_branch = "main"
delete_branch_on_merge = false
description = "My second repo"
etag =
====================================================================================================
58
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
"W/\"69da422869ef1b6d60cd71ff4c72a6e05236075153485165f9cc146148289674\""
full_name = "vishalk17/second_repository_terraform"
git_clone_url = "git://github.com/vishalk17/second_repository_terraform.git"
has_discussions = false
has_downloads = false
has_issues = false
has_projects = false
has_wiki = false
homepage_url = null
html_url = "https://github.com/vishalk17/second_repository_terraform"
http_clone_url = "https://github.com/vishalk17/second_repository_terraform.git"
id = "second_repository_terraform"
is_template = false
merge_commit_message = "PR_TITLE"
merge_commit_title = "MERGE_MESSAGE"
name = "second_repository_terraform"
node_id = "R_kgDOMb2Nig"
primary_language = null
private = false
repo_id = 834506122
squash_merge_commit_message = "COMMIT_MESSAGES"
squash_merge_commit_title = "COMMIT_OR_PR_TITLE"
ssh_clone_url = "[email protected]:vishalk17/second_repository_terraform.git"
svn_url = "https://github.com/vishalk17/second_repository_terraform"
topics = []
visibility = "public"
vulnerability_alerts = false
web_commit_signoff_required = false
security_and_analysis {
====================================================================================================
59
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
secret_scanning {
status = "enabled"
}
secret_scanning_push_protection {
status = "enabled"
}
}
}
● terraform console: Opens an interactive Terraform console allows you to query and evaluate Terraform expressions,
inspect the current state, and interact with your Terraform configuration in real-time.
> github_repository.first_repository_terraform.full_name
"vishalk17/first_repository_terraform"
terraform refresh: Updates the Terraform state file to match the current infrastructure.
● maintains a state file (terraform.tfstate) to track the current state of your infrastructure.
====================================================================================================
60
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
vishal@vishalk17:~/Documents/Learn/Terraform/providers/github$ ls -la
total 40
drwxrwxr-x 3 vishal vishal 4096 Jul 27 19:10 .
drwxrwxr-x 3 vishal vishal 4096 Jul 27 01:06 ..
-rw-rw-r-- 1 vishal vishal 545 Jul 27 18:51 main.tf
-rw-rw-r-- 1 vishal vishal 101 Jul 27 18:48 staging.tfvars
drwxr-xr-x 3 vishal vishal 4096 Jul 27 18:38 .terraform
-rw-r--r-- 1 vishal vishal 1379 Jul 27 18:38 .terraform.lock.hcl
-rw-rw-r-- 1 vishal vishal 5970 Jul 27 18:55 terraform.tfstate
-rw------- 1 vishal vishal 203 Jul 27 19:13 .terraform.tfstate.lock.info
-rw-rw-r-- 1 vishal vishal 103 Jul 27 18:47 variables.tf
Before :
====================================================================================================
61
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
After .
====================================================================================================
62
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Note : This will not modify any existing configuration file. If You again apply previous configs it will update configuration as
mentioned in *.tf file
● terraform destroy: Destroys all resources managed by Terraform in the current directory.
● terraform destroy -target: Destroys a specific resource or module, rather than the entire configuration.
To destroy a specific resource in Terraform using the -target option, the syntax is as follows:
====================================================================================================
63
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Before :
====================================================================================================
64
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the
following symbols:
- destroy
====================================================================================================
65
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
- security_and_analysis {
- secret_scanning {
- status = "enabled" -> null
}
- secret_scanning_push_protection {
- status = "enabled" -> null
}
}
}
====================================================================================================
66
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
╷
│ Warning: Resource targeting is in effect
│
│ You are creating a plan with the -target option, which means that the result of this plan may not represent all
of the
│ changes requested by the current configuration.
│
│ The -target option is not for routine use, and is provided only for exceptional situations such as recovering
from errors
│ or mistakes, or when Terraform specifically suggests to use it as part of an error message.
╵
====================================================================================================
67
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
message.
╵
Destroy complete! Resources: 1 destroyed.
====================================================================================================
68
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
6.0 Tasks : Use Aws Provider and perform Sub task tasks :
My goal here is to create an AWS instance. To achieve this, we will divide the task into multiple subtasks. In the final task, we will
have an AWS instance with everything we need. Of course, we will learn to apply new and existing things together.
Be more generic, separating common values to allow easier editing, and ensure proper structure.
Requirement:
variables.tf
variable "auth" {
type = map(any)
}
variable "ami" {
type = string
}
variable "instance_name" {
type = string
}
variable "instance_type" {
type = string
====================================================================================================
69
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
variable "region" {
type = string
}
provider.tf
instance.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = "${var.ami}"
instance_type = "${var.instance_type}"
tags = {
Name = "${var.instance_name}"
}
}
====================================================================================================
70
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
test.tfvars
auth = {
access_key = "your-access-key"
secret_key = "your-secret-key"
}
ami = "ami-068e0f1a600cd311c"
instance_name = "amz-linux-2023"
instance_type = "t2.micro"
region = "ap-south-1"
====================================================================================================
71
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
6.2.0 : Create key pair for our instance and assign to it
====================================================================================================
72
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
vishal@vishalk17:~/Documents/Learn/Terraform/providers/aws/keys$ ls
id_rsa.pem id_rsa.pem.pub
Let’s check documentation, So that we will get an idea how we can do this,
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#argument-reference
====================================================================================================
73
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Based on what I'm observing we need to pass the content of the key in the public key field. For that we will use file function.
https://developer.hashicorp.com/terraform/language/functions/file
keys.tf
output "name" {
value = aws_key_pair.deployer.public_key
}
====================================================================================================
74
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
It returns just a dot. Ok now we have an idea how to deal with it .
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = "${var.ami}"
instance_type = "${var.instance_type}"
key_name = "instance_key"
tags = {
Name = "${var.instance_name}"
}
}
====================================================================================================
75
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Lets check plan and create instance with key pair.
====================================================================================================
76
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
77
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
6.3.0 : Create Security Group for our instance and assign to it
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
Create security_group.tf
tags = {
Name = "SG_vishal"
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
====================================================================================================
78
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
ingress {
from_port = 9090
to_port = 9090
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
====================================================================================================
79
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Now , how to get security group id .
Ref. https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
modify instance.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = "${var.ami}"
instance_type = "${var.instance_type}"
key_name = "instance_key"
# vpc_security_group_ids attribute expects a list of security group IDs,
# so we need to pass it as a list [...] instead of a string "..."
vpc_security_group_ids = [aws_security_group.SG_vishal.id]
tags = {
Name = "${var.instance_name}"
}
}
====================================================================================================
80
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
- heck terraform plan
- If everything is ok then apply changes using terraform apply
====================================================================================================
81
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
82
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Dynamic Blocks :
Ref.: https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks
In Terraform, a dynamic block is a way to generate repeatable nested blocks within a resource or data source using an expression
based on a collection of values.
dynamic "block_name" {
for_each = <collection>
content {
# block content
}
}
}
6.4.0 : Create Security Group with use of ingress dynamic block & then assign to instance
====================================================================================================
83
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Modify security_group.tf
tags = {
Name = "SG_vishal"
}
dynamic "ingress" {
for_each = [80,22,9090]
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
====================================================================================================
84
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Can we be more generic …? Why not…!
Modify security_group.tf
tags = {
Name = "SG_vishal"
}
dynamic "ingress" {
for_each = "${var.ports_list}"
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
====================================================================================================
85
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Modify variables.tf , add below line
variable "ports_list" {
type = list(number)
}
ports_list = [80,22,9090]
Done ,
====================================================================================================
86
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Terraform Taint or Terraform replace :
Terraform Taint :
In Terraform, the taint command is used to manually mark a resource as tainted, which means it is flagged for destruction and
recreation during the next terraform apply. This can be useful if you want to force a resource to be recreated, even if there are
no changes detected in its configuration.
Usage / Example :
And you want to taint the aws_instance.example resource, you would use:
After running this command, the resource will be marked as tainted (terraform.tfstate). The next time you run terraform apply,
Terraform will destroy the existing resource and create a new one.
To untaint resource :
====================================================================================================
87
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Terraform Replace :
terraform taint command has been deprecated, and the recommended approach is to use the -replace flag with
terraform apply
Example :
This command will destroy the existing aws_instance.example resource and create a new one during the same apply
operation.
====================================================================================================
88
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
6.5.0 : Pass userdata in aws instance.
AWS User Data is a feature in Amazon Web Services that allows you to pass configuration scripts or commands to an instance at the
time of its launch. This data can be used to perform various initialization tasks, such as installing software packages, configuring
settings, or running scripts when the instance boots up for the first time.
userdata.txt
Modify instance.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = var.ami
instance_type = var.instance_type
key_name = "instance_key"
tags = {
Name = "${var.instance_name}"
}
# user_data = file("${path.module/userdata.txt}")
====================================================================================================
89
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
user_data = file("${path.module}/userdata.txt")
}
====================================================================================================
90
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
7.0: Provisioners :
Provisioners are used to execute scripts or commands on a local or remote machine as part of the resource creation or destruction
process. They allow you to run custom actions on the resource after it's been created or before it's destroyed.
Although it is not recommended to use for config of instances as best configurations tools available like ansible.
Important Considerations:
- While provisioners can be helpful, they are generally discouraged for several reasons:
- Idempotency Issues: Provisioners can make it difficult to maintain infrastructure as code in a consistent state .
- Debugging Challenges: Troubleshooting issues with provisioners can be complex.
- External Dependencies: They often rely on external tools and configurations, making the infrastructure less self-contained.
Best Practices:
Use Configuration Management Tools: Leverage tools like Ansible, Chef, or Puppet outside of Terraform for resource configuration.
Types of Provisioners:
- file: Copies files or directories from the machine running Terraform to the newly created resource.
- local-exec: Executes a local command on the machine running Terraform.
- remote-exec: Executes a script on a remote resource
Expressions in provisioner blocks cannot refer to their parent resource by name. Instead, they can use the special self object.
The self object represents the provisioner's parent resource, and has all of that resource's attributes. For example, use
self.public_ip to reference an aws_instance's public_ip attribute.
====================================================================================================
91
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
1. File Provisioner:
The file provisioner copies files or directories from the machine running Terraform to the newly created resource.
Ref. : https://developer.hashicorp.com/terraform/language/resources/provisioners/file
instance.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = var.ami
instance_type = var.instance_type
====================================================================================================
92
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
key_name = "instance_key"
tags = {
Name = "${var.instance_name}"
}
# user_data = file("${path.module/userdata.txt}")
user_data = file("${path.module}/userdata.txt")
====================================================================================================
93
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
94
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
After looking at the error it seems connection blocks is missing which is essential to transfer file
Let's add it,
Ref. : https://developer.hashicorp.com/terraform/language/resources/provisioners/connection
instance.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = var.ami
instance_type = var.instance_type
key_name = "instance_key"
tags = {
Name = "${var.instance_name}"
}
# user_data = file("${path.module/userdata.txt}")
user_data = file("${path.module}/userdata.txt")
connection {
type = "ssh"
user = "${var.instance_default_user}"
private_key = file("${path.module}/keys/id_rsa.pem") // pass private key not a public key
host = "${self.public_ip}" // self : referring to current resource block
} // public_ip : arg of aws instance resource
====================================================================================================
96
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
### just an example how to print some output
output "user_data" {
value = aws_instance.instance-1.user_data
}
variable "instance_default_user" {
type = string
}
====================================================================================================
97
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
98
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Let's check our desired result in instance :
====================================================================================================
99
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
7.0.2 : Use of local-exec provisioner
Ref.: https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec
Modify instance.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = var.ami
instance_type = var.instance_type
key_name = "instance_key"
tags = {
Name = "${var.instance_name}"
}
# user_data = file("${path.module/userdata.txt}")
user_data = file("${path.module}/userdata.txt")
connection {
type = "ssh"
user = "${var.instance_default_user}"
private_key = file("${path.module}/keys/id_rsa.pem") // pass private key not a public key
====================================================================================================
100
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
provisioner "local-exec" {
command = "echo ${self.public_ip} > public_ip.txt"
}
provisioner "local-exec" {
environment = {
"name" = "vishal"
}
command = "env > env.txt" // we can export env variable of local machine (where terraform is running )
}
provisioner "local-exec" {
working_dir = "/home"
interpreter = [ "python3", "-c" ] // can use different interpreter like this
command = "print('hello vishal-chinu')"
}
}
====================================================================================================
101
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
vishal@vishalk17:~/Documents/Learn/Terraform/provisioners/local-exec$ ls
env.txt keys provider.tf security_group.tf terraform.tfstate.backup userdata.txt
instance.tf keys.tf public_ip.txt terraform.tfstate test.tfvars variables.tf
====================================================================================================
102
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Categories of Provisioners:
Provisioners can be categorized based on when they are executed during the lifecycle of a resource
1. Creation-Time Provisioners
2. Destroy-Time Provisioners.
1. Creation-Time Provisioners:
- Creation-time provisioners are only run during creation, not during updating or any other lifecycle. They are meant as a
means to perform bootstrapping of a system.
- If a creation-time provisioner fails, the resource is marked as tainted.
- A tainted resource will be planned for destruction and recreation upon the next terraform apply. Terraform does this
because a failed provisioner can leave a resource in a semi-configured state. Because Terraform cannot reason about what
the provisioner does, the only way to ensure proper creation of a resource is to recreate it. This is tainting.
Failure Behavior:
By default, provisioners that fail will also cause the Terraform apply itself to fail. The on_failure setting can be used to change
this. The allowed values are:
====================================================================================================
103
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
provisioner "local-exec" {
command = "echo The server's IP address is ${self.private_ip}"
on_failure = continue
}
}
2. Destroy-Time Provisioners:
- Destroy provisioners are run before the resource is destroyed.
- If they fail, Terraform will error and rerun the provisioners again on the next terraform apply. Due to this behavior, care
should be taken for destroy provisioners to be safe to run multiple times.
- They are typically used for cleanup tasks, such as de-registering services, revoking access, or removing files and
configurations that were set up during creation and backup of somethings.
provisioner "remote-exec" {
when = "destroy"
command = "aws s3 cp /etc/myapp/config.conf s3://my-backup-bucket/config.conf.bak"
}
tags = {
Name = "ConfigBackupInstance"
}
}
====================================================================================================
104
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
7.0.3 : Use of remote-exec provisioner
The remote-exec provisioner invokes a script on a remote resource after it is created. This can be used to run a configuration
management tool, bootstrap into a cluster, etc.
- Install nginx
- Install tree
- Create sample file and and put some data in it
- backup one of file from instance to local (where terraform is running)
nginx-service.sh
====================================================================================================
105
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
instance.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = var.ami
instance_type = var.instance_type
key_name = "instance_key"
tags = {
Name = "${var.instance_name}"
}
connection {
type = "ssh"
user = "${var.instance_default_user}"
private_key = file("${path.module}/keys/id_rsa.pem") // pass private key not a public key
host = "${self.public_ip}" // self : referring to current resource block
} // public_ip : arg of aws instance resource
====================================================================================================
106
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
}
# Execute Script and continue even if it failed
provisioner "remote-exec" {
on_failure = continue
script = "nginx-service.sh"
}
vishal@vishalk17:~/Documents/Learn/Terraform/provisioners/remote-exec$ ls
keys nginx-service.sh security_group.tf instance.tf keys.tf provider.tf test.tfvars
variables.tf
Final OutPut :
====================================================================================================
107
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
vishal@vishalk17:~/Documents/Learn/Terraform/provisioners/remote-exec$ ls
instance.tf keys keys.tf nginx-service.sh provider.tf ref.txt security_group.tf terraform.tfstate test.tfvars
variables.tf
vishal@vishalk17:~/Documents/Learn/Terraform/provisioners/remote-exec$ cat ref.txt
hello vishal
====================================================================================================
108
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
109
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
8.0: Data Sources :
Data sources are used to fetch information from external sources and make it available for use within your Terraform configuration.
They allow you to reference existing resources or services without having to define them in your configuration
Ref: https://developer.hashicorp.com/terraform/language/data-sources
1. Fetching Data: Data sources allow you to retrieve data from external sources, such as cloud providers, external APIs, or even
other Terraform configurations.
2. Read-Only: Data sources are read-only. You cannot modify or create resources using them; they are solely for retrieving
information.
Syntax: Data sources are defined using the data block, followed by the data source type and an identifier. For example:
data "aws_ami" "latest_amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
}
resource "aws_instance" "example" {
ami = data.aws_ami.latest_amazon_linux.id # AMI ID fetched from the aws_ami data source
instance_type = "t2.micro"
}
====================================================================================================
110
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
8.0.1: Task : Use Data source to fetch ami id from aws
- In the future, the AMI may update to the latest version, and its ID will also change. Therefore, we want to make it dynamic so
that we will always have the latest version of the image we want.
First, we will visit the AWS provider documentation and check what options are available to use.,
Ref. : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami
I got an idea here of what I'd like to do. With various filters, I can grab the AWS AMI ID.
====================================================================================================
111
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
112
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
How image specifications looks like ..? , let's find out on aws ami market place
Ref.: https://ap-south-1.console.aws.amazon.com/ec2/home?region=ap-south-1#AMICatalog
Now with this ami id: ami-025fe52e1f2dc5044 , Let’s find out more information in AMIs
Ref :
https://ap-south-1.console.aws.amazon.com/ec2/home?region=ap-south-1#Images:visibility=public-images;v=3;$case=tags:false%5
C,client:false;$regex=tags:false%5C,client:false
Then you will get all the information related to this AMI
====================================================================================================
113
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
—----------------
Note: AMi name might get change , we will pick common thing that may be same in future as well
====================================================================================================
114
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
ami_amazon_linux.tf
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "name"
values = ["al2023-ami-2023*"]
}
filter {
name = "owner-id"
values = ["137112412989"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
}
// argument for id :
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami#attribute-reference
output "aws_ami_id" {
value = data.aws_ami.amazon_linux_2023.id
}
====================================================================================================
115
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
provider.tf
variables.tf
variable "auth" {
type = map(any)
}
variable "region" {
type = string
}
test.tfvars
auth = {
access_key = "your-access-key"
secret_key = "your-secret-key"
}
region = "ap-south-1"
====================================================================================================
116
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Output:
ami_amazon_linux.tf
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "name"
values = ["al2023-ami-2023*"]
}
====================================================================================================
117
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
filter {
name = "owner-id"
values = ["137112412989"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
}
// argument for id :
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami#attribute-reference
output "aws_ami_id" {
value = data.aws_ami.amazon_linux_2023.id
}
instance.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = var.instance_type
key_name = "instance_key"
tags = {
Name = "${var.instance_name}"
}
}
====================================================================================================
118
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
variables.tf
variable "auth" {
type = map(any)
}
variable "instance_name" {
type = string
}
variable "instance_type" {
type = string
}
variable "region" {
type = string
}
test.tfvars
auth = {
access_key = "your-access-key"
secret_key = "your-secret-key"
}
instance_name = "amz-linux-2023"
instance_type = "t2.micro"
region = "ap-south-1"
====================================================================================================
119
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Output:
====================================================================================================
120
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
9.0 : Version Constraints
Version Constraints are used to specify which versions of a provider or module are compatible with your configuration. This ensures
that your configuration works with a specific set of versions, preventing breaking changes from affecting your infrastructure.
Ref.: https://developer.hashicorp.com/terraform/language/expressions/version-constraints
version.tf
terraform {
required_version = ">= 1.9.3" // Compatible with this version or higher than this
required_providers {
aws = {
source = "hashicorp/aws"
// ~> 5.0 allows versions such as 5.0.1, 5.1.0, or 5.9.9, but not 6.0.0 (major version ) or any later version.
version = "~> 5.0"
}
}
}
====================================================================================================
121
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
10.0 : Terraform graph
Produces a representation of the dependency graph between different objects in the current configuration and state.
graphviz
terraform graph | dot -Tpng > graph.png …….. Png / pdf / other
====================================================================================================
122
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
11.0 : Terraform workspace
Terraform workspaces are a feature that allows you to manage multiple environments (such as development, staging, and
production) within the same Terraform configuration. Workspaces help you maintain separate state files for different environments,
ensuring that changes in one environment do not affect another.
Default Workspace: When you first initialize a Terraform configuration, you start with a default workspace named default.
Use Cases :
● Separate Environments: Manage separate environments (e.g., dev, staging, prod) within the same configuration without
creating multiple directories or configurations.
● Testing and Development: Test changes in isolated workspaces before applying them to production.
● Isolated State Files: Keep state files isolated for different environments to avoid conflicts and ensure consistency.
terraform workspace list : Lists all workspaces. The current workspace will be indicated with *
terraform workspace new <name> : Creates a new workspace
terraform workspace select <name> : Switches to the workspace
terraform workspace delete <name>: Deletes the workspace with the specified <name>. This does not delete the
state files associated with it.
terraform workspace state show <resource> : Shows details of a specific resource from the state file in the
current workspace.
====================================================================================================
123
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
124
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
So , we have 3 workspaces, that's why Terraform created 3 different dir. To maintain a state file .
====================================================================================================
125
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
12.0 : Terraform Module
Modules allow you to define a set of resources and configurations that can be reused across different parts of your infrastructure.
Each module can be thought of as a building block that can be combined with other modules to create complex infrastructure.
This is just a sample thing in which we will learn , How one can create instance for their purpose.
Current Setup :
vishal@vishalk17:~/Documents/Learn/Terraform/modules$ ls
keys
vishal@vishalk17:~/Documents/Learn/Terraform/modules$ tree
.
└── keys
├── id_rsa.pem
└── id_rsa.pem.pub
1 directory, 2 files
ami_amazon_linux.tf
====================================================================================================
126
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
most_recent = true
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "name"
values = ["al2023-ami-2023*"]
}
filter {
name = "owner-id"
values = ["137112412989"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
}
// argument for id :
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami#attribute-reference
output "aws_ami_id" {
value = data.aws_ami.amazon_linux_2023.id
====================================================================================================
127
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
instance_md.tf
# ref : https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance
resource "aws_instance" "instance-1" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = var.instance_type_md
key_name = var.instance_key_md
tags = {
Name = var.instance_name_md
}
}
variables_md.tf
variable "instance_name_md" {
description = "This field is for Instance Name"
type = string
}
variable "instance_type_md" {
description = "This field is for Instance Type"
type = string
default = "t2.small"
}
variable "instance_key_md" {
type = string
}
====================================================================================================
128
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
0 directories, 3 files
main.tf
module "instance" {
source = "./instance-module"
keys.tf
====================================================================================================
129
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
provider.tf
variables.tf
variable "region" {
type = string
}
variable "access_key" {
type = string
}
variable "secret_key" {
type = string
}
variable "instance_name" {
description = "This field is for Instance Name"
type = string
}
variable "instance_type" {
description = "This field is for Instance Type"
type = string
}
====================================================================================================
130
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
prod.tfvars
instance_name = "amz-linux-2023"
instance_type = "t2.micro"
region = "ap-south-1"
vishal@vishalk17:~/Documents/Learn/Terraform/modules$ tree
.
├── instance-module
│ ├── ami_amazon_linux.tf
│ ├── instance_md.tf
│ └── variables_md.tf
├── keys
│ ├── id_rsa.pem
│ └── id_rsa.pem.pub
├── keys.tf
├── main.tf
├── prod.tfvars
├── provider.tf
└── variables.tf
2 directories, 10 files
Result :
export TF_VAR_access_key="your_access_key"
export TF_VAR_secret_key="your_secret_key"
====================================================================================================
131
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Note: Modules can be imported from various sources, including trusted sites like the Terraform Registry, Git repositories, or other
sources.
====================================================================================================
132
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
12.0.2 : Task : How to return some output from module block like print aws instance Public_ip
output_md.tf
output "instance_public_ip" {
value = aws_instance.instance-1.public_ip
}
module "instance" {
source = "./instance-module"
output "public_ip" {
value = module.instance.instance_public_ip
}
====================================================================================================
133
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Output:
====================================================================================================
134
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
13.0 : Terraform Backend
A backend defines where Terraform stores its state data files.
Ref.: https://developer.hashicorp.com/terraform/language/settings/backends/configuration
1. State Storage: It stores the current state of your infrastructure (what resources you've created, their configurations,
dependencies). This state is vital because Terraform uses it to plan changes and ensure it doesn't accidentally recreate
existing resources.
2. Locking: Backends prevent concurrent changes from different Terraform processes. This avoids conflicts where two
processes might try to modify the same resource simultaneously.
1. Collaboration:
- Shared State: Remote backends allow multiple team members to work on the same infrastructure simultaneously.
Everyone has access to the latest centralized state, preventing conflicts and ensuring consistency.
- Versioning: Many remote backends (like S3) support versioning, letting you track changes and revert to previous
states if needed.
====================================================================================================
135
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
2. Durability and Reliability:
- Data Loss Prevention: Local state files can be easily lost or corrupted. Remote backends offer secure, redundant storage,
protecting your state from accidental deletion or hardware failures.
- Backup and Recovery: Most remote backends have built-in backup mechanisms, making it easy to recover your state in
case of disaster.
3. State Locking:
- Conflict Prevention: Remote backends typically include locking mechanisms to prevent concurrent Terraform operations.
This ensures that only one person can modify the state at a time, avoiding errors and inconsistencies.
- Automatic Handling: Services like Terraform Cloud or AWS S3 with DynamoDB handle locking automatically, reducing the
risk of manual errors.
4. Security:
- Encryption: Many remote backends support encryption, both in transit and at rest, to protect your state data from
unauthorized access.
- Access Control: You can easily manage access permissions to your remote state, ensuring that only authorized individuals
can view or modify it.
5. Scalability:
- Large Projects: Remote backends are essential for large-scale infrastructure projects. They can handle the increased state
size and complexity, and they facilitate collaboration across multiple teams.
====================================================================================================
136
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Various Remote Backend Available:
====================================================================================================
137
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Basic example of configuring an S3 backend:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "terraform/state"
region = "us-west-2"
encrypt = true
dynamodb_table = "my-lock-table" # Optional, for state locking
}
}
Steps:
1. Add Backend Configuration: Include the backend block in your terraform configuration.
2. Initialize Backend: Run terraform init to configure the backend or migrate any existing state.
====================================================================================================
138
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
13.0.1 : Task : Configure aws for remote backend and state locking
terraform {
backend "s3" {
bucket = "vishalk17-terraform"
key = "terraform/terraform.tfstate"
region = "ap-south-1"
}
}
====================================================================================================
139
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
terraform {
backend "s3" {
bucket = "vishalk17-terraform" // bucket name
key = "terraform/terraform.tfstate"
region = "ap-south-1"
dynamodb_table = "vishalk17-terraform-table" // Table name for state locking
}
}
Now,
Note: Make sure aws user has required permissions to access s3 and dynamodb
- Create S3 bucket and Dynamodb table
====================================================================================================
140
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
141
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Output :
====================================================================================================
142
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
143
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
13.0.2: What happens if multiple people perform Terraform operations concurrently?
Conclusion : State Locking: DynamoDB handles state locking to prevent concurrent modifications. When one person runs a
Terraform operation, it acquires a lock on the state file, preventing others from making changes until the lock is released.
====================================================================================================
144
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Apply terraform configurations :
====================================================================================================
145
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
What will be the outcome ?
====================================================================================================
146
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Conclusion: Terraform created a new directory named env, under which it created subdirectories test and prod, corresponding to
the environments or workspaces created previously. Within each environment, Terraform maintains its own state file.
Note: The process is similar for using different backends. You only need to change the backend configuration, use terraform
init to initialize the new backend, and follow the on-screen instructions.
Modify remote_backend.tf
terraform {
backend "s3" {
bucket = "migrated-backend" // new s3 bucket
key = "terraform/terraform.tfstate"
region = "ap-south-1"
dynamodb_table = "vishalk17-terraform-table"
}
}
====================================================================================================
147
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Lets see what happens if i directly use terraform apply without initializing ,
====================================================================================================
148
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
149
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
State files successfully migrated to the new bucket,
====================================================================================================
150
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
14.0 : Misc Things
- I missed Some important things , So i will cover in this.
Here:
terraform.tfvars
auth = {
access_key = "your-access-key"
secret_key = "your-secret-key"
}
region = "ap-south-1"
====================================================================================================
151
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
1. # Configure the AWS Provider
2. provider "aws" {
3. region = var.region
4. access_key = lookup(var.auth, "access_key")
5. secret_key = lookup(var.auth, "secret_key")
6. }
7.
8. variable "region" {
9. type = string
10. }
11.
12. variable "auth" {
13. type = map(any)
14. }
15.
16. variable "amz-linux-ami" {
17. description = "This AMI for Production"
18. default = "ami-0a4408457f9a03be3"
19. }
20.
21. variable "ubuntu-ami" {
22. description = "This AMI for Development"
23. default = "ami-0ad21ae1d0696ad58"
24. }
25.
26. variable "setup_prod_env" {
27. type = string
28. description = "Setup production env? (y/n)"
29. }
30.
31.
32.
====================================================================================================
152
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
33. // lower: Converts a string to lowercase.
34. resource "aws_instance" "vishalk17-server" {
35. ami = lower(var.setup_prod_env) == "y" ? var.amz-linux-ami : var.ubuntu-ami
36. instance_type = "t2.micro"
37. tags = {
38. Name = "vishalk17-server"
39. }
40. }
Provider Block:
Variables :
Resource Block:
ami: Uses a conditional expression to choose the AMI based on the value of setup_prod_env.
====================================================================================================
153
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
====================================================================================================
154
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
14.2: Multiple Providers
1. provider "github" {
2. token = "8q948q4hjdofaauuidfh" # or `GITHUB_TOKEN`
3. }
4.
5. provider "aws" {
6. region = "us-west-2"
7. }
====================================================================================================
155
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
secret_key = "access-key-account-2"
}
====================================================================================================
156
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
14.3 : How to use , depends_on
depends_on allows you to specify explicit dependencies between resources. It ensures that Terraform creates resources in a
specific order, which is essential when resources rely on each other.
In this example, the aws_eip resource depends on the aws_instance resource. Terraform will create the aws_instance
resource first and then create the aws_eip resource, using the id of the aws_instance resource.
Without depends_on, Terraform might create resources in an incorrect order, leading to errors or unexpected behavior. For
instance, if you create an Elastic IP address (EIP) before the instance it's associated with, the EIP creation will fail.
====================================================================================================
157
Terraform / vishal-kapadi t.me/vishalk17 github.com/vishalk17 / vishalk17
—-----------------------------------------------—----------------------------------------------------------------------------------------------------------------------------
Ref. & Source code :
- https://github.com/vishalk17/devops/
- https://www.youtube.com/playlist?list=PL6XT0grm_Tfi21F8O0TvHmb78P2uEmhDq (Terraform Playlist Gaurav Sharma )
====================================================================================================
158