0% found this document useful (0 votes)
6 views

2-terraform tutorial

The document is a comprehensive Terraform cheat sheet covering Infrastructure as Code (IaC), Terraform's purpose, benefits, installation, and usage examples. It details key features, Terraform CLI commands, state management, remote backends, and input/output variables, along with practical examples for creating AWS resources. Additionally, it discusses Terraform workspaces, loops with count parameters, and the taint command for resource management.

Uploaded by

Suresh
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

2-terraform tutorial

The document is a comprehensive Terraform cheat sheet covering Infrastructure as Code (IaC), Terraform's purpose, benefits, installation, and usage examples. It details key features, Terraform CLI commands, state management, remote backends, and input/output variables, along with practical examples for creating AWS resources. Additionally, it discusses Terraform workspaces, loops with count parameters, and the taint command for resource management.

Uploaded by

Suresh
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 19

Terraform cheetsheet:

========================

Agenda:
=========
What is Infrastructure as Code (IaC)?
What is Terraform?
What are the benefits of using Terraform?
Terraform key features
How to get started using Terraform?
Terraform installation and setup
Terraform providers
Resources
Terraform CLI commands
Terraform variables
State management
Remote backends
What is Infrastructure as Code (IaC)?

What is Terraform?
----------------------
Terraform => infrastructure provisions on the major cloud providers

Configuration mgt => update install the sw on the server, server is alreay
created by
provisioning - server create

Provisioning: Terraform, pulumi, cloud formation


Configuration mgt: shef puppet, ansible

Terraform is a product by Hashicorp that uses Infrastructure as Code (IaC)


to provision cloud infrastructure.

What is Iac?
--------------
as Code (IaC) is a practice where infrastructure is managed and provisioned
using code
rather than manual processes.
Similar to application code, the infrastructure code is stored in a version
control systems (VCS),
that ensure infrastructure changes are trackable and scalable.
By defining infrastructure in descriptive, machine-readable files,
IaC enables automation, consistency, and repeatability while reducing human
error.

Why use Terraform?


---------------------

=> declarative approach allows users to define the desired state of their
infrastructure,
which Terraform then enforces.
This capability extends across various cloud providers and on-premises
environments,
offering flexibility and reducing the complexity of managing multi-cloud or
hybrid environments.
What are the benefits of using Terraform?
---------------------------------------------------
Traditionally, cloud infrastructure was managed manually without IaC
(Infrastructure as Code).

This method was inefficient and prone to errors.

Maintaining consistency was especially challenging when managing multiple


servers and clusters.

While configuration management tools were available, their support for


infrastructure was quite limited.

Benefit Description
-------------------
Consistency
Automation
Less risk
Modular and DRY
Declarative
Cloud agnostic
Ecosystem
Extendible
Agentless

How to get started using Terraform? installation:


----------------------------------
Step 1: create EC2 instance and create an token provide

terraform-token-busycoder

--------------------
----------------

step 2: connnect with mobaxerm


set up:

export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=

step 3: install terraform

installation step:
https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-
cli

check terraform version


terraform version

Example 1: creating an ec2 instance of aws:


---------------------------------------
ami-00bb6a80f01f03502
main.tf
-----------
provider "aws" {
region = "ap-south-1"
}

resource "aws_instance" "example" {


ami = "ami-0f1ba6e558ee844a5"
instance_type = "t2.micro"

tags = {
Name = "terraform-example"
}
}

terraform init

terraform plan

terraform apply

terraform destroy

terraform init:
we are telling terraform about provider, so that binary code related
to aws provider is configured to this machine-readable

terraform plan:
tell what changes going to happen on aws

terraform apply:
actually create infrastructure on aws

terraform destroy:
how terraform know which resouces to destroy?
terraform matain a file terraform-state.tf file what contain all information
of resouce ie created
using terraform

how terraform knows which resouce to destroy?


--------------------------------------------
terraform store state information in a file named terraform.tfstate

Example 2: creating an web server using terraform?


-------------------------------------------------
we want to create a web server on ec2 using terraform

let we do it manually to better understand this requirment:


step 1: create security group "terra-sec-group" that allow custom tcp 8080 for all
ip addresses
step 2: create an ec2 instance that use that sec group and add user data

#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p 8080 &

step 3: check using public ip address on port 8080


http://13.232.236.23:8080/

Now we want to create same stuff using terraform


-------------------------------------------------

