Overview
This guide covers the Terraform configuration and deployment process for creating the AWS infrastructure, including VPC, EKS cluster, RDS database, S3 storage, and security services.
The Terraform configuration is organized into modules:
- Networking: VPC, subnets, route tables, gateways, security groups
- Kubernetes Cluster: EKS cluster, node groups, IAM roles
- Database: RDS PostgreSQL with Multi-AZ support (prod only)
- Storage: S3 buckets with encryption and versioning
- Security: WAF, GuardDuty, KMS, CloudTrail, Security Hub
Backend Configuration
Terraform state is stored in S3 for team collaboration:
platform/terraform/main.tf
terraform {
backend "s3" {
bucket = "govtech-terraform-state-835960996869"
key = "terraform.tfstate"
region = "us-east-1"
encrypt = true
}
}
Replace the bucket name with your own S3 bucket created during setup.
Provider Configuration
The AWS provider is configured with default tags:
platform/terraform/main.tf
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Project = "govtech"
Environment = var.environment
ManagedBy = "terraform"
}
}
}
Required Variables
The following variables are required:
| Variable | Description | Default | Required |
|---|
aws_region | AWS region | us-east-1 | No |
environment | Environment name | - | Yes |
vpc_cidr | VPC CIDR block | 10.0.0.0/16 | No |
db_username | Database username | govtech_admin | No |
db_password | Database password | - | Yes |
The db_password variable is sensitive and must be provided via environment variable TF_VAR_db_password or a .tfvars file (never committed to Git).
Deployment Steps
Development Environment
Navigate to Dev Environment
cd platform/terraform/environments/dev
Initialize Terraform
Initialize Terraform and download required providers:Expected output:Initializing the backend...
Initializing modules...
Initializing provider plugins...
Terraform has been successfully initialized!
Review Terraform Plan
Generate and review the execution plan:This shows all resources that will be created. Review carefully before applying. Set Database Password
Set the database password as an environment variable:export TF_VAR_db_password="your-secure-password"
Apply Terraform Configuration
Apply the configuration to create infrastructure:Type yes when prompted to confirm.Initial deployment takes 15-20 minutes. EKS cluster creation is the longest step.
Save Terraform Outputs
Save important outputs for later use:terraform output > terraform-outputs.txt
# Get specific outputs
terraform output cluster_name
terraform output kubeconfig_command
Production Environment
Production deployment requires additional approval and uses different instance sizes and Multi-AZ configuration.
Navigate to Production Environment
cd platform/terraform/environments/prod
Review Production Configuration
Production uses:
- EKS: t3.medium nodes, min 3 nodes (1 per AZ)
- RDS: db.t3.small, Multi-AZ enabled, 30-day backups
- Network: 3 availability zones for high availability
- VPC CIDR: 10.2.0.0/16 (separate from dev/staging)
Initialize and Plan
terraform init
export TF_VAR_db_password="prod-secure-password"
terraform plan -out=prod.tfplan
Save the plan for audit purposes.Apply with Approval
terraform apply prod.tfplan
Production deployment takes 20-30 minutes due to Multi-AZ RDS.
Module Details
Networking Module
Creates VPC with public and private subnets across multiple availability zones:
platform/terraform/main.tf
module "networking" {
source = "./modules/networking"
project_name = local.project_name
environment = var.environment
vpc_cidr = var.vpc_cidr
availability_zones = local.availability_zones
public_subnet_cidrs = local.public_subnet_cidrs
private_subnet_cidrs = local.private_subnet_cidrs
}
Resources Created:
- VPC with DNS enabled
- Public subnets (for ALB)
- Private subnets (for EKS nodes and RDS)
- Internet Gateway
- NAT Gateways (1 per AZ)
- Route tables
- Security groups for EKS, RDS, and ALB
Kubernetes Module
Creates EKS cluster with managed node groups:
platform/terraform/main.tf
module "kubernetes" {
source = "./modules/kubernetes-cluster"
project_name = local.project_name
environment = var.environment
cluster_name = "${local.project_name}-${var.environment}"
vpc_id = module.networking.vpc_id
subnet_ids = module.networking.private_subnet_ids
node_instance_type = local.node_instance_type
node_min_size = local.node_min
node_max_size = local.node_max
node_desired_size = local.node_desired
}
Instance Types by Environment:
- Dev: t3.medium (2 vCPUs, 4GB RAM) - 2 nodes
- Staging: t3.small (2 vCPUs, 2GB RAM) - 3 nodes
- Prod: t3.medium (2 vCPUs, 4GB RAM) - 3-10 nodes
Database Module
Creates RDS PostgreSQL instance:
platform/terraform/main.tf
module "database" {
source = "./modules/database"
project_name = local.project_name
environment = var.environment
subnet_ids = module.networking.private_subnet_ids
security_group_id = module.networking.rds_security_group_id
db_username = var.db_username
db_password = var.db_password
multi_az = var.environment == "prod" ? true : false
}
Configuration by Environment:
| Environment | Instance Class | Storage | Multi-AZ | Backup Retention |
|---|
| Dev | db.t3.micro | 20GB | No | 3 days |
| Staging | db.t3.small | 30GB | No | 7 days |
| Prod | db.t3.small | 50GB | Yes | 30 days |
Security Module
Creates security services:
platform/terraform/main.tf
module "security" {
source = "./modules/security"
project_name = local.project_name
environment = var.environment
account_id = local.account_id
aws_region = var.aws_region
logs_bucket = module.storage.bucket_id
}
Resources Created:
- WAF: Web Application Firewall for ALB protection
- GuardDuty: Threat detection
- KMS: Encryption keys for data at rest
- CloudTrail: API audit logging
- Security Hub: Centralized security findings
ECR Repositories
Terraform creates ECR repositories for Docker images:
platform/terraform/main.tf
resource "aws_ecr_repository" "backend" {
name = "govtech-backend"
image_tag_mutability = "MUTABLE"
image_scanning_configuration {
scan_on_push = true
}
encryption_configuration {
encryption_type = "KMS"
kms_key = module.security.kms_key_arn
}
}
ECR Features:
- Vulnerability scanning on every push
- KMS encryption
- Lifecycle policy (keeps last 10 tagged images, removes untagged after 7 days)
Important Outputs
After deployment, Terraform provides these outputs:
# VPC and Networking
terraform output vpc_id
# EKS Cluster
terraform output eks_cluster_name
terraform output eks_cluster_endpoint
# Database (sensitive)
terraform output rds_endpoint
# ECR Repositories
terraform output ecr_backend_url
terraform output ecr_frontend_url
# GitHub Actions CI/CD
terraform output github_actions_role_arn
# WAF
terraform output waf_arn
Connecting to EKS Cluster
After Terraform completes, configure kubectl:
# Get kubeconfig command from Terraform output
terraform output kubeconfig_command
# Or run directly
aws eks update-kubeconfig --name govtech-dev --region us-east-1
# Verify connection
kubectl cluster-info
kubectl get nodes
Viewing State
# List all resources in state
terraform state list
# Show specific resource
terraform state show module.networking.aws_vpc.main
Importing Existing Resources
# Import existing S3 bucket
terraform import module.storage.aws_s3_bucket.app_storage govtech-dev-app-storage-835960996869
Refreshing State
# Sync state with real infrastructure
terraform refresh
Updating Infrastructure
To update existing infrastructure:
Modify Configuration
Edit the relevant .tf files with your changes.
Plan Changes
Review what will be changed, added, or destroyed.
Some changes may require resource replacement (destroy then create). Review the plan carefully before applying.
Destroying Infrastructure
To destroy all infrastructure (use with caution):
cd platform/terraform/environments/dev
terraform destroy
This will delete ALL resources including databases, S3 buckets (if not protected), and the EKS cluster. Ensure you have backups before proceeding.
Troubleshooting
# Clear cached plugins and modules
rm -rf .terraform
terraform init
State Lock Issues
If state is locked by another process:
# Force unlock (use with caution)
terraform force-unlock <LOCK_ID>
Provider Version Conflicts
# Update providers to latest compatible versions
terraform init -upgrade
EKS Cluster Creation Timeout
EKS creation can take 15-20 minutes. If it times out:
# Check cluster status in AWS Console
aws eks describe-cluster --name govtech-dev --region us-east-1
# Continue waiting for completion
terraform apply
Next Steps
- Deploy applications to Kubernetes
- Understand environment configurations
- Set up rollback procedures