TERRAFORM COMPLETE NOTES BY DevOps Shack
TERRAFORM COMPLETE NOTES BY DevOps Shack
1. Introduction to Terraform
What is Terraform?
Terraform, developed by HashiCorp, is an open-source Infrastructure as Code (IaC) tool that allows
users to define, provision, and manage infrastructure resources through configuration files. These
resources can be physical or virtual components like servers, databases, networking components,
storage, or even Kubernetes clusters. The configurations are written in a declarative language known
as HashiCorp Configuration Language (HCL), which is both easy to learn and highly expressive.
The beauty of Terraform lies in its ability to abstract infrastructure management into a simplified,
declarative model. Instead of manually provisioning resources through cloud provider dashboards, or
writing scripts to automate them, you can simply describe what your infrastructure should look like,
and Terraform handles the rest.
Terraform is widely used because it can manage infrastructure across various cloud providers such as
AWS, Azure, Google Cloud, and even on-premises environments using providers like VMware and
OpenStack. With Terraform, you can manage all your infrastructure in one place, regardless of the
provider.
To better understand Terraform, it’s important to grasp the concept of Infrastructure as Code (IaC).
IaC allows you to automate the provisioning and management of infrastructure in a declarative or
imperative manner using code. Instead of configuring each resource manually (via cloud consoles or
command-line interfaces), you describe the desired state of your infrastructure, and the IaC tool (like
Terraform) will provision it for you.
• Version Control: Infrastructure configurations can be stored in version control systems like
Git, making it easy to track changes over time, roll back if necessary, and collaborate with
other team members.
Terraform operates using providers to interact with infrastructure APIs (like AWS or Azure APIs).
Here's a simplified view of how Terraform works:
1. Configuration Files: You define the desired state of your infrastructure in .tf files using HCL.
2. Terraform Plan: Terraform compares your desired configuration with the current
infrastructure state to generate a plan of action.
3. Terraform Apply: Terraform applies the changes defined in the plan by interacting with cloud
provider APIs to provision, update, or destroy resources.
4. State File: Terraform tracks the resources it manages through a state file (terraform.tfstate).
This state file acts as a record of what Terraform has done, allowing it to manage future
changes incrementally.
a. Multi-Cloud Support
One of the standout features of Terraform is its support for multiple cloud providers. Unlike many
IaC tools that are locked to a single provider (e.g., AWS CloudFormation for AWS), Terraform allows
you to manage infrastructure across multiple cloud environments. This is particularly useful for
organizations adopting multi-cloud or hybrid cloud strategies.
For example, you can manage AWS EC2 instances for your core infrastructure, Google Cloud Storage
for your data storage, and Azure Kubernetes Services (AKS) for your microservices deployment – all
within a single Terraform configuration. This flexibility enables teams to avoid vendor lock-in and
utilize the best features from each cloud provider.
provider "aws" {
region = "us-east-1"
}
Terraform uses a declarative model for defining infrastructure. This means you describe what you
want your infrastructure to look like, and Terraform handles how to achieve that state. For example,
rather than manually specifying every step to create an EC2 instance, you simply define the end
result, and Terraform will handle the underlying logic.
This contrasts with imperative approaches, where you have to specify step-by-step instructions for
every task. With Terraform's declarative nature, your configuration files are easier to understand,
more concise, and less error-prone.
c. Modular Infrastructure
Terraform promotes the use of modules, which are self-contained components of infrastructure that
can be reused across different projects. This makes your infrastructure modular and scalable. A
module is essentially a directory that contains .tf files, and it can be used to encapsulate a set of
resources.
For example, you can create a module for a Virtual Private Cloud (VPC), another module for EC2
instances, and a third for load balancers. You can then reuse these modules across multiple
environments (development, staging, production), without duplicating the code.
Terraform tracks the state of your infrastructure through a state file (terraform.tfstate). This state file
serves as a snapshot of your current infrastructure and allows Terraform to know what resources
already exist, what resources need to be modified, and what resources should be deleted.
The state file enables Terraform to perform incremental updates to your infrastructure, ensuring
that only the necessary changes are applied. This avoids the need for redeploying the entire
infrastructure, saving time and reducing the risk of errors.
• Locally: The state file is stored on the machine where Terraform is executed.
DevOps Shack
• Remotely: The state file can be stored remotely in services like Amazon S3 or Azure Blob
Storage. This is particularly useful for teams where multiple members are collaborating on
the same infrastructure.
a. Execution Plans
Terraform’s execution plan feature allows you to preview changes before they are applied. When you
run terraform plan, Terraform compares the current state of your infrastructure (stored in the state
file) with the desired state defined in the configuration files. It then generates a plan that shows
what actions Terraform will take, such as creating new resources, updating existing ones, or deleting
obsolete resources.
terraform plan
Output Example:
+ aws_instance.my_instance
ami: "ami-0c55b159cbfafe1f0"
instance_type: "t2.micro"
This feature provides an opportunity to review changes before applying them, reducing the risk of
accidental changes to production environments.
b. Resource Graph
Terraform builds a resource dependency graph that represents the relationships between your
resources. By understanding the dependencies, Terraform can determine which resources can be
created in parallel and which ones need to be created in a specific order.
For instance, if you're provisioning an EC2 instance and an S3 bucket that don’t depend on each
other, Terraform can create both in parallel. However, if your EC2 instance relies on a VPC being
created first, Terraform will ensure that the VPC is provisioned before the EC2 instance.
c. Multi-Provider Ecosystem
Terraform has a vast ecosystem of providers. Providers are responsible for interacting with cloud
providers and other APIs. Some of the most popular providers include:
• AWS Provider: Manages resources in Amazon Web Services (AWS), such as EC2 instances, S3
buckets, and RDS databases.
• Azure Provider: Manages resources in Microsoft Azure, including Virtual Machines, App
Services, and Azure Kubernetes Services (AKS).
DevOps Shack
• Google Cloud Provider: Manages resources in Google Cloud Platform (GCP), such as
Compute Engine, Cloud Storage, and Google Kubernetes Engine (GKE).
• Kubernetes Provider: Manages Kubernetes clusters and resources, allowing you to manage
Kubernetes infrastructure as code.
As mentioned earlier, Terraform supports modules, which promote reusability and help you organize
your infrastructure code. Modules are especially useful for large-scale infrastructure where you need
to manage hundreds or thousands of resources.
For example, a module that defines a VPC can be reused across multiple environments, ensuring
consistent network configurations for all environments.
Terraform configurations can be stored in version control systems like Git. This enables teams to
collaborate on infrastructure in the same way they collaborate on application code. Every change to
the infrastructure configuration is tracked in the version control history, making it easy to audit
changes, revert problematic updates, and collaborate across teams.
4. Terraform Installation
Terraform can be installed on various platforms such as Linux, macOS, and Windows. The installation
process is fairly straightforward and involves downloading the binary and setting it up in your
system’s path.
o Visit the official Terraform downloads page to download the latest version for Linux,
or use the wget command as shown below:
wget https://releases.hashicorp.com/terraform/1.0.0/terraform_1.0.0_linux_amd64.zip
o After downloading the binary, unzip the file to access the Terraform executable.
unzip terraform_1.0.0_linux_amd64.zip
o Move the unzipped binary to the /usr/local/bin/ directory so that it can be executed
from any terminal session.
o To ensure that Terraform was installed correctly, run the following command:
terraform --version
You should see the installed Terraform version displayed, confirming the installation was successful.
If you're using macOS, you can install Terraform using the package manager Homebrew.
o Homebrew is a popular package manager for macOS, and it simplifies the installation
of many development tools, including Terraform. You can install Homebrew by
running:
the Installation:
o Verify that Terraform has been installed correctly by checking the version:
terraform --version
For Windows, you can manually download the Terraform binary or use Chocolatey, a Windows
package manager.
1. Using Chocolatey:
o If you already have Chocolatey installed, you can install Terraform by running the
following command in an Administrator-level command prompt:
2. Manual Installation:
o Alternatively, you can download the Windows binary from the official website.
o Extract the zip file and place the terraform.exe in a directory that’s added to your
PATH environment variable, such as C:\Windows\System32.
o Open a Command Prompt window and type the following to check the installed
version of Terraform:
terraform --version
DevOps Shack
Once Terraform is installed, the next step is to create a basic configuration to start managing
infrastructure. Terraform uses configuration files written in HashiCorp Configuration Language (HCL)
to describe the desired state of infrastructure.
• Variables and Outputs: Variables allow for flexibility in configurations, and outputs provide
useful information after deployment.
Let’s walk through a simple example where we’ll set up an AWS EC2 instance using Terraform.
b. Defining a Provider
A provider is responsible for creating and managing infrastructure resources. Terraform supports
many cloud providers, including AWS, Azure, and Google Cloud. Before you can provision resources,
you need to define the provider for the platform you are working with. Example: Defining an AWS
Provider provider "aws" { region = "us-west-1" access_key = "your-access-key" secret_key =
"your-secret-key"
• The provider block defines the configuration required to interact with AWS.
• You can either specify your access keys directly in the configuration (not recommended for
security reasons) or use environment variables like AWS_ACCESS_KEY_ID and
AWS_SECRET_ACCESS_KEY for authentication.
c. Defining Resources
Once the provider is defined, you can start defining resources. Resources are the fundamental
components of infrastructure, such as virtual machines, storage, and networks.
d. Variables in Terraform
Terraform supports the use of variables to make configurations more dynamic and reusable. Instead
of hardcoding values like instance types or regions, you can define variables.
variable "instance_type" {
default = "t2.micro"
}
Variables can also be passed as command-line arguments during terraform apply, allowing you to
dynamically set values without editing configuration files.
e. Outputs in Terraform
Outputs are used to extract values from your infrastructure once it has been provisioned. This can be
useful for passing data between configurations or displaying important information like IP addresses,
resource IDs, etc.
aws_instance.example.public_ip
• After applying the Terraform configuration, the public IP address of the EC2 instance will be
displayed.
You can access output values using terraform output after the infrastructure has been provisioned:
Before running any Terraform commands, you need to initialize the project. The terraform init
command downloads the necessary provider plugins and sets up the working environment.
DevOps Shack
Example: terraform
init
This command is run from the directory containing your Terraform configuration files (.tf files). After
initialization, Terraform is ready to manage your infrastructure.
Once your configuration is ready, the next step is to preview the changes Terraform will make. This is
done using the terraform plan command.
Example:
terraform plan
The output will show what resources will be created, modified, or destroyed. This is a critical step to
avoid accidentally modifying production infrastructure.
Once you’re satisfied with the plan, you can apply the changes to create or update resources using
terraform apply. Example:
terraform apply
This will trigger Terraform to communicate with the cloud provider (AWS in this case) and provision
the resources defined in the configuration.
Terraform keeps track of the resources it manages using a state file. The state file (terraform.tfstate)
contains the current state of your infrastructure, and it’s critical for Terraform’s ability to manage
incremental changes.
By default, the state file is stored locally in the working directory, but it can also be stored remotely
using services like Amazon S3, Azure Blob Storage, or Google Cloud Storage. Remote state is useful
when multiple team members are working on the same infrastructure.
terraform show
When you’re finished with your infrastructure and want to clean up the resources, you can use the
terraform destroy command. This will remove all resources that were created by Terraform.
Example:
terraform destroy
Terraform will prompt for confirmation before proceeding with the deletion of resources.
DevOps Shack
As your infrastructure grows, it’s important to organize your Terraform configurations into modules
or separate files. By splitting resources into multiple .tf files or using modules, you can keep your
code organized and reusable.
For example:
/project
├── main.tf
├── variables.tf
├── outputs.tf
├── modules
│ ├── vpc
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
This separation allows different teams to work on different aspects of the infrastructure without
conflict.
6. Conclusion
In this module, we’ve walked through how to install Terraform on various platforms, create a basic
configuration using providers, resources, variables, and outputs, and manage your infrastructure
with commands like terraform plan, apply, and destroy.
7. Terraform Providers
A provider in Terraform is responsible for managing the lifecycle of resources. Terraform uses
providers to interact with different APIs and cloud platforms like AWS, Azure, Google Cloud, and
many others. Providers serve as the bridge between Terraform and the infrastructure it manages.
Providers define the set of resources and data sources that Terraform can manage. For example, the
AWS provider allows you to manage AWS resources like EC2 instances, S3 buckets, RDS databases,
etc.
Each provider exposes certain resources that can be created or managed. For example:
• The AWS provider exposes resources like aws_instance, aws_s3_bucket, aws_vpc, etc.
Terraform providers must be configured before you can use them to provision resources. Provider
configurations typically include authentication credentials (like access keys or tokens) and regional
settings.
b. Configuring a Provider
To configure a provider, you define a provider block in your Terraform configuration. For example, if
you're working with AWS, you would configure the AWS provider like this:
• region: Specifies the AWS region where Terraform will provision resources (e.g., us-west-1).
• access_key and secret_key: These are the AWS credentials that Terraform uses to
authenticate API requests. You can either hard-code them (not recommended for security
reasons) or use environment variables like AWS_ACCESS_KEY_ID and
AWS_SECRET_ACCESS_KEY.
Terraform supports managing infrastructure across multiple providers in the same configuration. For
example, you could manage both AWS and Google Cloud resources in a single project.
# AWS Provider
provider "aws" {
region = "us-west-1"
DevOps Shack
}
= "my-gcp-project" region
= "us-central1"
0c55b159cbfafe1f0" instance_type =
"t2.micro"
In this example:
• The Google Cloud provider is used to create a storage bucket in Google Cloud.
d. Provider Versioning
Terraform allows you to specify the version of the provider you want to use. This is important to
ensure that the same version of the provider is used across different environments, preventing
breaking changes that might occur due to provider updates.
The version argument ensures that Terraform uses version 2.x of the AWS provider. You can also pin
exact versions or specify version ranges.
DevOps Shack
If you need to interact with multiple accounts or regions within the same provider, you can use
provider aliases. For example, you may want to manage resources in multiple AWS regions.
}
In this example, the provider block with the alias "us_east" configures a second AWS provider for the
us-east-1 region, while the default provider uses us-west-1. The EC2 instance east_instance is
created in the us-east-1 region by referencing the aliased provider.
8. Terraform Resources
Resources are defined in resource blocks within the configuration files. Each resource block specifies
the type of resource to be managed, the provider that will manage it, and the configuration for that
resource.
a. Defining Resources
To define a resource in Terraform, you use the resource block, which has the following format:
• <PROVIDER>: The cloud provider that manages the resource (e.g., aws, azurerm, google).
• <RESOURCE_TYPE>: The type of resource being managed (e.g., instance, bucket, vpc).
• <CONFIGURATION>: A set of arguments that specify how the resource should be configured.
"t2.micro"
In this example:
• The resource name is my_instance, which is how Terraform identifies the resource in its
internal state.
• The ami and instance_type are arguments used to configure the EC2 instance.
b. Resource Attributes
Each resource in Terraform exposes a set of attributes that can be used to configure the resource or
extract information from it.
You can reference resource attributes in other parts of the configuration. For example:
c. Managing Dependencies
Terraform automatically manages the dependencies between resources. It understands that certain
resources depend on others, and it ensures that resources are created in the correct order.
For example, if you're creating an EC2 instance that depends on a VPC, Terraform will know that the
VPC must be created first.
Example: Creating a VPC and an EC2 instance that depends on the VPC:
DevOps Shack
resource "aws_vpc" "my_vpc" {
cidr_block = "10.0.0.0/16"
In this example, the EC2 instance will not be created until the VPC has been successfully provisioned.
Terraform allows you to control the lifecycle of resources using the lifecycle block. This is useful for
customizing how Terraform handles resource creation, update, or deletion.
• create_before_destroy: Ensures that a new resource is created before the old resource is
destroyed.
Example: Ensuring an EC2 instance is created before the old one is destroyed:
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
lifecycle {
create_before_destroy = true
In this case, Terraform will create a new EC2 instance before destroying the old one, minimizing
downtime.
e. Resource Provisioners
Provisioners allow you to execute scripts or commands on the resource after it has been created.
Provisioners can be useful for bootstrapping resources or performing configuration tasks.
DevOps Shack
Example: Running a shell script on an EC2 instance after it is created:
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
provisioner "remote-exec" {
inline = [
connection {
type = "ssh" user =
"ubuntu" private_key =
file("~/.ssh/id_rsa")
host = self.public_ip
In this example, the remote-exec provisioner is used to run commands on the EC2 instance after it is
created. The connection block specifies how Terraform should connect to the instance.
9. Conclusion
In this module, we covered the concepts of Terraform Providers and Terraform Resources in great
detail. Providers are essential for interacting with external systems, and resources are the
fundamental units of infrastructure that Terraform manages. We explored how to configure
providers, define resources, manage dependencies, and control resource lifecycles.
In the next module, we will dive into Variables, Outputs, and Data Sources, which are essential for
making Terraform configurations more dynamic and reusable.
DevOps Shack
a. Declaring Variables
Variables in Terraform are declared using the variable block. Each variable can have the following
attributes:
• sensitive: Marks the variable as sensitive, ensuring it is not displayed in logs or outputs.
In this example, we define a variable named aws_region with a default value of "us-west-1". The
description provides context about what the variable does.
DevOps Shack
b. Variable Types
• List: A collection of values. Useful for defining multiple instances, subnets, etc.
variable "instance_types" {
type = list(string)
variable "ami_ids" {
type = map(string)
default = {
west-1 = "ami-654321"
With these variable types, you can create dynamic configurations that can adapt to different input
values.
Once you’ve declared variables, you can reference them in your resource definitions using the var.
prefix. Example:
ami = var.ami_ids[var.aws_region]
instance_type = var.instance_type
In this example:
1. Default Values: If no value is provided, Terraform will use the default value defined in the
variable block.
2. Command Line Flags: You can pass variables directly through the terraform apply or
terraform plan command using the -var flag.
3. Environment Variables: Variables can be set using environment variables. For example, to
pass the AWS region, you can use:
export TF_VAR_aws_region=us-east-1
terraform apply
4. Terraform .tfvars Files: Variables can be defined in a separate .tfvars file and passed to
Terraform during runtime. Example of a terraform.tfvars file:
= "t2.medium"
e. Sensitive Variables
Sometimes, you may need to pass sensitive information, such as API keys, database passwords, or
SSH private keys. Terraform allows you to mark variables as sensitive, ensuring they are not exposed
in logs or outputs.
Example: variable
"db_password" {
type = string
sensitive = true
By setting the sensitive flag to true, Terraform will ensure that the value of db_password is not
displayed during terraform apply or terraform plan.
a. Defining Outputs
You can define an output using the output block. Each output block contains:
• sensitive: If set to true, the value will not be displayed in the Terraform output logs.
In this example:
b. Viewing Outputs
After applying the configuration, you can view outputs by running the terraform output command:
terraform output
This command will display all the outputs defined in your configuration. To view a specific output,
you can run:
One of the most powerful use cases for outputs is sharing data between Terraform modules. When
working with multiple modules, outputs from one module can be used as input for another module.
"./modules/vpc"
subnet_ids = module.vpc.subnet_ids
In this example, the vpc_id and subnet_ids from the vpc module are passed to the ec2 module as
inputs.
d. Sensitive Outputs
Similar to sensitive variables, Terraform allows you to mark outputs as sensitive. This ensures that
sensitive information, such as passwords or private keys, is not displayed in the output logs.
aws_db_instance.my_db.password sensitive
= true
Data sources allow you to query and reference existing infrastructure outside of Terraform. This is
useful for situations where you need to use resources that are managed by another team, project, or
process but still want to integrate them into your Terraform configuration.
A data source in Terraform allows you to read information about existing infrastructure components.
Data sources do not create new resources; instead, they retrieve data about resources that already
exist.
For example, you might want to query an existing AWS VPC to retrieve its ID and use it in your
configuration.
Terraform provides a wide range of data sources across different providers. Here are a few common
data sources:
• AWS:
• Azure:
• Google Cloud:
Let's look at a more advanced example where we query information from both AWS and Google
Cloud using data sources.
• The default AWS VPC is queried using the aws_vpc data source, and the subnet ID is used to
provision an EC2 instance.
• The existing Google Cloud Storage bucket is queried using the google_storage_bucket data
source, and its location is output after the infrastructure is applied.
Data sources are incredibly useful for making your Terraform configurations more dynamic and
flexible. Here are a few benefits:
• Seamless Integration with Existing Infrastructure: Data sources allow you to work with
resources that are managed outside of Terraform, reducing the need to recreate them.
• Cross-Project Reusability: You can reference shared infrastructure resources between teams
or projects without managing them directly.
• Avoids Redundant Resource Creation: You can query existing resources to avoid the
accidental duplication of infrastructure components.
13. Conclusion
In this module, we explored the concepts of variables, outputs, and data sources in Terraform. These
are critical components for making your infrastructure-as-code more dynamic, reusable, and flexible.
By using variables, you can parameterize your configuration for different environments. Outputs
allow you to extract and share valuable data from your infrastructure, while data sources enable you
to query and integrate with existing infrastructure outside of Terraform's direct control.
• Variables make configurations more dynamic, allowing for flexibility across environments.
• Outputs help expose critical information about your resources, which can be passed to other
modules or systems.
DevOps Shack
• Data Sources allow you to query existing infrastructure, helping you integrate Terraform with
infrastructure managed by other teams or providers.
In the next module, we will delve into State Management, Remote State, and Backends, which are
critical for ensuring that Terraform manages infrastructure consistently across team members and
environments.
Terraform uses a state file (terraform.tfstate) to keep track of the resources it manages. This state file
serves as a snapshot of your infrastructure's current configuration, allowing Terraform to know what
resources it has created, updated, or destroyed.
Without state, Terraform would have to query your cloud provider’s API every time to check the
current status of resources. Instead, the state file allows Terraform to incrementally manage
resources by comparing the current infrastructure state (stored in the state file) with the desired
configuration (defined in .tf files).
For example, when you run terraform apply, Terraform reads the state file to determine:
When Terraform creates or modifies resources, it updates the state file to reflect the changes. For
example, when you provision an EC2 instance on AWS, Terraform saves information about that
instance (like the instance ID and public IP) in the state file.
1. State Initialization: When you first run terraform init, Terraform creates an empty state file
or fetches an existing one if it’s stored remotely.
2. State Refresh: Terraform refreshes the state by querying the provider's API to make sure the
state file matches the actual state of resources.
3. Plan: When you run terraform plan, Terraform compares the state file to the configuration
files to generate a plan of what needs to be changed.
4. Apply: After reviewing the plan, terraform apply updates the infrastructure and the state file
accordingly.
DevOps Shack
5. Destroy: When running terraform destroy, Terraform reads the state file to identify and
delete the existing resources.
By default, Terraform stores the state file locally in the directory where you run Terraform
(terraform.tfstate). However, for collaborative environments or projects, it's better to store the state
file in a remote backend (like Amazon S3 or Azure Blob Storage) to avoid conflicts when multiple team
members work on the same infrastructure.
The state file contains information about all the resources Terraform manages. This includes:
• Resource IDs: Unique identifiers for the resources created, such as EC2 instance IDs or S3
bucket names.
• Resource Attributes: Additional information like IP addresses, security group rules, or subnet
IDs.
• Outputs: Any values specified in output blocks, such as public IP addresses or database
endpoints.
Sensitive information, such as passwords or access keys, may also be stored in the state file. This is
why it’s important to protect the state file and ensure it’s not accessible to unauthorized users.
• Tracking Resource Changes: The state file acts as the "source of truth" for Terraform. It
allows Terraform to know what changes need to be made when you run terraform apply.
• Performance: Without a state file, Terraform would need to query the cloud provider’s API
for every resource on each execution, slowing down operations.
• Incremental Changes: The state file allows Terraform to make incremental changes to
resources, updating only the components that need modification, rather than re-deploying
everything.
In collaborative environments, storing the state file locally can lead to conflicts if multiple people are
working on the same infrastructure. To solve this, Terraform supports remote state, which allows the
state file to be stored in a shared location where it can be accessed by multiple users.
Remote state storage also provides features like state locking, preventing multiple users from
applying changes at the same time and corrupting the state file.
DevOps Shack
Remote state refers to storing the Terraform state file in a remote location, such as an S3 bucket,
Azure Blob Storage, Google Cloud Storage, or HashiCorp's Terraform Cloud. By doing so, multiple
team members can access the same state file, ensuring consistency and collaboration.
• State Locking: Ensures that only one user can modify the state at a time.
• State Encryption: Protects sensitive data within the state file by encrypting it.
• Versioning: Remote storage like S3 can version state files, allowing you to recover previous
versions in case of accidental changes or corruption.
To store your state file in an Amazon S3 bucket, you can configure Terraform to use an S3 backend.
• bucket: Specifies the S3 bucket where the state file will be stored.
• key: Defines the path to the state file within the S3 bucket.
To avoid multiple users attempting to modify the state file simultaneously, you can enable state
locking using DynamoDB. This ensures that only one user can run terraform apply at a time,
preventing state corruption.
"my-terraform-state" key =
"global/s3/terraform.tfstate" region
In this example, the dynamodb_table argument specifies the table that Terraform will use to lock the
state file while changes are being applied.
Another option for remote state storage is Terraform Cloud, which provides native support for
storing Terraform state, locking, and collaboration features. Terraform Cloud offers:
• Integrated state locking: Prevents multiple users from making changes simultaneously.
• Collaborative workflows: Terraform Cloud integrates with version control systems (like
GitHub) and supports team-based collaboration.
workspaces {
name = "my-workspace"
}
}
}
A backend in Terraform defines where and how the state file is stored and how Terraform operations
(like apply, plan, destroy) are executed. By default, Terraform uses a local backend, but it can be
configured to use a variety of remote backends, including Amazon S3, Azure Blob Storage, Google
Cloud Storage, Terraform Cloud, and others.
• State Locking: Prevent multiple users from changing the state file at the same time.
• Run Terraform in Remote Environments: Some backends, like Terraform Cloud, allow
Terraform to execute plans and apply changes remotely, rather than on your local machine.
a. Types of Backends
DevOps Shack
Here are a few common backends used in Terraform:
1. Amazon S3:
o Widely used for storing state files remotely in AWS. o Supports state locking with
DynamoDB.
4. Terraform Cloud:
o Native backend provided by HashiCorp for state storage and remote operations.
b. Configuring a Backend
Here’s how you can configure Terraform to use Azure Blob Storage as a backend:
terraform { backend
"azurerm" {
storage_account_name = "myterraformstorage"
container_name = "tfstate"
key = "terraform.tfstate"
}
}
In this example:
• storage_account_name: The name of the Azure storage account where the state file is
stored.
• container_name: The container within the storage account where the state file is stored.
• Collaboration: Teams can share the same state file, ensuring that everyone is working from
the same source of truth.
DevOps Shack
• Security: Remote backends like S3 or Terraform Cloud can encrypt the state file to protect
sensitive information.
• State Locking: Prevents multiple users from running terraform apply simultaneously, which
could result in conflicts or state corruption.
• Disaster Recovery: Remote backends store state files in highly available and durable storage,
ensuring that state files are not lost in case of local machine failure.
17. Conclusion
In this module, we covered the critical concept of state management in Terraform, including how
Terraform tracks the state of resources using the state file, and how remote state and backends
enable collaboration, security, and locking in multi-user environments.
State management is essential for ensuring that Terraform can accurately manage your
infrastructure, especially as your projects grow in size and complexity. By storing the state file
remotely, using state locking, and encrypting the state file, you can create a more secure, reliable,
and scalable infrastructure management process.
DevOps Shack
A module in Terraform is a container for multiple resources that are used together. A module
encapsulates one or more resources into a single unit that can be reused across projects and
environments. Think of a module as a way to package infrastructure code so that it can be easily
maintained, shared, and reused.
• Abstraction: Modules can abstract away complex infrastructure details, making it easier for
users to consume them.
• Maintainability: By organizing infrastructure into modules, you can manage large, complex
projects more effectively.
In Terraform, every configuration is part of a module. The configuration in your working directory is
called the root module, and you can call other modules from within the root module.
b. Defining a Module
3. outputs.tf: Defines the outputs the module provides to the calling configuration.
/modules
/ec2
main.tf
variables.tf
outputs.tf
DevOps Shack
variable "ami" {
description = "The AMI to use for the EC2 instance"
}
variable "instance_type" {
description = "The instance type to use"
default = "t2.micro"
}
variable "instance_name" {
description = "The name to assign to the EC2 instance"
default = "example-instance"
}
Here, three variables are defined: ami, instance_type, and instance_name. These are passed to the
module by the calling configuration. Step 4: Define the outputs.tf File (Outputs) output
"instance_id" { value = aws_instance.my_instance.id
aws_instance.my_instance.public_ip
The outputs.tf file defines outputs that expose the instance ID and public IP of the EC2 instance
created by the module.
c. Using a Module
DevOps Shack
Once the module is defined, you can call it from your root module (i.e., the main configuration file in
your working directory). Here’s how you would call the EC2 module created above.
• source: Specifies the location of the module. In this case, it is a local path (./modules/ec2).
• ami, instance_type, and instance_name: These are the input variables required by the
module.
When you run terraform apply, Terraform will use the module to provision an EC2 instance with the
specified AMI, instance type, and name.
In addition to local modules, Terraform allows you to use remote modules hosted in version control
systems like GitHub, or in the Terraform Registry. This makes it easy to share and reuse modules
across different teams and projects. Example: Using a module from GitHub.
modules/terraform-aws-vpc"
"us-west-1b"]
In this example:
• The module accepts inputs like cidr and azs to define the VPC configuration.
1. Use Modules for Reusable Infrastructure: Break down your infrastructure into reusable
modules. For example, create separate modules for VPC, EC2 instances, databases, and so
on.
2. Version Your Modules: If you're using modules from version control or the Terraform
Registry, always specify the module version to avoid breaking changes.
DevOps Shack
3. Modularize Your Projects: Organize your project into separate modules for easier
maintenance. For example, you can have a module for networking, another for compute
resources, and a third for monitoring.
4. Document Your Modules: Provide clear documentation for the inputs, outputs, and purpose
of each module. This helps other team members understand how to use the modules
correctly.
Terraform workspaces allow you to manage multiple environments (e.g., development, staging,
production) from the same configuration. Each workspace has its own separate state file, which
means that changes in one workspace won’t affect the resources in another workspace.
By default, Terraform operates in a single workspace called default. However, you can create
additional workspaces to manage different environments using the same configuration files.
• You want to maintain separate infrastructure environments (e.g., dev, staging, prod) without
duplicating configuration code.
• You need to create isolated copies of the infrastructure for testing or QA purposes.
Each workspace has its own state, so the resources created in one workspace are independent of
those in another.
You can create a new workspace using the terraform workspace new command, and switch between
workspaces using the terraform workspace select command. Step 1: Create a New Workspace
terraform workspace new dev
This creates a new workspace called dev. Terraform will automatically create a new state file for this
workspace.
This command switches Terraform to the dev workspace. Any resources created or modified while in
this workspace will be isolated from other workspaces.
workspace list
DevOps Shack
This command lists all workspaces in the current project. You’ll see an output like:
* default
dev prod
You can reference the active workspace in your configuration using the terraform.workspace variable.
This is useful for customizing resource names or tags based on the workspace.
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "my-instance-${terraform.workspace}"
In this example, the EC2 instance name will be suffixed with the workspace name (e.g., my-
instancedev or my-instance-prod).
Workspaces are ideal for managing multiple environments like development, staging, and
production, without duplicating code. Each environment can have its own workspace, and resources
in each environment will be completely isolated.
Example workflow:
By using workspaces, you can avoid duplicating configurations for each environment while keeping
the infrastructure state isolated.
e. Limitations of Workspaces
While workspaces are useful for managing environments, they have some limitations:
• Limited to State Management: Workspaces only isolate the state, not the configuration
itself. If you need to manage different configurations (e.g., different AMI IDs for dev and
prod), you’ll need to handle that logic using variables.
• Not Suitable for Every Use Case: For large-scale projects with many environment-specific
differences, using separate workspaces might become complex. In such cases, it may be
better to create separate Terraform projects for each environment.
20. Conclusion
In this module, we covered Terraform Modules and Terraform Workspaces, both of which are crucial
for organizing and managing infrastructure in a scalable and maintainable way.
• Modules enable you to create reusable, modular components that simplify infrastructure
management and promote consistency across projects.
• Workspaces allow you to manage multiple environments using the same configuration,
isolating state files for each environment.
By using modules and workspaces effectively, you can reduce duplication, improve maintainability,
and ensure consistent deployments across different environments.
Suppose you want to provision different EC2 instance types based on the environment (e.g., use
t2.micro in development and t3.large in production). You can use a conditional expression to achieve
this.
Example:
variable "environment" {
default = "dev"
In this example:
You can also use conditional expressions to decide whether or not to create a resource. This is useful
for controlling optional resources, such as adding a load balancer only in production environments.
Example:
name = "my-load-balancer"
availability_zones = ["us-west-1a", "us-west-1b"]
}
In this example:
DevOps Shack
• The count argument determines whether the resource is created. If var.create_elb is true,
Terraform will create one load balancer; if false, Terraform will create none.
Terraform provides for loops to iterate over lists or maps and create multiple resources or dynamic
configurations. Loops are incredibly useful when you need to provision multiple instances of the
same resource or dynamically configure settings based on a list of values.
2. Map iteration: Used for iterating over a map's keys and values.
If you want to create multiple EC2 instances based on a list of instance types, you can use a for loop
to iterate over the list and create resources dynamically.
Example:
variable "instance_types" {
default = ["t2.micro", "t2.small", "t2.medium"]
}
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_types[count.index]
}
In this example:
• The count parameter creates an EC2 instance for each element in the instance_types list.
You can also use for loops to dynamically generate resource attributes, such as tags.
Example:
DevOps Shack
variable "tags" {
type = map(string)
default = {
Name = "example-instance"
Owner = "admin"
Env = "dev"
}
}
• The for loop iterates over the tags map and dynamically applies the tags to the EC2 instance.
• Each key-value pair in the tags map becomes a tag for the instance.
You can use a for loop to create resources in multiple availability zones.
Example:
• The for loop iterates through the list of availability zones and creates a subnet in each one.
Dynamic blocks in Terraform allow you to generate multiple nested blocks within a resource,
dynamically controlling how many blocks are created and their configuration. This is particularly
useful when dealing with resources that require nested blocks, such as security groups, load
balancers, and network ACLs.
DevOps Shack
A dynamic block allows you to conditionally add multiple nested blocks within a resource based on a
variable or a loop. It consists of three parts:
• content: Defines the content that will be generated for each item in the loop.
Suppose you need to create multiple security group rules for different ports. You can use a dynamic
block to iterate through a list of ports and create a rule for each one.
Example:
variable "allowed_ports" {
default = [22, 80, 443]
}
dynamic "ingress" {
for_each = var.allowed_ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp" cidr_blocks
= ["0.0.0.0/0"]
}
}
}
In this example:
• The dynamic block iterates over the allowed_ports variable and creates a separate ingress
block for each port.
You can also use dynamic blocks to create multiple autoscaling policies for an application.
Example:
variable "scaling_policies" {
DevOps Shack
default = { scale_up = { adjustment = 2,
cooldown = 300 } scale_down = { adjustment = -1,
cooldown = 300 }
}
}
name = "${each.key}-policy"
scaling_adjustment = each.value.adjustment cooldown
= each.value.cooldown adjustment_type =
"ChangeInCapacity"
autoscaling_group_name = aws_autoscaling_group.my_asg.name
}
In this example:
• A dynamic block creates multiple autoscaling policies (scale-up and scale-down) for an
autoscaling group based on the scaling_policies variable.
• You need to create multiple nested blocks of the same type (e.g., security group rules,
autoscaling policies).
Dynamic blocks help reduce redundancy in your configuration and make it more scalable by
eliminating the need to manually define multiple similar blocks.
24. Conclusion
In this module, we covered some of Terraform's most powerful features: Conditional Expressions,
For Loops, and Dynamic Blocks. These features allow you to create dynamic, flexible, and scalable
configurations that adapt to different environments and requirements. By using these tools, you can
write more efficient infrastructure code that reduces redundancy and improves maintainability.
1. Unit Testing: Testing individual components (e.g., modules) to verify their functionality.
2. Integration Testing: Verifying that different parts of the infrastructure interact correctly.
3. Acceptance Testing: Ensuring that the entire infrastructure is provisioned correctly and
functions as expected in real-world scenarios.
Terraform has built-in commands to validate and lint your configurations. The terraform validate
command checks whether the configuration files are syntactically valid and internally consistent. a.
Running terraform validate
terraform validate
• This command ensures that the syntax of the Terraform configuration files (.tf) is correct.
• It does not create or destroy any resources but ensures the Terraform code is ready to be
applied.
If there are issues, Terraform will provide an error message indicating what went wrong.
The terraform plan command is another key component in testing your configuration. It allows you
to preview the changes Terraform will make before applying them. This helps you verify whether the
desired changes are correct and expected.
terraform plan
• terraform plan generates an execution plan that shows what Terraform will do to achieve the
desired state of the infrastructure.
• This is useful for testing the logic in your configuration to ensure it behaves as expected.
Example output:
+ aws_instance.my_instance
DevOps Shack
ami: "ami-0c55b159cbfafe1f0"
instance_type: "t2.micro"
...
In this example:
• The + symbol indicates that Terraform will add a new resource (an EC2 instance).
• The plan gives you a chance to review the actions Terraform will take before applying them.
While terraform plan is useful for reviewing the changes, it's important to test the actual application
of changes in a non-production environment (such as a sandbox, dev, or staging environment). a.
Running terraform apply
Once you're satisfied with the plan, you can apply the changes:
terraform apply
This will actually provision the resources in the target environment. Running this in a sandbox
environment allows you to test whether the resources are correctly created and configured. If
everything works as expected, you can apply the same changes to the production environment.
Example output:
aws_instance.my_instance: Creating...
Terratest is a popular Go-based framework for writing automated tests for Terraform code. It allows
you to write tests that automate the execution of Terraform configurations, deploy infrastructure,
and verify that it works as expected. It’s especially useful for integration and acceptance testing. a.
What is Terratest?
• Provision infrastructure using Terraform and validate its correctness by running real-world
checks (e.g., pinging an EC2 instance, checking that a load balancer is correctly set up).
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/aws"
"github.com/gruntwork-io/terratest/modules/terraform"
)
• The test provisions an EC2 instance using Terraform and then verifies that the instance is
running.
• After the test is completed, Terratest automatically destroys the infrastructure using
terraform destroy.
github.com/gruntwork-io/terratest/modules/terraform
Terratest will provision the infrastructure, run the tests, and clean up afterward.
Sometimes, things go wrong when running Terraform. Whether it’s a failed terraform apply, incorrect
resource creation, or unexpected changes, debugging your Terraform configuration is crucial to
identify and resolve issues.
Terraform allows you to enable detailed logging to help with debugging. You can set the TF_LOG
environment variable to DEBUG to enable debug logs.
Example:
export TF_LOG=DEBUG
terraform apply
With TF_LOG set to DEBUG, Terraform will output detailed information about what it’s doing at each
step. This can help you pinpoint issues in the configuration or identify API errors when interacting
with cloud providers.
terraform show
This command shows the contents of the state file, allowing you to inspect the resources Terraform is
managing and their current state. If a resource is missing or misconfigured, it will likely show up in
the state file.
Terraform automatically manages resource dependencies, ensuring that resources are created,
modified, or destroyed in the correct order. However, if you suspect a dependency issue, you can use
terraform graph to visualize the resource graph.
Example:
This command generates a graph of dependencies between resources, which can help you identify
issues related to resource ordering or dependencies.
1. Resource Already Exists: If Terraform tries to create a resource that already exists, check
whether the resource is in the state file. If not, import it using:
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
timeouts {
create = "10m"
31. Conclusion
In this module, we explored Terraform Testing and Debugging Techniques to ensure that your
infrastructure-as-code is robust and functions as expected. Testing is crucial in any software
development workflow, and Terraform provides several tools, such as terraform validate and
terraform plan, for validating configurations. More advanced testing can be automated using
Terratest, which integrates real-world testing into your Terraform workflows. Additionally, Terraform’s
debugging tools, such as debug logs and state management, help identify and fix issues when things
go wrong.
• Single Responsibility Principle: Each module should be responsible for one component (e.g.,
VPC, EC2, RDS). This keeps your modules focused and reusable.
• Use Inputs and Outputs: Define variables for user inputs and outputs for passing information
between modules.
• Store Modules in Version Control: Store modules in a Git repository or the Terraform
Registry to ensure version control and easy sharing between teams.
Example structure:
/modules
/vpc
main.tf
variables.tf
outputs.tf
/ec2
main.tf
variables.tf
outputs.tf
This structure makes it easy to reuse modules across projects, reducing duplication and ensuring
consistency.
As discussed in Module 5, storing the state file remotely is a best practice, especially for teams
working in a collaborative environment. Use a backend like Amazon S3, Azure Blob Storage, or
Terraform Cloud to ensure the state is consistent across team members and protected with features
like encryption and locking.
Always store your Terraform configurations and modules in a version control system (such as Git).
This allows you to track changes, collaborate with other developers, and roll back to previous
versions if something goes wrong.
DevOps Shack
Key practices for version control:
• Commit Often: Make small, incremental commits with meaningful commit messages.
• Use Branches: Separate your development, staging, and production environments using Git
branches.
• Tag Versions: Tag releases of your infrastructure code to provide easy rollback options.
Example:
git add .
push --tags
By tagging your Terraform configurations, you can track infrastructure versions, making it easier to
identify what version is running in production.
d. Use .terraformignore
Similar to .gitignore, the .terraformignore file allows you to exclude specific files or directories from
being uploaded when using remote backends like Terraform Cloud.
*.tfstate
*.log
.secret/*
This prevents sensitive or unnecessary files from being uploaded to the backend.
Terraform provides several advanced techniques to help manage complex infrastructure, secrets, and
workflows. Let’s explore some of these advanced features.
Managing secrets like API keys, passwords, and SSH keys can be challenging in Terraform. It’s
important to avoid hardcoding sensitive information in your configuration files. There are several
ways to manage secrets securely in Terraform:
1. Environment Variables: Store sensitive information in environment variables and pass them
to Terraform at runtime.
Example: export
TF_VAR_db_password="mysecretpassword"
DevOps Shack
terraform apply
3. Secrets Management Tools: Integrate with secrets management tools like HashiCorp Vault,
AWS Secrets Manager, or Azure Key Vault to dynamically inject secrets into your Terraform
configurations.
"my-db-password"
password = data.aws_secretsmanager_secret.db_password.value
In this example, the database password is securely retrieved from AWS Secrets Manager, rather than
being hardcoded in the Terraform configuration.
With Terraform Cloud, you can execute Terraform commands remotely, rather than running them on
your local machine. This is especially useful for larger teams and organizations that want to centralize
infrastructure management.
• Remote State Management: Automatically stores and locks the state file.
• Remote Plan and Apply: Executes terraform plan and apply in a remote environment,
ensuring consistency across team members.
• Collaboration Tools: Allows multiple team members to work on the same infrastructure.
organization = "my-org"
workspaces { name =
"my-workspace"
}
DevOps Shack
}
By using Terraform Cloud, you can also integrate CI/CD pipelines, automate the application of
Terraform plans, and manage approvals.
If you have existing resources that were created manually (e.g., through a cloud provider’s console),
you can bring those resources under Terraform management using the terraform import command.
This is useful when you want Terraform to manage resources that were not initially provisioned by
Terraform.
• In this example, the EC2 instance with the ID i-0abcd1234 is imported into Terraform’s state.
• After importing, you need to define the resource in your configuration (e.g., main.tf) so that
Terraform can manage it going forward.
Terraform workspaces are useful for managing multiple environments (e.g., dev, staging, production)
from a single configuration, as discussed in Module 6.
= "t2.micro"
tags = {
Name = "my-instance-${terraform.workspace}"
By using workspaces, you can manage different environments without duplicating configuration files.
DevOps Shack
e. Using depends_on to Manage Complex Dependencies
ami = "ami-0c55b159cbfafe1f0"
[aws_s3_bucket.my_bucket]
bucket = "my-bucket"
In this example, Terraform will ensure that the S3 bucket is created before the EC2 instance, even if
there is no direct connection between the two resources.
34. Conclusion
In this module, we covered Terraform Best Practices and Advanced Techniques to help you manage
infrastructure-as-code efficiently, securely, and at scale. By adopting best practices like modularizing
your code, using remote backends for state management, and storing sensitive information securely,
you can improve the maintainability and security of your Terraform projects. Additionally, advanced
techniques like using workspaces, remote execution, and importing existing resources help
streamline complex workflows and infrastructure management.
• Collaboration: Team members can collaborate effectively using version control systems (like
Git), ensuring that all changes are tracked and reviewed.
• Testing and Validation: CI/CD pipelines can validate the Terraform configuration (e.g., using
terraform plan and terraform validate) before applying changes, reducing the risk of
misconfigurations.
DevOps Shack
• Rollback: CI/CD integration can help roll back infrastructure changes if something goes
wrong during deployment.
GitHub Actions is a powerful CI/CD tool that can automate workflows directly in your GitHub
repository. You can use GitHub Actions to trigger Terraform runs whenever a change is made to the
infrastructure code (for example, after a pull request is merged).
1. Create a GitHub Actions Workflow: GitHub Actions workflows are stored in the
.github/workflows/ directory of your repository. Example workflow file:
.github/workflows/terraform.yml
name: Terraform
on: push:
branches: -
main
pull_request:
branches:
- main
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
• It checks out the repository, sets up Terraform, and runs terraform init and terraform plan.
• On a push to the main branch, terraform apply is automatically executed to apply the
changes.
2. Storing Secrets in GitHub: Sensitive information like access keys or API tokens should be
stored securely using GitHub Secrets. In your repository, go to Settings → Secrets and
variables → Actions and add your secrets.
In a typical GitHub Actions workflow, terraform plan can run for every pull request to validate the
changes without actually applying them. terraform apply can run only when the changes are merged
into the main branch.
Jenkins is another popular CI/CD tool that can be used to automate Terraform workflows. You can
use Jenkins pipelines to validate, plan, and apply Terraform configurations.
1. Install the Terraform Plugin: Jenkins has a Terraform plugin that makes it easy to integrate
Terraform with Jenkins pipelines.
2. Creating a Jenkins Pipeline: In Jenkins, create a new pipeline job and define your pipeline in
the Jenkinsfile.
stages {
DevOps Shack
stage('Checkout') {
steps {
checkout scm
}
}
stage('Terraform Init') {
steps {
sh 'terraform init'
}
}
stage('Terraform Plan') {
steps {
sh 'terraform plan'
}
}
stage('Terraform Apply') {
when {
branch 'main'
}
steps {
sh 'terraform apply -auto-approve'
}
}
}
}
In this example:
• It initializes Terraform using terraform init and validates the configuration with terraform
plan.
3. Storing Credentials in Jenkins: Use Jenkins Credentials to securely store access keys and
tokens for your cloud provider. Go to Manage Jenkins → Manage Credentials and add your
credentials there. You can reference these credentials in the pipeline using environment
variables.
GitLab CI is the built-in CI/CD tool in GitLab, which can also be used to automate Terraform
workflows.
1. Create a .gitlab-ci.yml File: GitLab CI configurations are defined in the .gitlab-ci.yml file located
in the root of your repository.
stages: -
validate
- plan
- apply
before_script:
- terraform init
validate:
stage: validate
script:
- terraform validate
plan:
stage: plan
script:
- terraform plan
only:
- merge_requests
apply:
stage: apply
script:
- terraform apply -auto-approve
only:
- master
In this example:
• terraform plan runs only for merge requests to preview the changes.
• terraform apply runs only on the master branch, ensuring that changes are applied only after
being merged.
2. Managing Secrets in GitLab CI: You can store sensitive credentials using GitLab CI variables.
Go to your project’s Settings → CI/CD → Variables and add your cloud provider credentials
as variables.
When deploying infrastructure via CI/CD, use separate pipelines or workspaces for different
environments (e.g., dev, staging, production). This ensures that changes can be tested in a staging
environment before being deployed to production.
DevOps Shack
Example: Using workspaces in Terraform: - name: Terraform Apply (Staging)
For production environments, consider adding an approval gate before running terraform apply. This
ensures that infrastructure changes are reviewed by a team member before being applied.
steps:
- name: Terraform Apply
run: terraform apply -auto-approve
if: github.event_name == 'workflow_dispatch'
This configuration requires a manual trigger to apply changes, ensuring that production changes are
not applied automatically.
Before applying infrastructure changes, run automated tests to validate the configuration. Use tools
like Terratest (as discussed in Module 8) or InSpec to ensure the infrastructure behaves as expected.
40. Conclusion
In this module, we covered how to integrate Terraform with CI/CD pipelines using GitHub Actions,
Jenkins, and GitLab CI. These tools enable you to automate infrastructure provisioning, ensure
consistency, and reduce manual intervention. By incorporating CI/CD into your Terraform workflows,
you can implement best practices such as automated testing, environment isolation, and approval
gates, making your infrastructure-as-code processes more reliable and efficient.
In the next module, we will cover Terraform Cost Estimation and Optimization Techniques, which
will help you ensure that your infrastructure is both cost-efficient and scalable.
DevOps Shack
• Avoiding Vendor Lock-In: By relying on multiple providers, you are not locked into a single
cloud vendor, reducing risks such as price hikes or outages.
• Leveraging Best Features: Different cloud providers excel in specific areas (e.g., AWS for
compute, Azure for enterprise services, Google Cloud for machine learning). Multi-cloud
allows you to pick the best services from each provider.
However, managing multiple cloud environments can add complexity, which is why Terraform's
provider model simplifies the process by allowing consistent infrastructure management across
clouds.
Terraform’s ability to work with multiple cloud providers simultaneously is powered by providers.
Each cloud provider (such as AWS, Azure, or Google Cloud) has its own Terraform provider plugin that
allows Terraform to interact with its APIs.
In a multi-cloud setup, you define multiple provider blocks in your Terraform configuration, each
corresponding to a specific cloud provider. You can then use resources from each provider in the
same configuration.
b. Provider Aliases
Terraform allows you to create provider aliases if you need to work with multiple regions, accounts,
or subscriptions within the same provider. This is particularly useful when deploying resources to
different environments (e.g., different AWS regions or Azure subscriptions).
Let’s explore a basic example where we deploy an EC2 instance on AWS and a virtual machine (VM)
on Azure, all from a single Terraform configuration.
a. Configuration Structure
/multi-cloud
main.tf
variables.tf
outputs.tf
DevOps Shack
b. Provider Configuration
In the main.tf file, you define the providers for both AWS and Azure. You can also specify multiple
accounts or regions using provider aliases.
• The azurerm provider deploys resources using credentials for an Azure subscription.
Once the providers are defined, you can declare resources from both providers. For example, let’s
create an EC2 instance in AWS and an Azure Virtual Machine. Step 2: Create an AWS EC2
Instance resource "aws_instance" "my_aws_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "AWS-Instance"
ip_configuration {
name = "myNICConfig"
subnet_id = azurerm_virtual_network.my_vnet.subnets[0].id
private_ip_address_allocation = "Dynamic"
}
}
• A Windows Virtual Machine is created on Azure, including resources like a resource group,
virtual network, and network interface.
Once the resources are created, you can use the outputs block to display relevant information, such
as the public IP addresses of both instances.
DevOps Shack
output "aws_instance_public_ip" { value =
aws_instance.my_aws_instance.public_ip
azurerm_windows_virtual_machine.my_vm.public_ip_address
To deploy these resources to both AWS and Azure, run the following commands:
This command will simultaneously deploy the EC2 instance on AWS and the virtual machine on
Azure.
Managing credentials for multiple cloud providers is critical for a secure multi-cloud deployment. You
should avoid hardcoding sensitive credentials in your Terraform configuration. Instead, use
environment variables or secure credential storage services such as AWS Secrets Manager, Azure
Key Vault, or Google Secret Manager.
You can pass cloud provider credentials securely through environment variables.
AWS_ACCESS_KEY_ID="your-aws-access-key" export
AWS_SECRET_ACCESS_KEY="your-aws-secret-key" export
ARM_CLIENT_ID="your-azure-client-id" export
ARM_CLIENT_SECRET="your-azure-client-secret" export
ARM_TENANT_ID="your-azure-tenant-id"
Terraform will automatically pick up these credentials when the provider blocks are executed.
secret_id = "db_password"
allocated_storage = 20
data.aws_secretsmanager_secret_version.db_password.secret_string
When managing multi-cloud environments, aim to maintain consistency in the way resources are
named, tagged, and configured. This helps with resource management, cost tracking, and
automation.
tags = {
Environment = "production"
Project = "multi-cloud-demo"
tags = {
Environment = "production"
Project = "multi-cloud-demo"
}
DevOps Shack
}
Ensure that you have a unified monitoring and observability solution across cloud providers. Many
third-party tools, like Prometheus, Grafana, and Datadog, support multi-cloud monitoring. c.
Centralized Logging
Use tools like ELK Stack (Elasticsearch, Logstash, Kibana), Azure Monitor, or AWS CloudWatch to
collect and analyze logs from different cloud providers in a single location. This simplifies
troubleshooting in multi-cloud environments.
50. Conclusion
In this module, we explored how to manage Multi-Cloud Deployments with Terraform. By leveraging
Terraform's provider architecture, you can manage infrastructure across multiple cloud providers like
AWS, Azure, and Google Cloud from a single configuration. We discussed key concepts such as
multiple providers, managing credentials securely, and deploying resources across clouds with
consistency. Multi-cloud deployments offer flexibility, resilience, and reduced vendor lock-in, but
they also require careful management and planning
• High Availability (HA): Ensures services are always available by distributing them across
multiple regions or zones.
• Data Backup and Restore: Regular backups of databases, file systems, and application data
allow recovery in case of corruption or data loss.
• Failover and Failback: The ability to switch from a failed primary system to a secondary
system (failover) and back (failback) once the issue is resolved.
Terraform can automate many of these tasks, ensuring that infrastructure and services are easily
replicated or restored in case of failure.
One of the most common approaches to disaster recovery is to deploy resources across multiple
regions or availability zones. In case of a failure in one region, traffic is redirected to another region
where the same infrastructure is running.
Regular data backups are essential for disaster recovery. Terraform can manage cloud-native backup
services such as Amazon S3, Azure Backup, and Google Cloud Storage to automatically back up your
data to secure storage locations.
DevOps Shack
c. Automated Failover
Automated failover ensures that if a primary system fails, traffic is automatically redirected to a
backup system. This can be achieved using tools like AWS Route 53, Azure Traffic Manager, or
Google Cloud Load Balancing to direct traffic based on availability.
In a multi-region setup, you deploy the same infrastructure in multiple regions to ensure that
services remain available even if one region experiences an outage.
Let’s consider an example where we deploy an application in two AWS regions. We will use Route 53
for DNS failover, ensuring that traffic is directed to the available region in case one goes down.
provider "aws" {
region = "us-east-1"
alias = "us_east"
}
provider "aws" {
region = "us-west-1"
alias = "us_west"
}
In this example, we define two AWS providers with aliases (us_east and us_west) to handle resources
in different regions.
"aws_instance" "web_us_east" {
0c55b159cbfafe1f0" instance_type =
"t2.micro"
tags = {
Name = "WebServer-East"
}
DevOps Shack
# EC2 Instance in US-West resource
"aws_instance" "web_us_west" {
0c55b159cbfafe1f0" instance_type =
"t2.micro"
tags = {
Name = "WebServer-West"
In this example:
alias {
name = aws_instance.web_us_east.public_ip
zone_id = aws_instance.web_us_east.id
evaluate_target_health = true
}
failover_routing_policy {
type = "PRIMARY"
}
}
alias {
name = aws_instance.web_us_west.public_ip
zone_id = aws_instance.web_us_west.id
evaluate_target_health = true
}
DevOps Shack
failover_routing_policy {
type = "SECONDARY"
}
}
In this example:
• The primary instance in US-East is used by default, and if it becomes unhealthy, traffic is
automatically redirected to the secondary instance in US-West.
Backup and replication are key elements of a disaster recovery strategy. Cloud providers offer built-in
tools for backing up data, such as AWS RDS snapshots, Azure Backup, and Google Cloud Persistent
Disk Snapshots.
Let’s automate the process of backing up an AWS RDS database using Terraform. Example:
• An RDS instance is created with automatic backups enabled, retaining them for 7 days.
• A manual RDS snapshot is also created on-demand using Terraform, and the snapshot is
timestamped.
For object storage, such as Amazon S3, you can use lifecycle rules to automatically transition data to
cheaper storage classes (e.g., Glacier) or delete old data after a certain period. Example: S3 Lifecycle
Rules
resource "aws_s3_bucket" "my_bucket" {
bucket = "my-backup-bucket"
DevOps Shack
lifecycle_rule {
enabled = true
transition {
days
= 30
storage_class
= "GLACIER" #
Move data to
Glacier after 30
days
}
expiration {
days = 365 # Delete objects after 365 days
}
}
}
In this example:
• S3 lifecycle rules automatically transition data to Glacier for long-term, low-cost storage after
30 days.
• Objects are deleted after 365 days to reduce storage costs and ensure data is not kept
indefinitely.
Kubernetes clusters are often used for deploying containerized applications, and disaster recovery is
crucial to ensure cluster availability. Terraform can be used to create highly available Kubernetes
clusters across multiple regions or zones.
a. Example: Deploying Kubernetes Cluster Across Multiple AWS Availability Zones Step
1: Create EKS Cluster in Multi-AZ
resource "aws_eks_cluster" "my_cluster" {
name = "my-eks-cluster"
role_arn = aws_iam_role.eks_role.arn
vpc_config {
subnet_ids = aws_subnet.my_subnets[*].id
}
}
DevOps Shack
resource "aws_eks_node_group" "my_node_group" {
cluster_name = aws_eks_cluster.my_cluster.name
node_role = aws_iam_role.node_role.arn
subnet_ids = aws_subnet.my_subnets[*].id
scaling_config { desired_size = 3 max_size = 5
min_size = 1
}
}
In this example:
• A highly available EKS cluster is deployed across multiple AWS availability zones, ensuring that
the Kubernetes control plane and worker nodes remain available in case of failure in one zone.
Ensure that your disaster recovery plan is tested regularly by simulating outages and ensuring that
failover, backups, and restores work as expected.
Automate the backup process using cloud-native tools and Terraform. Regular, automated backups
reduce the risk of human error and ensure that the latest data is available for recovery.
Monitor the costs associated with disaster recovery, especially in multi-region deployments. Use cost
management tools like AWS Budgets or Azure Cost Management to ensure DR solutions are
optimized without overspending.
57. Conclusion
In this module, we covered how to implement Disaster Recovery Strategies using Terraform. We
explored the importance of multi-region deployments, data backup and replication, and failover
mechanisms to ensure high availability and minimize downtime during disasters. By automating DR
strategies with Terraform, you can create a robust and scalable infrastructure that can withstand
outages and recover quickly.
In the next module, we will explore Terraform in Hybrid Cloud Deployments, focusing on how to
integrate on-premises infrastructure with cloud environments.
• Optimize Costs by using cloud services for non-critical workloads and on-premises resources
for core business systems.
Managing hybrid cloud environments can be complex, but Terraform simplifies this by providing a
unified approach to infrastructure-as-code across cloud and on-premises environments.
One of the key goals of a hybrid cloud is to extend on-premises resources into the cloud. For
example, you can extend an on-premises network into AWS or Azure using VPN or Direct Connect. b.
Consistent Management
Terraform allows you to use consistent configurations across cloud providers and on-premises
infrastructure, providing a single pane of glass for managing the entire infrastructure. c.
Multi-Cloud Integration
In many hybrid cloud setups, different parts of the infrastructure may be hosted in different clouds,
such as AWS for computing power and Azure for database services. Terraform’s multi-provider
support makes it easy to manage these resources within a single configuration.
• On-Premises Data Center: Hosts legacy applications or systems with strict security or
compliance requirements.
• Cloud Provider (AWS/Azure): Hosts scalable workloads like web applications or cloud-native
services.
• Network Integration: Connects the on-premises network with the cloud provider’s network
via VPN, Direct Connect, or ExpressRoute.
Let’s walk through an example of setting up a hybrid cloud where an on-premises network is
extended to AWS using AWS Site-to-Site VPN.
For this example, we assume that an on-premises network with a private subnet exists, and we want
to extend this network to AWS by creating a VPN connection between the on-premises environment
and an AWS VPC.
region = "us-west-2" }
={
Name = "HybridCloudVPC"
vpc_id = aws_vpc.my_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-2a"
In this configuration:
• A subnet is created in the VPC for the application workloads. Step 4: Create
vpc_id = aws_vpc.my_vpc.id
A Virtual Private Gateway (VGW) is created and attached to the AWS VPC. This acts as the
connection point for the VPN.
tags = {
Name = "OnPremToAWS-VPN"
DevOps Shack
}
}
• The Customer Gateway defines the on-premises VPN gateway with its public IP address and
ASN.
• The VPN connection is established between the AWS VPC and the on-premises network.
• A VPN connection route is created to route traffic between the AWS VPC and the
onpremises CIDR block.
In this example, we extend an on-premises network to Azure using Azure ExpressRoute, which
provides a private connection between your on-premises network and Azure datacenters.
Step 1: Azure Provider Configuration provider "azurerm" {
features {}
"azurerm_virtual_network" "my_vnet" {
name = "my-vnet"
address_space = ["10.1.0.0/16"]
resource_group_name = azurerm_resource_group.my_rg.name
This creates an Azure Virtual Network (VNet) that will host workloads in Azure.
"my_circuit" {
name = "my-expressroute-circuit"
resource_group_name = azurerm_resource_group.my_rg.name
service_provider_name = "Equinix"
DevOps Shack
peering_location = "Silicon Valley"
bandwidth_in_mbps = 1000
sku { tier =
"Standard"
family = "MeteredData"
In this example:
• The circuit has a bandwidth of 1 Gbps and uses metered data. Step 4:
"azurerm_virtual_network_gateway" "vpn_gateway" {
name = "vpn-gateway"
resource_group_name = azurerm_resource_group.my_rg.name
type = "ExpressRoute"
vpn_type = "RouteBased"
sku = "Standard"
This creates a Virtual Network Gateway to handle the ExpressRoute connection on Azure.
Terraform has providers that support on-premises resources, such as VMware vSphere, OpenStack,
and Kubernetes. These providers allow you to define and manage on-premises VMs, storage, and
networking using the same approach as for cloud resources.
provider "vsphere" {
vsphere_server = "vsphere.local"
user = "myuser"
DevOps Shack
password = "mypassword"
allow_unverified_ssl = true
}
num_cpus = 2
memory = 4096
guest_id = "rhel7_64Guest"
network_interface {
network_id = data.vsphere_network.network.id
adapter_type = "vmxnet3"
}
disk {
label = "disk0"
size = 40
thin_provisioned = true
}
}
In this example:
• Terraform manages a VMware vSphere VM, including its CPU, memory, storage, and network
configuration.
• This resource can be integrated into a broader hybrid cloud strategy by linking it with cloud
providers.
Ensure that logging and monitoring for both on-premises and cloud resources are centralized. Tools
like AWS CloudWatch, Azure Monitor, and Prometheus can help collect and analyze logs from both
environments.
Apply consistent tagging and naming conventions across cloud and on-premises environments to
simplify resource tracking, cost management, and automation.
Ensure that VPN or direct connections between on-premises and cloud environments are secure,
using encryption protocols and firewalls to protect data in transit.
63. Conclusion
DevOps Shack
In this module, we explored how to manage Hybrid Cloud Deployments using Terraform. We
covered how to extend on-premises networks to the cloud using VPN and ExpressRoute, how to
manage on-premises resources using providers like VMware vSphere, and best practices for hybrid
cloud environments. By using Terraform to manage both cloud and on-premises infrastructure, you
can ensure consistency, scalability, and security across your hybrid cloud architecture.
• State Management: Terraform state contains sensitive information and should be handled
securely.
• Security: Access controls, secret management, and audit logs are critical to protecting
production infrastructure.
• Monitoring and Logging: Monitoring changes and logging activities is important to track
issues and ensure accountability.
Terraform provides tools and integrations to help overcome these challenges, enabling safe and
scalable production deployments.
Terraform’s state file tracks the current state of your infrastructure and allows Terraform to
determine what changes need to be applied. In a production environment, managing the state
securely and ensuring consistency across teams is crucial.
In production, Terraform state should be stored remotely using backends like Amazon S3, Azure Blob
Storage, or Terraform Cloud. Remote state allows for better collaboration, versioning, locking, and
security.
{
DevOps Shack
backend "s3" { bucket = "my-
terraform-state-prod" key =
"global/s3/terraform.tfstate" region
= "us-west-1" encrypt = true
dynamodb_table = "terraform-lock"
}
}
In this configuration:
• DynamoDB is used to implement state locking, preventing multiple users from making
changes to the state at the same time.
State locking prevents simultaneous operations on the state file, ensuring that only one Terraform
execution can modify the infrastructure at any given time. This is crucial in production environments
to avoid race conditions or conflicts.
Versioning allows you to roll back to previous states if needed, helping to recover from mistakes or
unexpected issues.
b. Secret Management
Secrets such as API keys, passwords, and credentials should never be hardcoded in your Terraform
configuration. Instead, you can use cloud-native secret management solutions like AWS Secrets
Manager, Azure Key Vault, or HashiCorp Vault to store and retrieve sensitive information. Example:
Retrieving Secrets from AWS Secrets Manager
Using Git for version control ensures that changes to infrastructure are tracked, reviewed, and
approved before being applied.
Example Workflow:
DevOps Shack
1. Create a Feature Branch: Create a new branch for any infrastructure changes.
2. Make Changes to Terraform Configuration: Add new resources or modify existing ones.
3. Run terraform plan: Generate an execution plan to see what changes will be applied.
4. Submit a Pull Request: Once the changes are ready, submit a pull request for review.
5. Merge and Apply: After approval, merge the pull request into the main branch and apply the
changes using Terraform.
Automating Terraform workflows through CI/CD pipelines ensures that infrastructure is deployed
consistently and with minimal human intervention. You can integrate Terraform into CI/CD pipelines
using tools like Jenkins, GitHub Actions, or GitLab CI.
Here’s an example of a GitHub Actions workflow that automates the Terraform plan and apply
process.
name: Terraform
on:
pull_request:
branches: -
main push:
branches:
- main
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
• terraform apply is triggered when changes are pushed to the main branch.
Monitoring and logging are critical for tracking the status of your infrastructure and identifying
potential issues in production. Many cloud providers offer native monitoring tools that can be
integrated with Terraform.
You can configure AWS CloudWatch to monitor key metrics and send alerts when infrastructure
behaves unexpectedly.
alarm_actions = [aws_sns_topic.my_topic.arn]
}
In this example, an AWS CloudWatch alarm is created to monitor EC2 CPU utilization. If CPU usage
exceeds 80%, an alert is sent to an SNS topic.
• Idempotency: Ensure that running the same Terraform code multiple times produces the
same result.
• Versioning: Use Git to track changes to your Terraform code and enable rollbacks.
DevOps Shack
• Modularity: Break your Terraform configuration into reusable modules to simplify
management and ensure consistency.
b. Automated Testing
Automate testing of your Terraform code using tools like Terratest to validate that infrastructure
behaves as expected before it is deployed to production.
71. Conclusion
In this module, we covered how to run Terraform in Production. We discussed critical aspects such as
state management, security considerations, collaboration through version control, and automation
using CI/CD pipelines. Implementing these practices helps ensure that your production infrastructure
is deployed and managed securely, consistently, and with minimal downtime.
Terraform provides mechanisms to enforce compliance rules through code, helping to automate and
audit compliance efforts across cloud environments.
a. Configuration Drift
Configuration drift occurs when the actual state of your infrastructure deviates from the desired state
defined in your Terraform code. This can happen when changes are made manually outside of
Terraform’s control, leading to compliance violations.
Ensuring that access to sensitive resources (e.g., databases, S3 buckets) is restricted and that secrets
(e.g., API keys, credentials) are securely stored and managed is a key compliance requirement. c.
Regulatory Reporting
Many regulations require organizations to generate reports demonstrating compliance with specific
policies. Keeping track of infrastructure changes and ensuring that they meet regulatory
requirements can be difficult without automation.
Policy as Code (PaC) is a methodology where compliance policies are written in code, much like
Infrastructure as Code (IaC). This approach allows you to enforce compliance rules across your
infrastructure automatically.
Terraform integrates with several Policy as Code tools to ensure that infrastructure adheres to
security, operational, and regulatory standards.
Sentinel is HashiCorp’s Policy as Code framework designed to work with Terraform. It allows you to
write policies that are evaluated before any infrastructure changes are applied. Example: Sentinel
Policy to Restrict AWS Instance Sizes
main = rule {
all tfplan.resource_changes as _, rc {
rc.change.after.instance_type is "t2.micro" or
rc.change.after.instance_type is "t2.small"
}
}
In this example:
• The Sentinel policy ensures that only t2.micro or t2.small instance types are allowed.
• If any attempt is made to deploy an instance with a larger size, the policy will block the
change.
Sentinel policies can be used to enforce a wide range of compliance requirements, from restricting
resource types to enforcing tagging standards or ensuring encryption.
Open Policy Agent (OPA) is another popular open-source policy engine that can be used to enforce
compliance rules for Terraform. OPA is more general-purpose than Sentinel and can be used with
many tools and systems.
package terraform.s3
deny[msg] {
input.resource_type == "aws_s3_bucket"
input.config.server_side_encryption_configuration == null
msg = "S3 bucket must have encryption enabled."
}
This OPA policy denies any S3 bucket that does not have server-side encryption enabled, ensuring
compliance with security best practices.
DevOps Shack
You can integrate compliance checks into your CI/CD pipelines using Terraform. By automating these
checks, you ensure that infrastructure changes are reviewed against compliance policies before they
are applied.
Here’s how you can integrate OPA into a GitHub Actions pipeline to check for compliance before
applying changes.
on:
pull_request:
branches:
- main
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
• If the policies are violated (e.g., an S3 bucket without encryption), the pipeline will fail,
preventing the change from being applied.
Managing sensitive data, such as API keys, database credentials, and access tokens, is critical for
maintaining compliance. Terraform integrates with various secret management tools to ensure that
sensitive information is securely stored and accessed.
To meet regulatory requirements, organizations often need to keep detailed logs of infrastructure
changes and access to sensitive resources. Terraform can integrate with logging and auditing tools to
provide the necessary visibility.
AWS CloudTrail can be used to log all API requests made by Terraform, including who applied the
changes and what resources were modified.
On Azure, Azure Monitor can track and log infrastructure changes, helping to ensure compliance
with security and operational policies.
resource "azurerm_monitor_diagnostic_setting" "example" {
name = "example-setting"
target_resource_id = azurerm_storage_account.example.id
log {
category = "Administrative"
enabled = true
retention_policy { enabled =
true
days = 365
DevOps Shack
}
}
}
This Azure Monitor configuration logs all administrative actions (e.g., resource creation, deletion)
and retains them for 365 days.
Ensure that compliance checks are integrated into every stage of your infrastructure lifecycle. By
running automated compliance checks in CI/CD pipelines and during infrastructure updates, you
reduce the risk of non-compliant resources being deployed.
Standardize compliance rules using Policy as Code frameworks like Sentinel or OPA. These policies
should be reviewed regularly and updated as compliance requirements evolve.
Set up regular audits of your infrastructure using logging and monitoring tools like CloudTrail, Azure
Monitor, or Google Cloud Logging. Regular audits ensure that your infrastructure adheres to
compliance standards and that any unauthorized changes are detected early.
79. Conclusion
In this module, we covered how to ensure Compliance with Terraform. By integrating compliance
checks through Policy as Code frameworks like Sentinel and OPA, managing sensitive data securely,
and setting up automated logging and auditing, you can ensure that your infrastructure adheres to
security, regulatory, and operational standards. Automating compliance checks and continuously
monitoring your infrastructure helps prevent violations, keeping your environment secure and
compliant.
• Disaster Recovery (DR): Ensures that critical infrastructure and data can be restored in the
event of a catastrophic failure (e.g., natural disasters, data center outages).
• High Availability (HA): Ensures that applications and services remain accessible, even when
parts of the system fail, by using redundancy and failover mechanisms.
Terraform allows you to define your DR and HA strategies as code, ensuring consistency and
repeatability when deploying resilient infrastructure.
One of the core strategies for DR and HA is deploying infrastructure across multiple regions. This
ensures that if one region goes down, traffic can be routed to another region where the same
infrastructure is deployed.
To ensure data integrity and service continuity, resources like databases, storage, and applications
need to be replicated across multiple regions. Failover mechanisms are put in place to automatically
switch to backup systems if the primary system fails.
Automating backups of critical infrastructure, such as databases and storage, ensures that in the
event of a disaster, data can be restored quickly and accurately. Terraform can help manage and
automate backup schedules and recovery.
To achieve high availability and disaster recovery, deploying your infrastructure across multiple
regions is a common approach. In this section, we will create a multi-region setup using AWS as an
example, deploying resources in two regions and setting up failover mechanisms.
In a multi-region setup, we’ll deploy an application across two AWS regions: US-East and US-West.
The infrastructure will include an EC2 instance in each region, a RDS database, and Route 53 for DNS
failover.
provider "aws" {
region = "us-east-1"
alias = "us_east"
}
provider "aws" {
region = "us-west-2"
alias = "us_west"
}
In this example, we define two AWS providers with aliases for the US-East and US-West regions.
• Both instances host the same application, ensuring high availability across regions.
resource
"aws_route53_record" "primary" { zone_id =
aws_route53_zone.example.zone_id name =
"www.example.com"
type = "A"
alias {
name = aws_instance.web_us_east.public_ip
zone_id = aws_instance.web_us_east.id
evaluate_target_health = true
}
failover_routing_policy {
type = "PRIMARY"
}
}
name = "www.example.com"
type = "A"
DevOps Shack
alias {
name = aws_instance.web_us_west.public_ip
zone_id = aws_instance.web_us_west.id
evaluate_target_health = true
}
failover_routing_policy {
type = "SECONDARY"
}
}
In this configuration:
• If the primary EC2 instance in US-East becomes unhealthy, traffic is automatically routed to
the secondary EC2 instance in US-West.
Automating backups of critical data ensures that you can recover from data loss or infrastructure
failures. Terraform can manage backup policies for cloud resources such as databases and storage. a.
Automating RDS Backups in AWS
Let’s automate the backup process for an RDS database in AWS, ensuring that daily backups are
taken and stored securely.
• An RDS instance is created with automated backups that are retained for 7 days.
• The backups are taken daily during the specified backup window.
b. Automating S3 Backups
In addition to databases, other critical data, such as files stored in S3, need to be backed up. You can
use S3 lifecycle policies to automate data backup and retention.
lifecycle_rule {
enabled = true
transition {
days = 30
storage_class = "GLACIER" # Move data to Glacier for long-term storage after 30 days
}
expiration {
days = 365 # Delete data after 365 days
}
}
}
In this example:
• Data in the S3 bucket is automatically transitioned to Glacier for long-term archival after 30
days.
Automated failover ensures that when the primary infrastructure fails, traffic is seamlessly routed to
the backup infrastructure. Services like AWS RDS, Azure SQL, and Google Cloud SQL support
automated failover for databases.
AWS RDS offers Multi-AZ deployments, which automatically replicate data across availability zones
and provide failover support in case of hardware or network failures. Example: Enabling Multi-AZ
for RDS
In this example:
• The Multi-AZ option is enabled, ensuring that RDS automatically replicates the database to
another availability zone.
• In the event of an outage, AWS automatically fails over to the standby instance in another
availability zone.
dimensions = {
InstanceId = aws_instance.web_us_east.id
}
}
In this configuration:
Ensure that critical applications are deployed in multiple regions or availability zones to improve
resilience and reduce the risk of downtime.
Automate failover mechanisms and regularly test them to ensure that they work as expected.
Similarly, automate data backups and retention to ensure recoverability in case of disasters.
Set up regular disaster recovery drills to test your recovery processes. Ensure that your monitoring
and alerting systems provide timely notifications in case of failures.
87. Conclusion
In this module, we explored Disaster Recovery (DR) and High Availability (HA) strategies using
Terraform. We covered how to deploy multi-region infrastructure, automate backups, and
implement failover mechanisms to ensure that your applications and data remain available and
recoverable in case of failure. By automating these processes with Terraform, you can improve
resilience and minimize downtime, ensuring business continuity.
DevOps Shack
• Resource Optimization: Ensures that resources are right-sized and utilized efficiently.
• Scaling and Flexibility: Allows infrastructure to scale without incurring unnecessary costs.
• Cloud Financial Operations (FinOps): Aligns infrastructure operations with financial goals,
optimizing for both performance and costs.
By integrating cost management strategies into your Terraform workflows, you can ensure that
resources are used efficiently and cloud costs remain predictable.
Right-sizing refers to ensuring that resources are appropriately sized for their workloads.
Overprovisioning resources such as compute, memory, and storage can result in unnecessary
costs. Terraform can help automate the process of adjusting resource sizes based on usage
patterns. Example: Right-Sizing AWS EC2 Instances resource "aws_instance" "example" {
tags = {
Name = "example-instance"
In this example, the instance type is adjusted from a larger instance (e.g., t3.large) to a smaller one
(t3.micro) to optimize costs.
Cloud providers like AWS, Azure, and Google Cloud offer Reserved Instances (RIs) or Savings Plans,
which provide significant cost savings in exchange for a commitment to using a certain amount of
compute resources over a specific time period.
You can manage reserved instances in AWS using Terraform to ensure long-term infrastructure cost
savings.
DevOps Shack
resource "aws_instance" "example" {
Reserved instances can provide discounts of up to 75% compared to on-demand pricing, making
them an effective strategy for cost management when workloads have predictable usage.
Idle resources can incur significant costs, especially in non-production environments like
development and testing. Terraform can automate the shutdown or scaling down of idle resources to
save costs during off-hours.
You can use AWS Lambda and CloudWatch Events to schedule the shutdown of EC2 instances during
non-business hours to save costs.
filename = "lambda_shutdown.zip"
function_name = "shutdownEC2Instances"
handler = "lambda_function.lambda_handler"
aws_iam_role.lambda_exec.arn
rule = aws_cloudwatch_event_rule.shutdown_rule.name
aws_lambda_function.shutdown_ec2.arn
In this example, a Lambda function shuts down EC2 instances every evening at 6 PM, helping reduce
costs by stopping idle resources during non-peak hours.
DevOps Shack
Monitoring cloud costs in real time is essential to prevent unexpected cost overruns. Terraform can
help automate the setup of monitoring tools like AWS Budgets, Azure Cost Management, or Google
Cloud Billing to track and control cloud spending.
AWS Budgets can be used to set cost thresholds and receive alerts when spending exceeds a
specified limit. Terraform allows you to automate the creation and management of AWS Budgets.
Example: AWS Budgets with Terraform resource "aws_budgets_budget" "monthly_budget" {
budget_type = "COST" limit_amount = "500" limit_unit = "USD"
time_unit = "MONTHLY"
cost_filters = {
Service = "AmazonEC2"
notification {
comparison_operator = "GREATER_THAN"
threshold = 80
= "ACTUAL" subscriber_email_addresses =
In this example:
• An alert is triggered when 80% of the budget is used, ensuring that cost overruns are
addressed early.
Azure provides Cost Management and Billing tools that allow you to set budgets, track spending, and
optimize costs across your resources. Terraform can be used to automate cost management in Azure.
DevOps Shack
"azurerm_cost_management_budget" "example" {
= azurerm_subscription.primary.id amount
time_period_start = "2024-01-01"
time_period_end = "2024-12-31"
threshold contact_emails =
In this example, an Azure Cost Management Budget is set up with a limit of $500 for the year 2024,
and a notification is sent when 80% of the budget is reached.
Storage costs, especially for long-term data retention, can be optimized using lifecycle policies that
automatically transition data to cheaper storage tiers, such as Amazon S3 Glacier or Azure Blob
Storage Archive Tier.
"my-data-bucket"
lifecycle_rule {
enabled = true
transition {
days = 30
}
DevOps Shack
expiration { days = 365 # Delete objects
In this example:
• Data in the S3 bucket is automatically transitioned to Glacier for low-cost archival storage
after 30 days.
• Objects are deleted after 365 days to avoid unnecessary long-term storage costs.
Autoscaling helps to manage cloud costs by automatically adjusting resource usage based on
demand. Terraform can automate the configuration of autoscaling groups to ensure that you only pay
for the resources you need.
By configuring an autoscaling group, you can dynamically add or remove instances based on resource
usage patterns, optimizing both performance and cost.
desired_capacity = 1 max_size =5
min_size =1
launch_configuration = aws_launch_configuration.example.id
= "autoscaled-instance"
propagate_at_launch = true
image_id = "ami-0c55b159cbfafe1f0"
DevOps Shack
instance_type = "t3.micro" security_groups =
[aws_security_group.instance.id]
lifecycle {
create_before_destroy = true
In this example:
• The autoscaling group automatically adjusts the number of EC2 instances based on demand,
reducing costs during periods of low usage while maintaining performance during peak
periods.
Set up regular reviews of your Terraform configurations to ensure that resources are right-sized and
that you are using cost-saving options like Reserved Instances or Savings Plans.
Automate the setup of cost alerts to notify you when spending thresholds are exceeded. This helps
catch unexpected cost increases early and allows for corrective action.
c. Implement Autoscaling
Use autoscaling groups to dynamically adjust resources based on traffic and usage patterns, ensuring
that you only pay for the resources you need at any given time.
94. Conclusion
In this module, we explored how to use Terraform for Cost Management and Optimization. We
covered key strategies such as right-sizing resources, using reserved instances, automating resource
shutdowns, setting up cost alerts, and integrating autoscaling to manage cloud costs effectively. By
leveraging Terraform to automate cost management processes, you can maintain control over your
cloud expenses while ensuring that your infrastructure scales efficiently.
• Vendor Independence: By using multiple cloud providers, organizations avoid being locked
into a single vendor's ecosystem, increasing flexibility and negotiating power.
DevOps Shack
• Resilience and Redundancy: Multi-cloud environments offer better disaster recovery options
by distributing workloads across multiple clouds, reducing the risk of complete outages.
• Cost Optimization: Different cloud providers offer varying pricing models, and multi-cloud
strategies allow organizations to use the most cost-effective services for specific workloads.
• Leveraging Best Features: Each cloud provider excels in specific areas (e.g., AWS for
compute, Azure for enterprise services, Google Cloud for machine learning), and multi-cloud
deployments allow organizations to take advantage of each provider's strengths.
a. Terraform Providers
Terraform’s provider architecture makes multi-cloud deployments possible. Each cloud provider (e.g.,
AWS, Azure, GCP) has its own Terraform provider plugin that allows Terraform to interact with its
APIs. You can define multiple providers within the same Terraform configuration to deploy resources
across different cloud platforms.
b. Provider Aliases
In a multi-cloud or even multi-region deployment, Terraform supports provider aliases, allowing you
to use different regions or cloud accounts for specific resources within the same configuration. This
provides flexibility and control when managing multiple clouds.
Let’s explore an example where we deploy an EC2 instance on AWS and a virtual machine on Azure,
demonstrating how to manage resources across multiple clouds within a single Terraform
configuration.
In this example, we will configure both AWS and Azure providers to manage resources in each cloud.
provider "aws" {
region = "us-west-2"
alias = "aws_us_west"
}
provider "azurerm" {
features {}
alias = "azure_west_us"
}
In this configuration:
• The Azure provider is defined for managing resources in Azure's West US region.
DevOps Shack
ip_configuration {
name = "myNICConfig"
subnet_id = azurerm_virtual_network.my_vnet.subnets[0].id
private_ip_address_allocation = "Dynamic"
}
}
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
}
In this example:
• We create an Azure Resource Group, Virtual Network, Network Interface, and finally a Linux
Virtual Machine.
• This demonstrates how Terraform can manage resources in Azure alongside resources in
AWS.
To see the results of our multi-cloud deployment, we can output the public IP addresses of both
instances.
output "aws_instance_public_ip" {
value = aws_instance.web_server_aws.public_ip
}
output "azure_vm_public_ip" {
value = azurerm_linux_virtual_machine.my_vm.public_ip_address
}
To deploy the infrastructure across both AWS and Azure, use the following Terraform commands:
This process will deploy resources across both AWS and Azure based on the configurations we
provided.
terraform { backend
"azurerm" {
storage_account_name = "mystorageaccount"
container_name = "tfstate"
key = "terraform.tfstate"
}
}
This stores the Terraform state file in an Azure Blob Storage container, ensuring that state is remotely
managed and accessible.
For security reasons, it’s essential to manage multi-cloud credentials securely. Rather than
hardcoding credentials in your Terraform configurations, use environment variables or secret
management tools such as AWS Secrets Manager, Azure Key Vault, or Google Cloud Secret
Manager.
AWS_SECRET_ACCESS_KEY="your-aws-secret-key" export
ARM_CLIENT_ID="your-azure-client-id" export
ARM_CLIENT_SECRET="your-azure-client-secret" export
ARM_SUBSCRIPTION_ID="your-azure-subscription-id"
Terraform will automatically pick up these environment variables when executing the provider blocks.
When deploying across multiple clouds, networking between cloud providers can become complex.
You need to ensure secure and reliable connections between resources in different clouds.
You can set up site-to-site VPN connections between AWS and Azure to enable secure
communication between the two environments.
vpc_id = aws_vpc.my_vpc.id
}
DevOps Shack
2. Create a Customer Gateway (CGW) on Azure:
name = "azure-vpn-gateway"
resource_group_name = azurerm_resource_group.my_rg.name
type = "Vpn"
vpn_type = "RouteBased"
sku = "Standard"
3. Establish the VPN Connection: Once the gateways are in place, you can create a VPN
connection between AWS and Azure, allowing resources in each cloud to communicate
securely.
Ensure that resources in all cloud providers are consistently tagged. This helps with cost
management, monitoring, and compliance. Example: Applying Consistent Tags
For large multi-cloud environments, use Terraform modules to organize and reuse code. This helps
reduce duplication and ensures consistency across cloud deployments.
101. Conclusion
In this module, we explored how to manage Multi-Cloud Deployments with Terraform. We covered
the key concepts, benefits, and challenges of using multiple cloud providers, and provided examples
DevOps Shack
for deploying resources across both AWS and Azure. By using Terraform, you can manage multi-cloud
environments consistently, securely, and efficiently, avoiding vendor lock-in and improving resilience
• Automation: Terraform can automate the creation of Kubernetes clusters across multiple
cloud providers (e.g., AWS EKS, Azure AKS, Google GKE).
• Infrastructure as Code (IaC): Terraform allows you to define Kubernetes clusters and
workloads declaratively, making it easier to track changes and ensure consistency.
• Multi-Cloud Support: Terraform can manage Kubernetes clusters across different cloud
providers, allowing for multi-cloud Kubernetes management from a single toolset.
• Scaling and Flexibility: Terraform can integrate with Kubernetes to dynamically scale clusters
and workloads based on resource requirements.
Terraform uses providers to interact with cloud platforms and services. The Kubernetes provider
enables Terraform to manage Kubernetes resources, while cloud-specific providers (like AWS, Azure,
and Google Cloud) are used to create the infrastructure for hosting Kubernetes clusters.
Terraform can automate the creation of Kubernetes clusters on various platforms. For example, you
can use the AWS EKS provider to create an EKS cluster, the Azure AKS provider to create an AKS
cluster, and the Google GKE provider to create a GKE cluster.
Once a Kubernetes cluster is created, Terraform can also manage Kubernetes resources such as
Deployments, Services, Namespaces, and Ingresses. This provides a unified workflow for managing
both the infrastructure and workloads.
Let’s walk through an example of deploying a Kubernetes (EKS) cluster on AWS using Terraform,
followed by the deployment of a simple Kubernetes workload.
First, we will create an AWS EKS cluster using Terraform. We’ll configure the EKS cluster, define the
worker nodes, and set up networking components such as VPC and subnets. Step 1: Define the
AWS Provider and EKS Configuration
DevOps Shack
provider "aws" {
region = "us-west-2"
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
cluster_name = "my-eks-cluster"
cluster_version = "1.21"
subnets = ["subnet-123456", "subnet-789012"]
vpc_id = "vpc-12345678"
node_groups = {
eks_nodes = {
desired_capacity = 2
max_capacity = 3
min_capacity = 1
instance_type = "t3.medium"
}
}
}
In this configuration:
• The EKS module is used to create an EKS cluster, specifying the VPC and subnets in which the
cluster will reside.
• We define an EKS node group that will manage the worker nodes for the cluster.
Once the Kubernetes cluster is deployed, we can manage Kubernetes resources (such as
Deployments, Services, and Ingresses) using the Kubernetes provider in Terraform. Step
2: Configure the Kubernetes Provider
provider "kubernetes" {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
exec {
api_version = "client.authentication.k8s.io/v1alpha1"
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
}
}
In this configuration:
• The Kubernetes provider is configured to connect to the newly created EKS cluster using the
cluster endpoint and certificate authority.
DevOps Shack
Step 3: Deploy a Kubernetes Workload (Nginx)
spec {
replicas = 2
selector {
match_labels = {
app = "nginx"
}
}
template {
metadata {
labels = {
app = "nginx"
}
}
spec {
container {
name = "nginx"
image = "nginx:latest"
ports {
container_port = 80
}
}
}
}
}
}
spec {
selector = {
app = "nginx"
}
port {
port = 80
target_port = 80
}
type = "LoadBalancer"
}
}
In this example:
DevOps Shack
• A Kubernetes deployment is created for the Nginx application, with two replicas.
To deploy the EKS cluster and Kubernetes workload, run the following Terraform commands:
Terraform allows you to manage a wide variety of Kubernetes resources beyond deployments and
services. You can use Terraform to create and manage Namespaces, ConfigMaps, Ingresses,
Persistent Volumes, and more.
app-namespace"
This creates a new namespace called my-app-namespace for isolating Kubernetes resources.
ConfigMaps allow you to store configuration data for your applications in key-value pairs.
DevOps Shack
resource "kubernetes_config_map" "my_config_map" {
metadata {
name = "app-config"
namespace = "default"
}
data = {
app_environment = "production"
app_version = "v1.0.0"
}
}
This ConfigMap can be referenced in a Kubernetes deployment to provide environment-specific
configuration data.
One of Kubernetes' key features is its ability to automatically scale workloads based on demand.
Terraform can be used to configure Horizontal Pod Autoscalers (HPA) for dynamic scaling of
workloads.
spec {
scale_target_ref {
kind = "Deployment"
name = kubernetes_deployment.nginx.metadata[0].name
}
min_replicas = 2
max_replicas = 10
target_cpu_utilization_percentage = 50
}
}
In this example:
• The HPA will scale the Nginx deployment between 2 and 10 replicas based on CPU
utilization.
• The target CPU utilization is set to 50%, meaning that the autoscaler will add or remove
replicas to maintain this level of resource usage.
Automate the scaling of both Kubernetes clusters and workloads using autoscaling mechanisms like
HPA for workloads and cluster autoscaler for nodes.
Ensure that Kubernetes resources such as Secrets, Ingresses, and RBAC policies are properly
managed to avoid security risks. Terraform can be used to enforce security policies through RBAC.
108. Conclusion
In this module, we explored how to use Terraform for Kubernetes Management. We covered key
concepts such as deploying Kubernetes clusters on AWS EKS, managing Kubernetes resources like
deployments and services, and configuring autoscaling with Terraform. By integrating Terraform into
your Kubernetes workflow, you can automate cluster provisioning, workload management, and
scaling, ensuring that your Kubernetes environment is efficient, secure, and scalable.
• Cost Efficiency: You only pay for the compute resources you actually use (e.g., function
execution time), rather than provisioning servers that may remain idle.
• Reduced Operational Complexity: The cloud provider handles server provisioning, scaling,
and patching, which reduces operational overhead.
• AWS Lambda
• Azure Functions
b. Event-Driven Architecture
In this section, we will deploy an AWS Lambda function using Terraform. AWS Lambda is one of the
most widely used serverless computing platforms, allowing developers to run code in response to
events without provisioning or managing servers.
Let’s walk through an example where we create a simple AWS Lambda function that processes
requests via API Gateway. Step 1: Define the AWS Provider provider "aws" { region = "us-
west-2"
This defines the AWS provider and specifies the region where the Lambda function will be deployed.
In this example:
• The Lambda function is written in Python 3.8 and packaged as a ZIP file
(lambda_function.zip).
• The handler specifies the entry point for the function (lambda_function.lambda_handler).
DevOps Shack
• The IAM role (lambda_role) provides the Lambda function with the necessary permissions to
execute.
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
]
}
EOF
}
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": "logs:CreateLogStream",
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": "logs:PutLogEvents",
"Resource": "arn:aws:logs:*:*:*"
}
]
}
EOF
}
In this example:
DevOps Shack
• An IAM role is created that allows the Lambda function to interact with Amazon CloudWatch
Logs to store logs.
To make the Lambda function accessible via HTTP, we’ll set up an API Gateway trigger.hcl resource
"aws_api_gateway_rest_api" "my_api" {
aws_api_gateway_rest_api.my_api.root_resource_id path_part =
"lambda"
= aws_api_gateway_resource.lambda_resource.id http_method
"lambda:InvokeFunction" function_name =
aws_lambda_function.my_lambda.arn principal =
"apigateway.amazonaws.com"
In this example:
• An API Gateway is set up with a GET method that triggers the Lambda function.
• A Lambda permission is created to allow API Gateway to invoke the Lambda function.
This will create the Lambda function, configure its IAM role, and expose it via API Gateway.
Next, we’ll explore how to deploy an Azure Function using Terraform. Azure Functions is Microsoft’s
serverless computing platform, allowing developers to deploy functions that can be triggered by
HTTP requests, events, and more.
provider "azurerm" {
features {}
In this example:
• We create an Azure Function App within a resource group, storage account, and app service
plan.
• The Function App uses the Linux OS and version 3.x of Azure Functions runtime.
After defining the infrastructure, you can deploy the Azure Function with:
plan
terraform apply
Use Terraform modules to organize serverless functions, making it easier to manage large numbers
of functions across multiple environments (e.g., development, staging, production).
For sensitive data like API keys or database credentials, use cloud-native secret management tools
such as AWS Secrets Manager or Azure Key Vault. This ensures that sensitive information is not
hardcoded into your Terraform code.
114. Conclusion
In this module, we covered how to use Terraform for Serverless Architectures. We explored
deploying AWS Lambda functions and Azure Functions, integrating with services like API Gateway,
and managing serverless functions using Terraform. By using Terraform to provision and manage
serverless architectures, you can automate infrastructure deployment, reduce operational
complexity, and ensure consistency across multiple environments.
DevOps Shack
• Error Detection: Logs provide critical information for troubleshooting errors and issues.
• Security Monitoring: Logging security-related events, such as access attempts and policy
changes, helps detect and prevent security breaches.
• Automated Alerts: Alerts ensure that teams are notified immediately when predefined
thresholds or anomalies are detected.
a. Infrastructure Monitoring
Terraform can configure infrastructure monitoring tools such as AWS CloudWatch, Azure Monitor,
and Google Cloud Monitoring to track the performance and health of your resources. Metrics such
as CPU usage, memory utilization, and network traffic can be automatically collected and analyzed. b.
Logging
Logs provide detailed records of events that occur within your infrastructure. Terraform can
configure logging solutions such as AWS CloudWatch Logs, Azure Log Analytics, and Google Cloud
Logging to capture, store, and analyze logs from various infrastructure components. c. Alerts
Setting up alerts based on predefined thresholds allows teams to respond to issues before they
escalate. Terraform can configure alerting mechanisms across platforms, enabling automated
notifications when critical thresholds are exceeded.
Let’s walk through how to use Terraform to configure AWS CloudWatch to monitor an EC2 instance’s
CPU usage and set up an alert if usage exceeds a certain threshold.
dimensions = {
InstanceId = aws_instance.my_instance.id
}
}
In this example:
• An alarm is triggered if the average CPU usage exceeds 80% for two consecutive evaluation
periods (5 minutes each).
To notify teams when the CPU threshold is breached, we use AWS Simple Notification Service (SNS).
resource
"aws_sns_topic_subscription" "email_subscription" {
topic_arn = aws_sns_topic.alert_topic.arn protocol = "email"
endpoint = "[email protected]" # Replace with the email address you want to receive alerts
}
In this configuration:
• When the CPUUtilization alarm is triggered, an alert is sent to the specified email address.
criteria {
metric_name = "Percentage CPU"
DevOps Shack
aggregation = "Average"
operator = "GreaterThan"
threshold = 80
dimensions = []
time_grain = "PT1M"
metric_namespace = "microsoft.compute/virtualmachines"
}
action {
action_group_id = azurerm_monitor_action_group.example.id
}
}
In this example:
• An alert is triggered if the CPU usage exceeds 80% on average for a specific time interval.
email_receiver { name
= "emailalerts"
email_address = "[email protected]"
}
}
In this example, an action group is set up to send email alerts to a specific address whenever the CPU
alert is triggered.
Terraform can also automate the setup of logging services, which capture events and performance
data across your infrastructure.
CloudWatch Logs capture system and application logs for AWS resources like EC2, Lambda, and RDS.
environment {
variables = {
LOG_GROUP_NAME = aws_cloudwatch_log_group.my_log_group.name
}
}
}
In this example:
• Logs are retained for 7 days before being deleted, helping manage storage costs.
Use Terraform to automate the setup of monitoring and logging across your infrastructure. This
ensures that all critical resources are monitored, and logs are captured consistently.
Ensure that alerts are set up for critical metrics such as CPU usage, memory utilization, and network
traffic. Use tools like AWS SNS, Azure Monitor Action Groups, or Google Cloud Alerts to notify teams
when issues arise.
Centralize logs using platforms like AWS CloudWatch Logs, Azure Log Analytics, or Google Cloud
Logging. Centralized logging makes it easier to troubleshoot issues and analyze system performance.
121. Conclusion
In this final module, we covered how to integrate Monitoring and Logging with Terraform. We
explored examples of configuring AWS CloudWatch and Azure Monitor for infrastructure metrics,
setting up alerts, and capturing logs. Monitoring and logging are essential for ensuring that your
infrastructure remains healthy, secure, and performant.
This concludes our comprehensive documentation on Terraform. Over the course of these modules,
we’ve explored how Terraform can be used to automate, manage, and optimize cloud infrastructure
across multiple platforms, from provisioning basic resources to managing serverless architectures
and Kubernetes clusters.
Key Takeaways:
• Infrastructure as Code (IaC): Terraform provides a declarative and consistent way to define,
provision, and manage infrastructure across multiple cloud providers.
DevOps Shack
• Automation: Terraform enables the automation of infrastructure provisioning, scaling, and
management, reducing operational overhead.
• Best Practices: Using Terraform modules, remote state, and version control helps ensure
infrastructure is scalable, maintainable, and secure.