Terraform: Difference between revisions

From Dave-Wiki
(Created page with "= Terraform Basics and Best Practices = ''This page covers Terraform fundamentals, best practices, essential commands, and deployment examples for AWS.'' == Introduction == Terraform is an Infrastructure as Code (IaC) tool used to provision, manage, and automate cloud infrastructure. It enables declarative configuration, making infrastructure deployments more reliable and consistent. == Best Practices == === 1. Use Remote Backend for State Management === Terraform sto...")
 
No edit summary
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Terraform Basics and Best Practices =
= Summary =
''This page covers Terraform fundamentals, best practices, essential commands, and deployment examples for AWS.''


== Introduction ==
Terraform is an open-source Infrastructure as Code (IaC) tool developed by HashiCorp. It allows you to define and provision infrastructure using a declarative configuration language called HCL (HashiCorp Configuration Language).
Terraform is an Infrastructure as Code (IaC) tool used to provision, manage, and automate cloud infrastructure. It enables declarative configuration, making infrastructure deployments more reliable and consistent.


== Best Practices ==
= Best Practices =


=== 1. Use Remote Backend for State Management ===
== Use Remote Backend for State Management ==
Terraform stores state to track infrastructure changes. A remote backend (e.g., '''S3 + DynamoDB''') ensures consistency and team collaboration.
Terraform stores state to track infrastructure changes. A remote backend (e.g., S3 + DynamoDB) ensures consistency and team collaboration.


'''Example (`backend.tf`):'''
Example (backend.tf):
<source lang="hcl">
<pre>
terraform {
terraform {
   backend "s3" {
   backend "s3" {
Line 21: Line 19:
   }
   }
}
}
</source>
</pre>


=== 2. Use Modules for Reusability ===
== Use Modules for Reusability ==
Organizing infrastructure as modules makes it easier to maintain and reuse components.
Organizing infrastructure as modules makes it easier to maintain and reuse components.


'''Example Directory Structure:'''
Example Directory Structure:
<pre>
<pre>
terraform/
terraform/
Line 40: Line 38:
</pre>
</pre>


=== 3. Use Workspaces for Multi-Environment Management ===
== Use Workspaces for Multi-Environment Management ==
Workspaces allow Terraform to manage multiple environments within the same configuration.
Workspaces allow Terraform to manage multiple environments within the same configuration.


'''Commands:'''
Commands to Create and Switch Workspaces:
<source lang="bash">
<pre>
terraform workspace new dev
terraform workspace new dev
terraform workspace select dev
terraform workspace select dev
terraform apply
terraform apply
</source>
</pre>
 
To switch to a different environment:
<pre>
terraform workspace select prod
terraform apply
</pre>
 
Using workspaces ensures that your environments (e.g., dev, prod, test) are separated, and each has its own isolated state file. This approach is particularly useful when you want to use the same configuration for different environments, but each environment's state is kept separate.
 
Example of Workspace-specific Variables:
<pre>
# terraform.tfvars for dev
aws_region = "us-east-1"
cidr_block = "10.0.0.0/16"
 
# terraform.tfvars for prod
aws_region = "us-west-2"
cidr_block = "10.1.0.0/16"
</pre>
 
Now, you can have different sets of configurations for dev, prod, and test environments with environment-specific variables that can be managed with different workspaces.


=== 4. Secure Secrets and Sensitive Data ===
== Secure Secrets and Sensitive Data ==
Use Terraform variables with `sensitive = true` and AWS Secrets Manager.
Use Terraform variables with `sensitive = true` and AWS Secrets Manager.


'''Example (`variables.tf`):'''
Example (variables.tf):
<source lang="hcl">
<pre>
variable "db_password" {
variable "db_password" {
   description = "Database password"
   description = "Database password"
Line 60: Line 79:
   sensitive  = true
   sensitive  = true
}
}
</source>
</pre>


== Essential Terraform Commands ==
= Essential Terraform Commands =
These commands are used in most Terraform workflows.
These commands are used in most Terraform workflows.


'''Initialization:'''
== Initialization: ==
<source lang="bash">
<pre>
terraform init
terraform init
</source>
</pre>