provider "aws" {
region = "ap-south-1"
}
resource "aws_instance" "example" {
ami = "ami-0f1ba6e558ee844a5"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p 8080 &
EOF

user_data_replace_on_change = true

tags = {
Name = "terraform-example"
}
}
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}

now apply commands:


-----------------
terraform init

terraform plan

terraform apply

terraform destroy

Example 3: terraform input/output variables:


----------------------------------------------
terraform input variables:
------------------------
To allow you to make code more DRY and more configurable

Terraform input variables are used to pass certain values from outside of the
configuration or module.
They are used to assign dynamic values to resource attributes.
The difference between local and input variables is that input variables
allow you to pass values before the code execution.

What are Terraform Output Values?


-----------------------------------
Terraform outputs are used for two things: either printing details about a
resource/datasource/local/variable or exporting different details about these
if we are using a module.

They are very useful in both cases. For example, you can build different
connection strings
you can print in the console for easy use in an app, or you can export things
that can be referenced in another configuration/in another module,
facilitating the creation of other resources.

--------------------------------------------------
Examples:
--------------------------------------------------
int i=66;

variable "number_example" {
description = "An example of a number variable in Terraform"
type = number
default = 42
}

variable "list_example" {
description = "An example of a list in Terraform"
type = list
default = ["a", "b", "c"]
}

variable "list_numeric_example" {
description = "An example of a numeric list in Terraform"
type = list(number)
default = [1, 2, 3]
}

variable "map_example" {
description = "An example of a map in Terraform"
type = map(string)

default = {
key1 = "value1"
key2 = "value2"
key3 = "value3"
}
}

variable "object_example" {
description = "An example of a structural type in Terraform"
type = object({
name = string
age = number
tags = list(string)
enabled = bool
})

default = {
name = "value1"
age = 42
tags = ["a", "b", "c"]
enabled = true
}
}

variable "security_group_name" {
description = "The name of the security group"
type = string
default = "terraform-example-instance"
}

--------------------------------------------------

Example: terraform input variables:


---------------------------------

variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}

how to pass input variables?


----------------------
terraform apply -var
terraform apply -var-file
export TF_VAR_variablename

how to refer in tf file?


-----------------------
${var.server_port}==> 8080

Example:
----------
Note : if not pass default value then terraform will ask the value while creating
plan:
--------------------------------------------------------------------------------

variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
}
vs

variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}
-------------------------

main.tf
---------

variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}

provider "aws" {
region = "ap-south-1"
}

resource "aws_instance" "example" {


ami = "ami-0f1ba6e558ee844a5"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p ${var.server_port} &
EOF

user_data_replace_on_change = true

tags = {
Name = "terraform-example"
}
}

resource "aws_security_group" "instance" {


name = "terraform-example-instance"
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}

now apply commands:


-----------------
terraform init

terraform plan

terraform apply
terraform destroy

how to pass input parameter:


------------------------------
terraform plan -var "server_port:8080"

create a seperate tf file for variables:


------------------------------

vim variables.tf
-----------------
variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}

terraform apply -var-file

terraform output variable


--------------------------
let say i want to know public ip address of instance of ec2 that is created by
terraform?
we need to manully go and find output

what if we ask terraform to provide us using output variable


----------------------------------------------------------

output "public_ip" {
value = aws_instance.example.public_ip
description = "The public IP address of the web server"
}

Example:
---------
main.tf
----------

variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}

provider "aws" {
region = "ap-south-1"
}

resource "aws_instance" "example" {


ami = "ami-0f1ba6e558ee844a5"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p ${var.server_port} &
EOF

user_data_replace_on_change = true

tags = {
Name = "terraform-example"
}
}

