Build a Resilient and Affordable ECS Fargate Infrastructure with Terraform
As cloud-native applications become the norm, developers are searching for resilient and cost-effective infrastructure solutions. Amazon ECS on Fargate offers a compelling serverless container orchestration platform, eliminating the need to manage EC2 instances. When paired with Terraform, this combination becomes a powerful Infrastructure-as-Code (IaC) solution for deploying scalable microservices.
In this blog post, we'll walk through the steps to building a highly available, cost-efficient ECS Fargate infrastructure using Terraform.
Why Choose ECS Fargate with Terraform?
ECS Fargate abstracts server provisioning—no EC2, no patching, just tasks.
Terraform enables repeatable, version-controlled infrastructure deployments.
Together, they ensure rapid scalability, automated provisioning, and resource-level cost control.
Core Architecture Components
VPC & Subnets: Custom VPC with public/private subnets in multiple Availability Zones for high availability.
Security Groups: Fine-grained control of access to containers and load balancers.
Application Load Balancer (ALB): Routes traffic to ECS services and enables scaling.
ECS Cluster: Managed by AWS ECS, using Fargate launch type.
Task Definitions: Docker containers configured with memory, CPU, and IAM roles.
ECS Services: Auto-scalable services with desired task count and load balancing.
Auto Scaling Policies: Scale based on CPU, memory, or custom CloudWatch metrics.
Terraform Modules: Reusable IaC modules for best practices and DRY principles.
Step-by-Step Terraform Configuration
1. Define the VPC and Subnets
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
name = "fargate-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
}
2. Create the ECS Cluster
resource "aws_ecs_cluster" "main" {
name = "fargate-cluster"
}
3. Define IAM Roles
Use aws_iam_role and aws_iam_policy to allow ECS tasks to access AWS services like S3, CloudWatch, or DynamoDB.
4. Configure Task Definition
resource "aws_ecs_task_definition" "app" {
family = "fargate-app"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
...
}
5. Deploy ECS Service with ALB Integration
resource "aws_ecs_service" "web" {
name = "fargate-service"
cluster = aws_ecs_cluster.main.id
launch_type = "FARGATE"
task_definition = aws_ecs_task_definition.app.arn
desired_count = 2
network_configuration {
subnets = module.vpc.private_subnets
security_groups = [aws_security_group.ecs_tasks.id]
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_lb_target_group.app.arn
container_name = "app"
container_port = 80
}
}
6. Auto Scaling (Optional but Recommended)
Use aws_appautoscaling_target and aws_appautoscaling_policy to scale ECS tasks automatically.
Cost Optimization Tips
Right-size containers with minimal CPU/memory.
Scale down during off-peak hours using scheduled auto scaling.
Use Graviton2-compatible tasks to reduce Fargate cost.
Minimize unused resources: clean up ALBs, target groups, unused IAM roles, etc.
Resilience Best Practices
Deploy across multiple AZs.
Use circuit breakers and health checks in ECS services.
Enable ALB stickiness if session persistence is needed.
Store terraform state in S3 with DynamoDB locking for consistency.
Monitoring & Logging
Enable AWS CloudWatch Logs in task definitions.
Use Container Insights for deep visibility.
Set up CloudWatch Alarms for autoscaling thresholds.
Testing the Deployment
After deployment:
Access the service via the ALB DNS name.
Use aws ecs list-tasks and describe-tasks to check task health.
Confirm logs in CloudWatch.

Comments
Post a Comment