Steps On How To Create Auto Scaling and SNS on AWS Using Terraform Scripts

Emmanuel
6 min readMay 20, 2024

--

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!

--

--

Emmanuel
Emmanuel

Written by Emmanuel

Certified Cloud Solutions Architect passionate about Cloud & DevOps, Technology Evangelism, Pastoral Ministry, Educator and Mentor, and World Travel.

Responses (1)