Steps On How To Create Auto Scaling and SNS on AWS Using Terraform Scripts
Introduction
Ensuring your applications can handle varying loads efficiently is crucial in the modern cloud environment. Auto Scaling helps maintain application availability and allows you to automatically scale your Amazon EC2 capacity up or down according to your defined conditions.
Amazon SNS (Simple Notification Service) enables you to send notifications from the cloud to users via SMS, email, or even HTTP endpoints.
Using Terraform to manage these resources as code simplifies the process and makes it reproducible.
In this article, I walk you through creating an Auto Scaling group and configuring SNS notifications using Terraform.
Prerequisites
- You need some basic understanding of AWS services, particularly EC2, Auto Scaling, and SNS.
- Install Terraform on your local machine.
- Configure AWS CLI with appropriate permissions.
Step 1: Set Up Your Terraform Configuration
Create a directory for your Terraform configuration files. Create a new directory and navigate into it:
mkdir terraform-autoscaling-sns
cd terraform-autoscaling-sns
Step 2: Define the Provider and Version
Create a file and name it provider.tf. In this file, start by defining the AWS provider.
This tells Terraform that we are managing resources in AWS:
provider "aws" {
region = var.AWS_REGION
}
terraform {
required_version = ">= 0.12"
}
Step 3: Create The VPC and Subnets
Create a file, name it vpc.tf, and add the following code:
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "main-public-1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
map_public_ip_on_launch = true
}
resource "aws_subnet" "main-public-2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1b"
map_public_ip_on_launch = true
}
resource "aws_subnet" "main-public-3" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.3.0/24"
availability_zone = "us-east-1c"
map_public_ip_on_launch = true
}
resource "aws_subnet" "main-private-1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.4.0/24"
availability_zone = "us-east-1a"
}
resource "aws_subnet" "main-private-2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.5.0/24"
availability_zone = "us-east-1b"
}
resource "aws_subnet" "main-private-3" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.6.0/24"
availability_zone = "us-east-1c"
}
The script above will create a VPC and the desired subnets where we want to deploy our infrastructure.
Step 4: Create an EC2 Launch Template and Auto Scaling Group
A launch template is an instance configuration template that an Auto Scaling group uses to launch EC2 instances.
Create a file that you should name autoscaling.tf, and add the following code to define a simple launch template:
resource "aws_launch_configuration" "t2s-launchconfig" {
name_prefix = "t2s-launchconfig"
image_id = var.AMIS[var.AWS_REGION]
instance_type = "t2.micro"
key_name = aws_key_pair.mykeypair.key_name
security_groups = [aws_security_group.allow-ssh.id]
}
resource "aws_autoscaling_group" "t2s-autoscaling" {
name = "t2s-autoscaling"
vpc_zone_identifier = [aws_subnet.main-public-1.id, aws_subnet.main-public-2.id]
launch_configuration = aws_launch_configuration.t2s-launchconfig.name
min_size = 1
max_size = 2
health_check_grace_period = 300
health_check_type = "EC2"
force_delete = true
tag {
key = "Name"
value = "ec2 instance"
propagate_at_launch = true
}
}
Step 5: Configure Auto Scaling Policies
The script below will help you create alarms, and for the sake of this project, we will only do it for CPU metrics.
Create a file and name it autoscalingpolicy.tf, and add this code:
# Creating a scale up alarm
resource "aws_autoscaling_policy" "t2s-cpu-policy" {
name = "t2s-cpu-policy"
autoscaling_group_name = aws_autoscaling_group.t2s-autoscaling.name
adjustment_type = "ChangeInCapacity"
scaling_adjustment = "1"
cooldown = "300"
policy_type = "SimpleScaling"
}
resource "aws_cloudwatch_metric_alarm" "t2s-cpu-alarm" {
alarm_name = "t2s-cpu-alarm"
alarm_description = "t2s-cpu-alarm"
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = "2"
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = "120"
statistic = "Average"
threshold = "30"
dimensions = {
"AutoScalingGroupName" = aws_autoscaling_group.t2s-autoscaling.name
}
actions_enabled = true
alarm_actions = [aws_autoscaling_policy.t2s-cpu-policy.arn]
}
# Creating a scale down alarm
resource "aws_autoscaling_policy" "t2s-cpu-policy-scaledown" {
name = "t2s-cpu-policy-scaledown"
autoscaling_group_name = aws_autoscaling_group.t2s-autoscaling.name
adjustment_type = "ChangeInCapacity"
scaling_adjustment = "-1"
cooldown = "300"
policy_type = "SimpleScaling"
}
resource "aws_cloudwatch_metric_alarm" "t2s-cpu-alarm-scaledown" {
alarm_name = "t2s-cpu-alarm-scaledown"
alarm_description = "t2s-cpu-alarm-scaledown"
comparison_operator = "LessThanOrEqualToThreshold"
evaluation_periods = "2"
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = "120"
statistic = "Average"
threshold = "5"
dimensions = {
"AutoScalingGroupName" = aws_autoscaling_group.t2s-autoscaling.name
}
actions_enabled = true
alarm_actions = [aws_autoscaling_policy.t2s-cpu-policy-scaledown.arn]
}
Step 6: Define the Security Group
Next, create a file and call it securitygroup.tf. This file will create a security group that allows SSH access:
resource "aws_security_group" "allow-ssh" {
vpc_id = aws_vpc.main.id
name = "allow-ssh"
description = "The Security Group allowing SSH and all Egress Traffic"
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "allow-ssh"
}
}
Step 7: Create an SNS Topic
Create an SNS topic to send notifications when scaling events occur:
# Creating An SNS Topic.
resource "aws_sns_topic" "t2s-sns" {
name = "sg-sns"
display_name = "The SNS topic to deploy"
}
resource "aws_autoscaling_notification" "t2s-notify" {
group_names = ["${aws_autoscaling_group.t2s-autoscaling.name}"]
topic_arn = "${aws_sns_topic.t2s-sns.arn}"
notifications = [
"autoscaling:EC2_INSTANCE_LAUNCH",
"autoscaling:EC2_INSTANCE_TERMINATE",
"autoscaling:EC2_INSTANCE_LAUNCH_ERROR"
]
}
resource "aws_sns_topic_subscription" "email-target" {
topic_arn = aws_sns_topic.t2s-sns.arn
protocol = "email"
endpoint = var.email
}
Step 8: Input Variables
Create a file, vars.tf, and add the following content:
variable "AWS_REGION" {
default = "us-east-1"
}
variable "PATH_TO_PRIVATE_KEY" {
default = "key"
}
variable "PATH_TO_PUBLIC_KEY" {
default = "key.pub"
}
variable "AMIS" {
type = map(string)
default = { # Replace with the Desired AMIs and AZs.
us-east-1 = "ami-0e001c9271cf7f3b9"
us-west-1 = "ami-0e001c9271cf7f3b9"
us-east-2 = "ami-0e001c9271cf7f3b9"
}
}
variable "email" {
default = "student4t2s@gmail.com"
}
Step 9: Generate Keys
You will need to generate key pairs after you create this file, key.tf and add the following code:
resource "aws_key_pair" "mykeypair" {
key_name = "my-key"
public_key = file("my-key.pub")
}
Step 10: Initialize, Plan, and Apply Terraform
Once you are sure you have all the configurations in place, run the following commands:
terraform init
terraform plan
terraform apply
Confirm the “terraform apply” after you review the infrastructure details you want to deploy.
When everything is done, you should see something similar to these screenshots.
A VPC with 6 subnets: 3 public and 3 private, two of each in three different Availability Zones.
Next, you will get an email asking you to subscribe to the SNS topic. You will need to check the inbox of the email you added to the vars.tf (variables file).
For this demo, I used student4t2s@gmail.com.
After you click “Confirm subscription” in the email (as shown above), you will be taken to the prompt below to confirm your subscription.
If you go to the SNS Dashboard on AWS, you will see your SNS topic and the subscribers to this topic.
The Terraform scripts will also create an Auto Scaling group and an Auto Scaling Policy to track the desired metrics.
Step 11: Clean Up
Now, make sure you clean up your environment. To do so, use this command:
terraform destroy
Conclusion
Following this guide, you will easily set up an Auto Scaling group and configure SNS notifications using Terraform. This setup ensures your application can handle varying loads efficiently while informing you of scaling events. Automating infrastructure management with Terraform simplifies resource provisioning and ensures consistency and reproducibility across environments. Happy scaling, and God bless you!