'''Plan the deployment:'''
== Plan the deployment: ==
<source lang="bash">
<pre>
terraform plan -var="aws_region=us-east-1"
terraform plan -var="aws_region=us-east-1"
</source>
</pre>


'''Apply changes:'''
== Apply changes: ==
<source lang="bash">
<pre>
terraform apply -var="aws_region=us-east-1" -auto-approve
terraform apply -var="aws_region=us-east-1" -auto-approve
</source>
</pre>


'''Check Terraform state:'''
== Check Terraform state: ==
<source lang="bash">
<pre>
terraform state list
terraform state list
</source>
</pre>


'''Destroy resources:'''
== Destroy resources: ==
<source lang="bash">
<pre>
terraform destroy -var="aws_region=us-east-1" -auto-approve
terraform destroy -var="aws_region=us-east-1" -auto-approve
</source>
</pre>


== Deploying an AWS VPC ==
= Deploying an AWS VPC =
This example provisions a '''VPC''' with public and private subnets.
This example provisions a VPC with public and private subnets.


'''VPC Module (`vpc.tf`):'''
== VPC Module (vpc.tf): ==
<source lang="hcl">
<pre>
module "vpc" {
module "vpc" {
   source = "./modules/vpc"
   source = "./modules/vpc"
Line 103: Line 122:
   private_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
   private_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
}
}
</source>
</pre>


'''VPC Module (`modules/vpc/main.tf`):'''
== VPC Module (modules/vpc/main.tf): ==
<source lang="hcl">
<pre>
resource "aws_vpc" "main" {
resource "aws_vpc" "main" {
   cidr_block = var.cidr_block
   cidr_block = var.cidr_block
Line 113: Line 132:
   }
   }
}
}
</source>
</pre>


'''Variables (`modules/vpc/variables.tf`):'''
== Variables (modules/vpc/variables.tf): ==
<source lang="hcl">
<pre>
variable "vpc_name" { type = string }
variable "vpc_name" { type = string }
variable "cidr_block" { type = string }
variable "cidr_block" { type = string }
variable "public_subnets" { type = list(string) }
variable "public_subnets" { type = list(string) }
variable "private_subnets" { type = list(string) }
variable "private_subnets" { type = list(string) }
</source>
</pre>


== Deploying a Terraform CI/CD Pipeline ==
= Deploying a Terraform CI/CD Pipeline =
A Terraform CI/CD pipeline ensures consistent and automated deployments. This example uses AWS CodePipeline.
A Terraform CI/CD pipeline ensures consistent and automated deployments. This example uses AWS CodePipeline.


'''Pipeline Stages:'''
== Pipeline Stages: ==
# '''Source''' – Fetch Terraform code from Bitbucket.
* '''Source''' – Fetch Terraform code from Bitbucket.
# '''Plan''' – Run `terraform plan`.
* '''Plan''' – Run `terraform plan`.
# '''Approve''' – Manual approval for `prod`.
* '''Approve''' – Manual approval for `prod`.
# '''Apply''' – Run `terraform apply`.
* '''Apply''' – Run `terraform apply`.


'''Pipeline Definition (`pipeline.tf`):'''
== Pipeline Definition (pipeline.tf): ==
<source lang="hcl">
<pre>
resource "aws_codepipeline" "terraform_pipeline" {
resource "aws_codepipeline" "terraform_pipeline" {
   name    = "terraform-deploy"
   name    = "terraform-deploy"
Line 193: Line 212:
   }
   }
}
}
</source>
</pre>
 
= Security Best Practices =
* '''Enable AWS Config & GuardDuty''' – Monitor changes and security threats.
* '''Encrypt sensitive data''' – Use '''AWS KMS''' for encrypting resources.
* '''Use private subnets''' – Keep sensitive resources off the public internet.
* '''Use IAM roles with least privilege access.'''
 
= Conclusion =
By following these Terraform best practices for AWS, you ensure a '''secure''', '''scalable''', and '''efficient''' infrastructure. Keep your Terraform setup '''modular''', '''automated''', and '''well-documented'''.
 
== Deploying with Workspaces for Environment Separation ==
Workspaces are useful when you want to maintain environment separation in a single Terraform configuration. For example, each environment (dev, test, prod) would have its own workspace, ensuring separate state files and variable configurations.
 
