Terraform deploy cluster web servers in Auto Scaling Group

#Introduction

In this tutorial, How to deploy cluster web servers use Terraform

  • AWS auto scaling Group: Min = 2, Max = 10 and desired_capacity =3
  • User user_data and create a script to install Nginx webserver on amazon linux 2.
  • Auto Scaling Group: Scaling Policy – Target Tracking policy
  • Security group ingress rule to allow access web server from my laptop 😊

Structure folder and files

Created Cluster_WebServer_ASG folder contains files as below:

asg_config.tf
auto_scale_group.tf
auto_scale_policy.tf
output.tf
provider.tf
securitygroups.tf
variables.tf

On AWS

we created key pair terraform-demo as the picture below

Deploy cluster web servers in Auto Scaling Group

Create a new file asg_config.tf with the content as below

resource aws_launch_configuration "my_config" {
name = "webserver-launch"
image_id = var.ami
instance_type = var.instance_type
security_groups=["${aws_security_group.web_sg.id}"]
key_name = "terraform-demo"
 user_data = <<EOF
#!/bin/bash -xe
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
sudo yum update -y
sudo amazon-linux-extras install nginx1 -y
sudo su -c "/bin/echo 'My Site: DevopsRoles.com' >/usr/share/nginx/html/index.html"
instance_ip=`curl http://169.254.169.254/latest/meta-data/local-ipv4`
sudo su -c "echo $instance_ip >>/usr/share/nginx/html/index.html"
sudo systemctl start nginx
sudo systemctl enable  nginx
EOF
}

Create a new file auto_scale_group.tf with the content as below

resource "aws_autoscaling_group" "first_asg" {
	launch_configuration = aws_launch_configuration.my_config.id
	availability_zones = "${var.azs}"
    
	min_size = 2
	max_size = 10
	desired_capacity = 3
	tag {
		key = "Name"
		value = "terraform-asg"
		propagate_at_launch = true  
	}
}

New file auto_scale_policy.tf with the content as below

resource "aws_autoscaling_policy" "my_asg_policy" {
  name = "webservers_autoscale_policy"
  policy_type = "TargetTrackingScaling"
  autoscaling_group_name = aws_autoscaling_group.first_asg.name

  target_tracking_configuration {
  predefined_metric_specification {
    predefined_metric_type = "ASGAverageCPUUtilization"
  }
  target_value = "75"
  }

}

Create new a provider.tf the content as below

provider "aws" {
        region = var.region
}

Create a new file output.tf with the content as below

output "asg_arn" {
    value = [ "${aws_autoscaling_group.first_asg.arn}"]
}

Create new file variables.tf with the content as below

variable "region" {
	description = " Define the AWS region "
	default = "us-west-2"
}
variable "server_port" {
	description = "http service listen"
	default = "80"
}

variable "ssh_port" {
	description = "ssh to server"
	default = "22"
}
variable "instance_type" { 
	description = "AWS ec2 instance type"
	default="t2.micro"
}
variable "my_public_ip" {
	description = "My laptop public IP ..." 
        default = "116.110.26.150/32"
}
variable "ami" {
    description = "amazon machine image"
        default = "ami-0c2d06d50ce30b442"
}

variable "azs" {
    default = [ "us-west-2a", "us-west-2b", "us-west-2c" ]
}

new file securitygroups.tf with the content as below

resource "aws_security_group" "web_sg" { 

    ingress {
        from_port = var.server_port
        to_port = var.server_port
        protocol = "tcp"
        cidr_blocks = [ var.my_public_ip ]
    }

    ingress {
        from_port = var.ssh_port
        to_port = var.ssh_port
        protocol = "tcp"
        cidr_blocks = [ var.my_public_ip ]
    }
egress {
    from_port       = 0
    to_port         = 0
    protocol        = "-1"
    cidr_blocks     = ["0.0.0.0/0"]
  }    
}

First, we run below to initialize, download the plugins and validate the terraform syntax…

terraform init
terraform validate

The output terminal is as follows

Applying a template

$ terraform apply

The output terminal is as below

C:\Users\HuuPV\Desktop\Terraform\Cluster_WebServer_ASG>terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
  + create

