In the last post, we deployed a secure, scalable AWS architecture for a restaurant booking app using EC2, RDS, and CloudWatch. Now letβs take it further:
- π Auto Scaling EC2 Instances
- βοΈ Infrastructure as Code with Terraform
- π Secrets Manager for Secure Configs
This final layer turns your setup into a production-grade cloud-native app.
π 1. Auto Scaling EC2 Instances
πΉ Why It Matters
Your app should automatically handle more traffic and recover from failure β even when you’re asleep.
β What Weβll Do
- Create an Auto Scaling Group (ASG)
- Attach to Application Load Balancer (ALB)
- Use Launch Templates for consistency
π§ Steps
Create Launch Template
aws ec2 create-launch-template \
--launch-template-name web-app-template \
--version-description v1 \
--launch-template-data file://lt-config.json
Create Auto Scaling Group
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name web-app-asg \
--launch-template LaunchTemplateName=web-app-template,Version=1 \
--min-size 2 --max-size 5 --desired-capacity 2 \
--vpc-zone-identifier subnet-xxxxxx,subnet-yyyyyy \
--target-group-arns arn:aws:elasticloadbalancing:...
Add Scaling Policy (CPU-Based)
aws autoscaling put-scaling-policy \
--auto-scaling-group-name web-app-asg \
--policy-name cpu-scale-up \
--policy-type TargetTrackingScaling \
--target-tracking-configuration file://cpu-scaling-config.json
βοΈ 2. Infrastructure as Code with Terraform
πΉ Why It Matters
- Avoid manual configuration
- Reproducible and version-controlled
β What Weβll Do
- Use Terraform to deploy VPC, EC2, RDS, IAM, ALB, etc.
π§± Sample Terraform Structure
terraform/
βββ main.tf # Provider and modules
βββ vpc.tf # VPC and subnet config
βββ ec2.tf # Launch template, ASG
βββ alb.tf # Load balancer setup
βββ rds.tf # Database
βββ outputs.tf # Useful outputs (IP, URLs)
π§ Example Snippet
resource "aws_launch_template" "app" {
name_prefix = "web-app"
image_id = "ami-0abc12345"
instance_type = "t3.micro"
user_data = filebase64("init.sh")
}
resource "aws_autoscaling_group" "app_asg" {
desired_capacity = 2
max_size = 5
min_size = 1
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
vpc_zone_identifier = [aws_subnet.public1.id, aws_subnet.public2.id]
target_group_arns = [aws_lb_target_group.app_tg.arn]
}
Run it all with:
terraform init
terraform apply
π 3. Secrets Manager for Environment Variables
πΉ Why It Matters
Never hardcode secrets in .env
files or user data scripts.
β What Weβll Do
- Store API keys, DB passwords securely
- Inject them into EC2 via IAM + SDK/CLI
π§ Create and Retrieve Secret
aws secretsmanager create-secret \
--name db_credentials \
--secret-string '{"username":"admin","password":"mypassword"}'
aws secretsmanager get-secret-value --secret-id db_credentials
π§ Access via Code (Python Example)
import boto3
import json
secrets = boto3.client('secretsmanager')
response = secrets.get_secret_value(SecretId='db_credentials')
creds = json.loads(response['SecretString'])
print(creds['username'])
Or pass to container as ENV via EC2 User Data script:
#!/bin/bash
export DB_USER=$(aws secretsmanager get-secret-value --secret-id db_credentials --query 'SecretString' --output text | jq -r .username)
π¦ What Youβve Built
β EC2 Auto Scaling behind ALB β Declarative Infrastructure via Terraform β Secure Secrets Management via AWS-native services