Important: replace every with your actual values (region, AMI, key pair name, VPC/subnet IDs). The AMI in your example may be region-specific — verify it for your region.
Project layout
day68-autoscaling/
├─ main.tf
├─ variables.tf
├─ outputs.tf
└─ terraform.tfvars (optional)
variables.tf
variable "region" {
type = string
default = "us-east-1"
}
variable "ami" {
type = string
default = "ami-005f9685cb30f234b" # replace if not available in your region
}
variable "instance_type" {
type = string
default = "t2.micro"
}
variable "key_name" {
type = string
default = "<YOUR_KEY_PAIR_NAME>"
}
variable "vpc_id" {
type = string
default = "<YOUR_VPC_ID>"
}
variable "public_subnet_ids" {
type = list(string)
default = ["<PUBLIC_SUBNET_ID_1>", "<PUBLIC_SUBNET_ID_2>"]
}
main.tf
This creates a security group (SSH & HTTP), a classic ELB (optional but included because your example referenced a load balancer), a launch configuration, and an autoscaling group.
terraform {
required_providers {
aws = { source = "hashicorp/aws" version = "~> 5.0" }
}
}
provider "aws" {
region = var.region
}
# --- Security group for web instances ---
resource "aws_security_group" "web_server" {
name = "day68-web-sg"
description = "Allow SSH and HTTP"
vpc_id = var.vpc_id
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # For demo only. Restrict in production.
}
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "day68-web-sg" }
}
# --- Optional Classic ELB to attach to ASG (example) ---
resource "aws_elb" "web_server_lb" {
name = "day68-web-elb"
subnets = var.public_subnet_ids
security_groups = [aws_security_group.web_server.id]
listener {
instance_port = 80
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
health_check {
healthy_threshold = 2
unhealthy_threshold = 2
timeout = 3
target = "HTTP:80/"
interval = 30
}
tags = { Name = "day68-web-elb" }
}
# --- Launch configuration (legacy) ---
resource "aws_launch_configuration" "web_server_lc" {
name_prefix = "day68-lc-"
image_id = var.ami
instance_type = var.instance_type
key_name = var.key_name
security_groups = [aws_security_group.web_server.id]
user_data = <<-EOF
#!/bin/bash
# simple web page bootstrap
if command -v yum >/dev/null 2>&1; then
yum update -y
yum install -y httpd
systemctl enable httpd
systemctl start httpd
echo "<html><body><h1>You're doing really Great</h1></body></html>" > /var/www/html/index.html
elif command -v apt-get >/dev/null 2>&1; then
apt-get update -y
apt-get install -y apache2
systemctl enable apache2
systemctl start apache2
echo "<html><body><h1>You're doing really Great</h1></body></html>" > /var/www/html/index.html
fi
EOF
lifecycle {
create_before_destroy = true
}
}
# --- Auto Scaling Group ---
resource "aws_autoscaling_group" "web_server_asg" {
name = "web-server-asg"
launch_configuration = aws_launch_configuration.web_server_lc.name
min_size = 1
max_size = 3
desired_capacity = 2
vpc_zone_identifier = var.public_subnet_ids
health_check_type = "EC2"
health_check_grace_period = 120
# attach ELB (classic) created above
load_balancers = [aws_elb.web_server_lb.name]
tag {
key = "Name"
value = "day68-web"
propagate_at_launch = true
}
}
outputs.tf
output "asg_name" {
value = aws_autoscaling_group.web_server_asg.name
}
output "elb_dns_name" {
value = aws_elb.web_server_lb.dns_name
}
Run it (commands)
A. Initialize:
cd day68-autoscaling
terraform init
B. Validate & plan:
terraform validate
terraform plan -out plan.tfplan
C. Apply:
terraform apply "plan.tfplan"
# or: terraform apply -auto-approve
Terraform will create the ELB, Launch Configuration, and ASG which launches instances in the two public subnets.
Test scaling (console + CLI)
Console
- Go to EC2, Auto Scaling Groups, select web-server-asg.
- Click Edit ,change Desired capacity to 3 ,Save.
- Wait a few minutes for instances to launch.
- Verify in EC2 , Instances.
- Change desired capacity back to 1 to scale down and confirm termination.
AWS CLI (optional)
# scale up
aws autoscaling set-desired-capacity --auto-scaling-group-name web-server-asg --desired-capacity 3 --honor-cooldown
# scale down
aws autoscaling set-desired-capacity --auto-scaling-group-name web-server-asg --desired-capacity 1 --honor-cooldown
Verify web page
• If you used ELB, open the ELB DNS:
http://$(terraform output -raw elb_dns_name)
You should see You’re doing really Great.
• Or open the public IP of any instance.
Cleanup
To remove resources and stop charges:
terraform destroy -auto-approve
Troubleshooting tips
• ASG not launching instances: check subnet IDs, IAM permissions, and AMI availability in region.
• User data script failed: inspect instance system logs in EC2 console or SSH and check /var/log/cloud-init-output.log.
• Health check failures: increase health_check_grace_period to allow setup time.
• SSH exposed to 0.0.0.0/0: change ingress to your IP only for security.
Notes & best practice recommendations
• aws_launch_configuration is legacy. Prefer aws_launch_template for new projects — launch templates are more flexible (and needed for many modern features). I can provide a launch_template + ASG + ALB example if you want.
• For HTTP scaling, prefer an ALB (Application Load Balancer) + Target Group instead of Classic ELB. ALB integrates with target tracking and metrics better.
• In production, restrict SSH to your IP or use SSM Session Manager instead of opening port 22.
• For autoscaling based on metrics, add scaling policies (target tracking or step policies) to auto-adjust based on CPU, request counts, etc.
Top comments (0)