Steps to Deploy Using Workspaces:
1. Create and switch to a workspace:
  <pre>
  terraform workspace new dev
  terraform workspace select dev
  terraform apply
  </pre>
 
2. Apply changes in the dev environment:
  <pre>
  terraform apply
  </pre>
 
3. Switch to the production workspace and apply:
  <pre>
  terraform workspace select prod
  terraform apply
  </pre>
 
By using workspaces, you separate your environments' state files, making it easier to manage infrastructure across multiple environments. Each workspace can have different configurations or even different variables.
 
== Deploying Without Workspaces ==
If you don't want to use workspaces and want to deploy in different environments without this separation, you can use distinct `terraform.tfvars` files or specify variables directly in the command line.
 
For example:
1. In the dev environment, you could specify variables like so:
  <pre>
  terraform apply -var="aws_region=us-east-1" -var="cidr_block=10.0.0.0/16"
  </pre>


== Security Best Practices ==
2. For production, you can specify a different set of variables:
* '''Enable AWS Config & GuardDuty''' – Monitor changes and security threats.
  <pre>
* '''Encrypt sensitive data''' – Use '''AWS KMS''' for encrypting resources.
  terraform apply -var="aws_region=us-west-2" -var="cidr_block=10.1.0.0/16"
* '''Use private subnets''' – Keep sensitive resources off the public internet.
  </pre>
* '''Use IAM roles with least privilege access.''' 


== Conclusion ==
This method doesn’t use workspaces but still allows different configurations for different environments by passing the relevant variables during the apply phase.
By following these Terraform best practices for AWS, you ensure a '''secure''', '''scalable''', and '''efficient''' infrastructure. Keep your Terraform setup '''modular''', '''automated''', and '''well-documented'''. 


---
---


'''''Retrieved from your Terraform Wiki'''''
'''''Retrieved from your Terraform Wiki'''''

Latest revision as of 14:41, 3 February 2025

Summary

Terraform is an open-source Infrastructure as Code (IaC) tool developed by HashiCorp. It allows you to define and provision infrastructure using a declarative configuration language called HCL (HashiCorp Configuration Language).

Best Practices

Use Remote Backend for State Management

Terraform stores state to track infrastructure changes. A remote backend (e.g., S3 + DynamoDB) ensures consistency and team collaboration.

Example (backend.tf):

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "envs/prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-lock"
    encrypt        = true
  }
}

Use Modules for Reusability

Organizing infrastructure as modules makes it easier to maintain and reuse components.

Example Directory Structure:

terraform/
├── modules/
│   ├── vpc/
│   ├── ec2/
│   ├── rds/
│   ├── s3/
├── environments/
│   ├── dev/
│   ├── prod/
│   ├── test/

Use Workspaces for Multi-Environment Management

Workspaces allow Terraform to manage multiple environments within the same configuration.

Commands to Create and Switch Workspaces:

terraform workspace new dev
terraform workspace select dev
terraform apply

To switch to a different environment:

terraform workspace select prod
terraform apply

Using workspaces ensures that your environments (e.g., dev, prod, test) are separated, and each has its own isolated state file. This approach is particularly useful when you want to use the same configuration for different environments, but each environment's state is kept separate.

Example of Workspace-specific Variables:

# terraform.tfvars for dev
aws_region = "us-east-1"
cidr_block = "10.0.0.0/16"

# terraform.tfvars for prod
aws_region = "us-west-2"
cidr_block = "10.1.0.0/16"

Now, you can have different sets of configurations for dev, prod, and test environments with environment-specific variables that can be managed with different workspaces.

Secure Secrets and Sensitive Data

Use Terraform variables with `sensitive = true` and AWS Secrets Manager.

Example (variables.tf):

variable "db_password" {
  description = "Database password"
  type        = string
  sensitive   = true
}

Essential Terraform Commands

These commands are used in most Terraform workflows.

Initialization:

terraform init

Plan the deployment:

terraform plan -var="aws_region=us-east-1"

Apply changes:

terraform apply -var="aws_region=us-east-1" -auto-approve

Check Terraform state:

terraform state list

Destroy resources:

terraform destroy -var="aws_region=us-east-1" -auto-approve

Deploying an AWS VPC