resource "aws_security_group" "instance" {


name = "terraform-example-instance"
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
output "public_ip" {
value = aws_instance.example.public_ip
description = "The public IP address of the web server"
}

now apply commands:


-----------------
terraform init

terraform plan

terraform apply

terraform destroy

State File Management


-----------------------

What is Terraform state file?


--------------------------
Terraform state file contain a custom json format that record
a mapping from terraform resouce in your configuration file to
the representation in the real world

Terraform state file: apply the state change based on configuration

cat terraform.tfstate
it contain information in json formate about all the resources created

Terraform Remote Backend with AWS S3


---------------------------------
if we store terraform.tfstate in git:
--------------------------------------
error changes are more due to not pulling lastest changes by team member
no logging feature
for security concern we should not keep terraform.tfstate into git

best way to store terraform.tfstate is use Remote Backend with AWS S3


-----------------------------------------------------------------
we will store store terraform.tfstate to shared resouces
such as aws s3, other cloud storage

mkdir test1
and run 6-a-bucket-DynamoTable.tf

mkdir test2
and run 6-b-RemoteBackend.tf

now apply commands:


-----------------
terraform init

terraform plan

terraform apply

terraform destroy

Note: delete both resouces

Need of Terraform workspace


-----------------------
till now all the configuration is store in default namespace

terraform workspace show


will display default namespace

Instead to maintain entire terraform code in single file or folder


it is better to isolate terraform configuration for each environments
so that tfstate file can be maintain easily

dev
stage
prod
How to create new workspace?
----------------------------
terraform workspace allow you to store your terraform state in multiple
seperate , named workspace. terraform start with a single workspace
called "default"

create an new workspace :


------------------------

terraform workspace new devops-busycoder1

Terraform workspace allow to run terraform workspace new and deploy an new
copy of exact same infrastructure
but storing the state in a seperate file

Limitation of isolatation with workspace:"


----------------------------------------

The state file of all the workspaces are stored in the same backend

workspace is not visible in the code on the terminal unless you run terraform
workspace command

Note: terraform env information store in the same s3 bucket

Now how to destroy the resource created in namespaces:


-------------------------------------------
terraform workspace show
terraform destroy

now we will swith to devops-busycoder1


----------------------------------------

terraform workspace select devops-busycoder1


terraform destroy

now we will swith to default and destory the resouce created


----------------------------------------

terraform workspace select default


terraform destroy

now dont forget to delete bucket and dynamodb table etc:


---------------------------------------------------------
cd ..
cd demo1

Loops With Count Parameter


----------------------------
Terraform is declartive language still it provide serveral different looping
constructs each intended to be used in a slightly different scenario
counter paramsters : to loop over resouce and modules

What if i want to create more then resouce with the same configuration?
loop

main.tf
-------------------
provider "aws" {
region = "ap-south-1"
}

resource "aws_iam_user" "example" {


count = 3
name = "devops.${count.index}"
}

terraform init

terraform plan

dont run: we just want to check what resouce will be created:


-----------------------------------
terraform apply
terraform destroy

Example 2: more flexible then giving name devops1 devops2 etc


we want to give some realist name:
---------------------------------------------

main.tf
-----------
provider "aws" {
region = "ap-south-1"
}
resource "aws_iam_user" "example" {
count = length(var.user_names)
name = var.user_names[count.index]
}

variables.tf
-----------
variable "user_names" {
description = "Create IAM users with these names"
type = list(string)
default = ["devops", "test", "test1"]
}

outputs.tf
-----------
output "first_arn" {
value = aws_iam_user.example[0].arn
description = "The ARN for the first user"
}

output "all_arns" {
value = aws_iam_user.example[*].arn
description = "The ARNs for all users"
}

terraform init

terraform plan
----------------
check all user created as per requirments

terraform apply
terraform destroy

Terraform Taints:
-----------------
Terraform maintains a state file that contains the innformations regrarding
thie real world resouces managed by terrafrm IaC
When a resouce becomre misconfigured or corrupt it is desirable to replace
them with new instances , the taint command updates
the corrospoing resouces state as a "tainted" resouces so that in the next
apply
cycle, terraform replace that resouces

Usages: Terraform taint aws_infra_name

Example:
--------
mkdir demo2
cd demo2

main.tf
-----------

provider "aws" {
region = "ap-south-1"
}
resource "aws_instance" "devops" {
ami = "ami-0f1ba6e558ee844a5"
instance_type = "t2.micro"

tags = {
Name = "devops",
}
}

resource "aws_instance" "busycoder" {


ami = "ami-0f1ba6e558ee844a5"
instance_type = "t2.micro"

tags = {
Name = "busycoder",
}
}

-------------------

Usage:

terraform init

terraform apply
terraform taint aws_instance.devops

ls
cat terraform.tfstate | grep taint

Now apply command terraform will recreate new ec2 instance (that was tainted)
------------------------------------------------------------
terraform apply

We can untaint an resource that was marked tainted by mistake


------------------------------------------------------------
terraform taint aws_instance.busycoder

terraform untaint aws_instance.busycoder

dont forget to run:


-------------------
terraform destroy

Assignment: Create AWS IAM User and Policy


-----------------------------------------------
we want to create 3 users : raj-bca, ekta-bca, gun-bca

and want to set policies for these users:


raj-bca: ec2 list
ekta-bca: s3 bucket list
gun-bca:

and then we want to link user with there policies:


-----------------------------------

main.tf
--------
provider "aws" {
region = "ap-south-1"
}
variable "username"{
type= list(string)
default = ["foo","bar","jar"]
}

resource "aws_iam_user" "lb" {


count = length(var.username)
name = element(var.username,count.index)
path = "/system/"

tags = {
tag-key = "tag-value"
}
}

resource "aws_iam_policy" "policy" {


name = "random-policy"
description = "My test policy"

policy = <<EOT
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListAllMyBuckets"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": "*"
}
]

}
EOT
}