Terraform will perform the following actions:

  # aws_autoscaling_group.first_asg will be created
  + resource "aws_autoscaling_group" "first_asg" {
      + arn                       = (known after apply)
      + availability_zones        = [
          + "us-west-2a",
          + "us-west-2b",
          + "us-west-2c",
        ]
      + default_cooldown          = (known after apply)
      + desired_capacity          = 3
      + force_delete              = false
      + force_delete_warm_pool    = false
      + health_check_grace_period = 300
      + health_check_type         = (known after apply)
      + id                        = (known after apply)
      + launch_configuration      = (known after apply)
      + max_size                  = 10
      + metrics_granularity       = "1Minute"
      + min_size                  = 2
      + name                      = (known after apply)
      + name_prefix               = (known after apply)
      + protect_from_scale_in     = false
      + service_linked_role_arn   = (known after apply)
      + vpc_zone_identifier       = (known after apply)
      + wait_for_capacity_timeout = "10m"

      + tag {
          + key                 = "Name"
          + propagate_at_launch = true
          + value               = "terraform-asg"
        }
    }

  # aws_autoscaling_policy.my_asg_policy will be created
  + resource "aws_autoscaling_policy" "my_asg_policy" {
      + arn                     = (known after apply)
      + autoscaling_group_name  = (known after apply)
      + id                      = (known after apply)
      + metric_aggregation_type = (known after apply)
      + name                    = "webservers_autoscale_policy"
      + policy_type             = "TargetTrackingScaling"

      + target_tracking_configuration {
          + disable_scale_in = false
          + target_value     = 60

          + predefined_metric_specification {
              + predefined_metric_type = "ASGAverageCPUUtilization"
            }
        }
    }

  # aws_launch_configuration.my_config will be created
  + resource "aws_launch_configuration" "my_config" {
      + arn                         = (known after apply)
      + associate_public_ip_address = false
      + ebs_optimized               = (known after apply)
      + enable_monitoring           = true
      + id                          = (known after apply)
      + image_id                    = "ami-0c2d06d50ce30b442"
      + instance_type               = "t2.micro"
      + key_name                    = "terraform-demo"
      + name                        = "webserver-launch"
      + name_prefix                 = (known after apply)
      + security_groups             = (known after apply)
      + user_data                   = "e210837ad2017cf0971bc0ed4af86edab9d8a10d"

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + no_device             = (known after apply)
          + snapshot_id           = (known after apply)
          + throughput            = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + throughput            = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

  # aws_security_group.web_sg will be created
  + resource "aws_security_group" "web_sg" {
      + arn                    = (known after apply)
      + description            = "Managed by Terraform"
      + egress                 = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = ""
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = false
              + to_port          = 0
            },
        ]
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "116.110.26.150/32",
                ]
              + description      = ""
              + from_port        = 22
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 22
            },
          + {
              + cidr_blocks      = [
                  + "116.110.26.150/32",
                ]
              + description      = ""
              + from_port        = 80
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 80
            },
        ]
      + name                   = (known after apply)
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags_all               = (known after apply)
      + vpc_id                 = (known after apply)
    }

Plan: 4 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + asg_arn = [
      + (known after apply),
    ]

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_security_group.web_sg: Creating...
aws_security_group.web_sg: Creation complete after 8s [id=sg-083d582a5691c56d9]
aws_launch_configuration.my_config: Creating...
aws_launch_configuration.my_config: Creation complete after 2s [id=webserver-launch]
aws_autoscaling_group.first_asg: Creating...
aws_autoscaling_group.first_asg: Still creating... [10s elapsed]
aws_autoscaling_group.first_asg: Still creating... [21s elapsed]
aws_autoscaling_group.first_asg: Still creating... [31s elapsed]
aws_autoscaling_group.first_asg: Still creating... [41s elapsed]
aws_autoscaling_group.first_asg: Creation complete after 45s [id=terraform-20211010125900499300000002]
aws_autoscaling_policy.my_asg_policy: Creating...
aws_autoscaling_policy.my_asg_policy: Creation complete after 2s [id=webservers_autoscale_policy]

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

asg_arn = [
  "arn:aws:autoscaling:us-west-2:633602660500:autoScalingGroup:2b023a9d-a66c-464e-9cb0-80d9eef00e33:autoScalingGroupName/terraform-20211010125900499300000002",
]

Result on EC2 AWS

3 Instance EC2

Auto Scaling: Launch configurations

Auto Scaling groups

Conclusion

You have to deploy cluster web servers in the Auto Scaling Group. I hope will this your helpful. Thank you for reading the DevopsRoles page!

, ,

About HuuPV

My name is Huu. I love technology and especially Devops Skill such as Docker, vagrant, git so forth. I likes open-sources. so I created DevopsRoles.com site to share the knowledge that I have learned. My Job: IT system administrator. Hobbies: summoners war game, gossip.
View all posts by HuuPV →

Leave a Reply

Your email address will not be published. Required fields are marked *

Comment moderation is enabled. Your comment may take some time to appear.

This site uses Akismet to reduce spam. Learn how your comment data is processed.