This example provisions a VPC with public and private subnets.

VPC Module (vpc.tf):

module "vpc" {
  source = "./modules/vpc"

  vpc_name        = "prod-vpc"
  cidr_block      = "10.0.0.0/16"
  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
  private_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
}

VPC Module (modules/vpc/main.tf):

resource "aws_vpc" "main" {
  cidr_block = var.cidr_block
  tags = {
    Name = var.vpc_name
  }
}

Variables (modules/vpc/variables.tf):

variable "vpc_name" { type = string }
variable "cidr_block" { type = string }
variable "public_subnets" { type = list(string) }
variable "private_subnets" { type = list(string) }

Deploying a Terraform CI/CD Pipeline

A Terraform CI/CD pipeline ensures consistent and automated deployments. This example uses AWS CodePipeline.

Pipeline Stages:

  • Source – Fetch Terraform code from Bitbucket.
  • Plan – Run `terraform plan`.
  • Approve – Manual approval for `prod`.
  • Apply – Run `terraform apply`.

Pipeline Definition (pipeline.tf):

resource "aws_codepipeline" "terraform_pipeline" {
  name     = "terraform-deploy"
  role_arn = aws_iam_role.pipeline_role.arn

  artifact_store {
    location = "my-codepipeline-bucket"
    type     = "S3"
  }

  stage {
    name = "Source"
    action {
      name             = "FetchSource"
      category         = "Source"
      owner           = "AWS"
      provider        = "CodeCommit"
      version         = "1"
      configuration   = { RepositoryName = "terraform-repo", BranchName = "main" }
      output_artifacts = ["source_output"]
    }
  }

  stage {
    name = "Plan"
    action {
      name             = "TerraformPlan"
      category         = "Build"
      owner           = "AWS"
      provider        = "CodeBuild"
      version         = "1"
      input_artifacts  = ["source_output"]
      configuration   = { ProjectName = aws_codebuild_project.terraform_plan.name }
    }
  }

  stage {
    name = "Approve"
    action {
      name     = "ManualApproval"
      category = "Approval"
      owner    = "AWS"
      provider = "Manual"
      version  = "1"
    }
  }

  stage {
    name = "Apply"
    action {
      name             = "TerraformApply"
      category         = "Build"
      owner           = "AWS"
      provider        = "CodeBuild"
      version         = "1"
      input_artifacts  = ["source_output"]
      configuration   = { ProjectName = aws_codebuild_project.terraform_apply.name }
    }
  }
}

Security Best Practices

  • Enable AWS Config & GuardDuty – Monitor changes and security threats.
  • Encrypt sensitive data – Use AWS KMS for encrypting resources.
  • Use private subnets – Keep sensitive resources off the public internet.
  • Use IAM roles with least privilege access.

Conclusion

By following these Terraform best practices for AWS, you ensure a secure, scalable, and efficient infrastructure. Keep your Terraform setup modular, automated, and well-documented.

Deploying with Workspaces for Environment Separation

Workspaces are useful when you want to maintain environment separation in a single Terraform configuration. For example, each environment (dev, test, prod) would have its own workspace, ensuring separate state files and variable configurations.

Steps to Deploy Using Workspaces: 1. Create and switch to a workspace:

   terraform workspace new dev
   terraform workspace select dev
   terraform apply
   

2. Apply changes in the dev environment:

   terraform apply
   

3. Switch to the production workspace and apply:

   terraform workspace select prod
   terraform apply
   

By using workspaces, you separate your environments' state files, making it easier to manage infrastructure across multiple environments. Each workspace can have different configurations or even different variables.

Deploying Without Workspaces

If you don't want to use workspaces and want to deploy in different environments without this separation, you can use distinct `terraform.tfvars` files or specify variables directly in the command line.

For example: 1. In the dev environment, you could specify variables like so:

   terraform apply -var="aws_region=us-east-1" -var="cidr_block=10.0.0.0/16"
   

2. For production, you can specify a different set of variables:

   terraform apply -var="aws_region=us-west-2" -var="cidr_block=10.1.0.0/16"
   

This method doesn’t use workspaces but still allows different configurations for different environments by passing the relevant variables during the apply phase.

---

Retrieved from your Terraform Wiki