resource "aws_iam_user_policy_attachment" "attachment" {


count = length(var.username)
user = aws_iam_user.lb[count.index].name
policy_arn = aws_iam_policy.policy.arn
}

terraform init

terraform apply
-----------------
seven resouce will be created

terraform destroy
misc:
-------------

All About Terraform Workspace


--------------------------------

partial configuration for backend:


------------------------------------

Limitation of Terraform backends

you need to write terraform code to create s3 bucket and dynamodb table
need to spefiy the remote backend configuration to your terraform code everytime
and run terraform init

Now in case if you want to delete S3 and dynamodb table you need to first remove
this configuration
from your code, rerun the terraform init command to tfstatefile locally to your
disk and finally run terraform destroy
so it is two way processes

You can use partial configuration for backend:


-------------------------------------------------

create a dir :demo1


cd demo1
and create main.tf

main.tf
-------------
terraform {
required_version = ">= 1.0.0, < 2.0.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}

provider "aws" {
region = "ap-south-1"
}
resource "aws_s3_bucket" "terraform_state" {

bucket = "ddevops-techstack21-busycoder1"

// This is only here so we can destroy the bucket as part of automated tests. You
should not copy this for production
// usage
force_destroy = true

# Enable versioning so you can see the full revision history of your
# state files
resource "aws_s3_bucket_versioning" "enabled" {
bucket = aws_s3_bucket.terraform_state.id
versioning_configuration {
status = "Enabled"
}
}

# Enable server-side encryption by default


resource "aws_s3_bucket_server_side_encryption_configuration" "default" {
bucket = aws_s3_bucket.terraform_state.id

rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}

# Explicitly block all public access to the S3 bucket


resource "aws_s3_bucket_public_access_block" "public_access" {
bucket = aws_s3_bucket.terraform_state.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}

resource "aws_dynamodb_table" "terraform_locks" {


name = "ddevops-techstack21-busycoder1"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"

attribute {
name = "LockID"
type = "S"
}
}

----------
terraform init

terraform plan

terraform apply
terraform destroy
--------------
create a dir : backend
cd backend
and create the resouces

-----------------------
# backend.hcl
----------------------

bucket = "ddevops-techstack21-busycoder1"
region = "ap-south-1"
dynamodb_table = "ddevops-techstack21-busycoder1"
encrypt = true

---------
main.tf
--------

terraform {
backend "s3" {
key = "example/terraform.tfstate"
}
}
provider "aws" {
region = "ap-south-1"
}

resource "aws_instance" "example" {


ami = "ami-0f1ba6e558ee844a5"
instance_type = "t2.micro"

tags = {
Name = "terraform-example"
}
}

------------------
terraform init -backend-config=backend.hcl

terraform plan

terraform apply

terraform destroy
Example: Build WebApp Cluster on AWS Cloud
--------------------------------------------
We will demonstrate how you can create scalable web app cluster on AWSCloud
using terraform.

We will create below resources like AWS launch configuration ,


Auto Scaling group,AWS Application Load Balancer and its components .
Finally we will access our webapp using the Load Balancer DNS.

AWS auto scalilng group:


------------------------
if load is more on web server then it will launch and manage web server
monitoring, replacing failed instance can be managed by aws auto scalilng
group

Eleastic load balance:


---------------------
routing to the instance with less load

Step 1:
1. define launch configuration, used by auto scaling group

Important ref:
--------------
terraform beginer guide
https://k21academy.com/terraform-iac/terraform-beginners-guide/

terraform important questions


https://k21academy.com/terraform-iac/terraform-interview-questions/

You might also like