Deploying infrastructure to multiple environments using Terraform modules

Mohammed IliyasMohammed Iliyas
4 min read

Deploying infrastructure to multiple environments using Terraform modules involves a structured approach to organizing and managing your Terraform code. This guide will walk you through a detailed example of how to set up and deploy complex infrastructure configurations across different environments, including development (dev), quality assurance (QA), staging, and production (prod). We'll cover security, networking, and other considerations in depth.

Step 1: Setting Up Terraform Modules for Multi-Environment Deployment

Organizing Terraform Modules

Terraform modules are reusable components that encapsulate infrastructure configurations. To deploy to multiple environments, you'll create separate modules for each environment. This approach allows you to manage environment-specific configurations and variables efficiently.

  1. Directory Structure:
   infrastructure/
   environments/
   dev/
   main.tf
   variables.tf
   qa/
   main.tf
   variables.tf
   staging/
   main.tf
   variables.tf
   prod/
   main.tf
   variables.tf
   modules/
   network/
   main.tf
   variables.tf
   compute/
   main.tf
   variables.tf
   storage/
   main.tf
   variables.tf
  1. Module Structure:
    • Each environment directory (dev, qa, staging, prod) contains a main.tf file that defines the infrastructure for that environment.

      • The variables.tf file in each environment directory defines environment-specific variables.

      • The modules directory contains reusable modules for network, compute, and storage configurations.

  1. Defining Environment Variables:
   variable "environment" {
     type = string
     default = "dev"
   }

   variable "instance_type" {
     type = string
     default = "t2.micro"
   }
  • Defining Modules:
  • In modules/network/main.tf, define a network module:
   resource "aws_vpc" "this" {
     cidr_block = "10.0.0.0/16"
   }

   resource "aws_subnet" "this" {
     cidr_block = "10.0.1.0/24"
     vpc_id     = aws_vpc.this.id
     availability_zone = "us-west-2a"
   }
  1. Using Modules in Environments:
  • In dev/main.tf, use the network module:
   module "network" {
     source = file("./modules/network")
   }

Managing Variables Across Environments

  1. Environment-Specific Variables:

    • Use environment-specific variables in your modules. For example, in modules/compute/main.tf:
   resource "aws_instance" "this" {
     ami           = "ami-0c94855ba95c71c99"
     instance_type = var.instance_type
   }
  1. Overriding Variables:

    • In prod/variables.tf, you can override the instance_type variable:
   variable "instance_type" {
     type = string
     default = "t2.large"
   }

Step 2: Configuring Complex Infrastructure with Terraform

Configuring Networks

  1. VPC and Subnets:

    • In modules/network/main.tf, define a VPC and subnets:
   resource "aws_vpc" "this" {
     cidr_block = "10.0.0.0/16"
   }

   resource "aws_subnet" "this" {
     cidr_block = "10.0.1.0/24"
     vpc_id     = aws_vpc.this.id
     availability_zone = "us-west-2a"
   }
  1. Security Groups:
  • In modules/network/main.tf, define a security group:
   resource "aws_security_group" "this" {
     name        = "allow_tls"
     description = "Allow TLS inbound traffic"
     vpc_id      = aws_vpc.this.id

     ingress {
       description = "TLS from anywhere"
       from_port   = 443
       to_port     = 443
       protocol    = "tcp"
       cidr_blocks = ["0.0.0.0/0"]
     }
   }

Configuring Compute Resources

  1. EC2 Instances:

    • In modules/compute/main.tf, define an EC2 instance:
   resource "aws_instance" "this" {
     ami           = "ami-0c94855ba95c71c99"
     instance_type = var.instance_type
     vpc_security_group_ids = [aws_security_group.this.id]
     subnet_id = aws_subnet.this.id
   }

Configuring Storage Resources

  1. S3 Buckets:

    • In modules/storage/main.tf, define an S3 bucket:
   resource "aws_s3_bucket" "this" {
     bucket = "my-bucket"
     acl    = "private"
   }

Step 3: Implementing Security and Networking Considerations

Security Considerations

  1. Access Controls:

    • Use IAM roles and policies to manage access to your resources. For example, in modules/compute/main.tf:
   resource "aws_iam_role" "this" {
     name        = "ec2-role"
     description = "EC2 role"

     assume_role_policy = jsonencode({
       Version = "2012-10-17"
       Statement = [
         {
           Action = "sts:AssumeRole"
           Principal = {
             Service = "ec2.amazonaws.com"
           }
           Effect = "Allow"
           Sid    = ""
         }
       ]
     })
   }
  1. Encryption:
  • Use AWS Key Management Service (KMS) to manage encryption keys. For example, in modules/storage/main.tf:
   resource "aws_kms_key" "this" {
     description = "S3 bucket encryption key"
   }

   resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
     bucket = aws_s3_bucket.this.id

     rule {
       apply_server_side_encryption_by_default {
         kms_master_key_id = aws_kms_key.this.arn
         sse_algorithm     = "aws:kms"
       }
     }
   }

Networking Considerations

  1. Network Architecture:

    • Design a network architecture that segregates resources into different subnets and security groups based on their roles.
  2. Network Segmentation:

    • Use subnets and security groups to isolate resources from each other.

Step 4: Deploying and Managing Environments with Terraform

Deploying Environments

  1. Initializing Terraform:

    • Navigate to the environment directory (e.g., dev) and run:
   terraform init
  1. Applying Terraform Configurations:

    • Run:
   terraform apply

Managing and Updating Environments

  1. Updating Infrastructure:

    • Make changes to your Terraform code and run terraform apply again.
  2. Managing State:

    • Use Terraform state files to keep track of your infrastructure state.
  3. Troubleshooting:

    • Use terraform validate to check for errors in your configuration.

    • Use terraform console to interactively explore your infrastructure state.

Additional Considerations

Version Control

  1. Versioning Terraform Code:

    • Use version control systems like Git to manage changes to your Terraform code.

Collaboration

  1. Collaborative Development:

    • Use Terraform workspaces to manage multiple environments and collaborate with team members.

Monitoring and Logging

  1. Monitoring Resources:

    • Use AWS CloudWatch to monitor your resources.
  2. Logging:

    • Use AWS CloudWatch Logs to collect and analyze logs from your resources.

Conclusion

Deploying infrastructure to multiple environments using Terraform modules requires careful planning and organization. By following this guide, you can create a structured approach to managing your infrastructure across different environments, ensuring consistency and security. Remember to consider additional factors like version control, collaboration, and monitoring to ensure the long-term maintainability of your infrastructure.

0
Subscribe to my newsletter

Read articles from Mohammed Iliyas directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mohammed Iliyas
Mohammed Iliyas

As a seasoned DevOps engineer, I bring a comprehensive set of skills to the table, encompassing version control with Git and GitOps using ArgoCD, containerization with Docker, and orchestration with Kubernetes, Helm, and Istio. I'm proficient in infrastructure provisioning and management using Terraform and Ansible, and have expertise in setting up and managing CI/CD pipelines with Jenkins, Azure Pipelines, and AWS CodePipeline. With extensive experience in cloud platforms, including Azure and AWS, I've deployed and managed applications on Azure Kubernetes Service (AKS) and AWS Elastic Container Service (ECS) and Elastic Container Service for Kubernetes (EKS). Additionally, I've integrated security practices into DevOps pipelines, ensuring secure and compliant software development and deployment. My technical prowess extends to Bash shell scripting, Linux system administration, and programming in Golang. Throughout my journey, I've developed a unique blend of skills that enable me to streamline development, deployment, and management of applications across multiple environments.