Deploying a Highly Available Web App on AWS Using Terraform

frankfolabi - Aug 28 - - Dev Community

It is so exciting to launch a single webserver, and you are now online. The media has made your product popular, and the internet traffic to your website is increasing greatly. How would we handle such a large number of requests? How can we ensure that out server does not go down due to overwhelming request? It would make sense to have additional servers to help hand this situation. Here come scaling which is the ability to increase the number or instance size of your server which we call horizontal or vertical scaling. Would it not be nice to automatically do this? Let us improve our architecture from the previous post.

Configuring the web server with variables

You may have notice that the port number 8080 was hardcoded and duplicated. It may be challenging to make changes without an error if there are numerous occurrences. A best practice is to follow the Don't Repeat Yourself (DRY) principle. To male our code configurable we can define input variables.

Let us define the port number as a variable.

variable "server_port" {
  description = "The port the server will use for HTTP requests"
  type = number
  default = 8080
}
Enter fullscreen mode Exit fullscreen mode

The type constraint will ensure that only a number value is acceptable. the code block also specific that the default port value as 8080. We can now refer to the variable in other places using var.server_port.
Let us now update the security group and the user data.

resource "aws_security_group" "instance" {
    name = "tf-sg"

    ingress {
        from_port = var.server_port
        to_port = var.server_port
        protocol = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
    }   
}
Enter fullscreen mode Exit fullscreen mode

Creating a highly available webserver

To create a highly available, a launch configuration is needed and an auto scaling resource that will use this configuration.

resource "aws_launch_configuration" "webserver" {
    image_id = "ami-0fb653ca2d3203ac1"
    instance_type = "t2.micro"
    security_groups = [aws_security_group.instance.id]

    user_data = <<-EOF
    #!/bin/bash
    echo "Hello, World. Welcome to the use of Terraform in deploying infrastructure" > index.html
    nohup busybox httpd -f -p ${var.server_port} &
    EOF

    lifecycle {
      create_before_destroy = true
    }
}
Enter fullscreen mode Exit fullscreen mode

Notice that the port in the user data script has been updated. The create_before_destroy would allow the autoscaling to be created first before destroying our single instance earlier launched.

resource "aws_autoscaling_group" "example" {
  launch_configuration = aws_launch_configuration.webserver.name
  vpc_zone_identifier = data.aws_subnets.default.ids

  target_group_arns = [aws_lb_target_group.webserver.arn]
  health_check_type = "ELB"

  min_size = 2
  max_size = 10

  tag {
    key = "Name"
    value = "tf-example"
    propagate_at_launch = true
  }
}
Enter fullscreen mode Exit fullscreen mode

This block shows that a minimum number of servers that would run as 2 and the maximum as 10. This will ensure that a single point of failure is avoided.

In a future post, we will attach a load balancer to the autoscaling group and test traffic sent to it. Feel free to ask any questions and give feedback on how to improve.

. . . . . .