Skip to content

Contains terraform scripts for learning important topics, useful tips and production environment best practice recommendations.

Notifications You must be signed in to change notification settings

prasanna7401/Terraform_Best_Practice_Examples

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Learn Terraform

Useful items:

  1. Statefile Backup:

    • If stored locally, the tfstate.backup file contains the previous terraform apply results.
    • If storing in a remote backend, make sure to enable versioning to be able to roll back.
    • If your apply operation fails without saving the state file to the remote backend, terraform will save the file locally under the name errored.tfstate. You can set up appropriate steps to save this file from your pipeline or CI Server. Alternatively, you can push this state file to the remote backend by terraform state push errored.tfstate
    • If your pipeline crashes during the process, the state file may remain locked. In this case, you can run terraform force-unlock <LOCK_ID>
  2. Import existing resources or Handle Manual changes to managed resources: 2.1. How to import a resource configuration for managing via terraform

    • Step-1: Create an empty resource block in the terraform file
        resource "aws_security_group" "to_be_imported" {
        # fill later after import
        }
    • Step-2: Run terraform import <resource_type>.<resource_name> <resource_id> (For example, aws_security_group.example sg-12345)
    • Step-3: After the configurations get imported into your state file, run terraform show or terraform state show <resource_type>.<resource_name>
    • Step-4: Clean up the output-only attributes like id, arn, timestamp, etc., and add the code block to the terraform configuration file.
  • If you had made manual changes to your terraform-managed resource, you could update your statefile by running terraform apply --refresh-only or terraform refresh

Other options: For bulk import of resources, you can use tools like terraformer & terracognita

  1. Avoid Resource modification/deletion (useful for imported/critical resources):

    • Option 1: Add a lifecycle block to your code:
      lifecycle {
          ignore_changes = [cidr_block] # or any specific resource config
          prevent_destroy = true
      }
    • Option 2: Manually remove the resource configuration from the state file.
          terraform state rm aws_instance.example
  2. Schematize/Validate Input variables:

  • Basic Input Validation: Use validation block
         variable "public_ip" { 
         description = "Public IP address for the service" 
         type = string 
         validation { 
             condition = can(regex("^(([0-9]{1,3}\\.){3}[0-9]{1,3})$", var.public_ip)) && length(split(".", var.public_ip)) == 4 && alltrue([for octet in split(".", var.public_ip) : tonumber(octet) <= 255]) 
             error_message = "The Public IP address must be in the format x.x.x.x where x is a number between 0 and 255." 
             } 
         }
    
  • For complex conditions on created resource: Use condition block under lifecycle block.
  • For more examples, check here.
  1. Enforce Default Tags: You can set up default tags during the provider configuration.

    provider "aws" {
        region = "something"
        default_tags {
            tags = {
                deployment = "terraform"
            }
        }
    }
    • This adds the mentioned tag if no tag is specified in your resource or module.
    • Alternatively, you can use policy as code like OPA, terratest to check your code. For reference, click here
  2. Instructions before refactoring existing code:

    • Modifying the names of the existing resource/module block may trigger changes causing downtime. So, follow appropriate procedures to move the state file resource configurations using one of the below-mentioned steps:
    1. State move command:
    terraform state mv <OLD_BLOCK_REFEERENCE> <NEW_REFERENCE>
    1. Use moved block:
    moved {
        from = aws_instance.something
        to = aws_instance.myserver
    }
  3. Force Re-creation of resource: Use either --replace flag with plan or apply step. For ex: terraform apply -replace="aws_something.example"

  4. Troubleshooting: Set TF_LOG to any debugging level (say, DEBUG) environment variable output. To store the logs in a persistant file, use TF_LOG_PATH, if not mentioned, you will see the debugging output in the terraform CLI.

  5. Reference to another state file:

  • Use case: Access outputs and resource attributes of another terraform deployment.
  • Example:
    data "terraform_remote_state" "example" {
        # For locally stored state files
        # backend = "local"
        # config = {
        #     path = "..."
        # }
        # For remote backends:
        backend = "s3"
        config = {
            bucket = "my-bucket"
            key = "example/firewalls/terraform.tfstate"
            region = "us-east-1"
        }
    
    }

Some parts of this repository contains the codes used for learning purposes from Terraform: Up and Running, originally authored by Yevgeniy Brikman and licensed under the MIT License.

About

Contains terraform scripts for learning important topics, useful tips and production environment best practice recommendations.

Topics

Resources

Stars

Watchers

Forks