skip to Main Content

I am trying to achieve setup shown in AWS doc (excluding Elastic IP because I am a bit scared to miss conditions described here to avoid possible charges in my Free Tier account) but so far I am only getting 502 Bad Gateway and not sure what I am missing/doing wrong. Although both instance check are successful ("System reachability check passed" and "Instance reachability check passed"), related Target Groups are "Unhealthy". Any is much appreciated.

Note: I am not experienced in AWS infra setup (nor terraform) but this is best I could produce after going through resources online.

terraform {
  required_version = "~> 1.4.4"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.30.0"
    }
  }
}

provider "aws" {
  profile = "development"
  region  = local.region
}

# -- VARS ----------------------------------------------------------------------

locals {
  public_key = "/Users/you/.ssh/api_rsa.pub"

  project = "api"

  region = "eu-west-1"

  vpc_cidr = "10.0.0.0/16"

  public_subnets = {
    "a1" = {
      az   = "${local.region}a"
      cidr = "10.0.10.0/24"
    },
    "b1" = {
      az   = "${local.region}b"
      cidr = "10.0.20.0/24"
    }
  }

  private_subnets = {
    "a1" = {
      az   = "${local.region}a"
      cidr = "10.0.135.0/24"
    },
    "b1" = {
      az   = "${local.region}b"
      cidr = "10.0.145.0/24"
    }
  }

  ec2_ami           = "ami-0fb2f0b847d44d4f0" // Amazon Linux 2023 AMI 2023.1.20230705.0 x86_64 HVM kernel-6.1
  ec2_instance_type = "t2.micro"
}

# -- VPC -----------------------------------------------------------------------

resource "aws_vpc" "vpc" {
  cidr_block           = local.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name = local.project
  }
}

# -- ROUTE TABLE ---------------------------------------------------------------

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "${local.project}-pub"
  }
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "${local.project}-prv"
  }
}

# -- INTERNET GATEWAY ----------------------------------------------------------

resource "aws_internet_gateway" "public" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = local.project
  }
}

resource "aws_route" "public" {
  destination_cidr_block = "0.0.0.0/0"
  route_table_id         = aws_route_table.public.id
  gateway_id             = aws_internet_gateway.public.id
}

# -- SUBNET --------------------------------------------------------------------

resource "aws_subnet" "public" {
  for_each = local.public_subnets

  vpc_id            = aws_vpc.vpc.id
  cidr_block        = each.value.cidr
  availability_zone = each.value.az

  tags = {
    Name = "${local.project}-pub-${each.key}"
  }
}

resource "aws_subnet" "private" {
  for_each = local.private_subnets

  vpc_id            = aws_vpc.vpc.id
  cidr_block        = each.value.cidr
  availability_zone = each.value.az

  tags = {
    Name = "${local.project}-prv-${each.key}"
  }
}

resource "aws_route_table_association" "public" {
  for_each = local.public_subnets

  subnet_id      = aws_subnet.public[each.key].id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "private" {
  for_each = local.private_subnets

  subnet_id      = aws_subnet.private[each.key].id
  route_table_id = aws_route_table.private.id
}

# -- SECURITY GROUP ------------------------------------------------------------

resource "aws_security_group" "load_balancer" {
  name        = "${local.project}-load-balancer"
  description = "Allow all inbound traffic from Internet and outbound traffic from ELB"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    description = "Internet > ELB"
    from_port   = "80"
    to_port     = "80"
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    description = "ELB > Internet"
    from_port   = "0"
    to_port     = "0"
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "ec2" {
  name        = "${local.project}-ec2"
  description = "Allow all inbound traffic from ELB/SSH and outbound traffic from EC2"
  vpc_id      = aws_vpc.vpc.id

  ingress {
    description     = "ELB > EC2"
    from_port       = "0"
    to_port         = "0"
    protocol        = "-1"
    security_groups = [aws_security_group.load_balancer.id]
  }

  ingress {
    description = "SSH > EC2"
    from_port   = "22"
    to_port     = "22"
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    description = "EC2 > ELB/SSH"
    from_port   = "0"
    to_port     = "0"
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# -- EC2 -----------------------------------------------------------------------

resource "aws_key_pair" "ssh" {
  key_name   = "${local.project}-rsa"
  public_key = file(local.public_key)
}

resource "aws_instance" "ec2" {
  for_each = local.private_subnets

  ami                         = local.ec2_ami
  instance_type               = local.ec2_instance_type
  subnet_id                   = aws_subnet.private[each.key].id
  vpc_security_group_ids      = [aws_security_group.ec2.id]
  key_name                    = aws_key_pair.ssh.key_name
  associate_public_ip_address = true # Do I need this enabled for EC2s in private subnet?

  user_data = <<-EOF
#!/bin/bash
sudo su
yum update -y
yum install httpd -y
service httpd start
chkconfig httpd on
echo "<html><body>Private subnet ${each.key}</body></html>" > /var/www/html/index.html
  EOF

  tags = {
    Name = "${local.project}-ec2-prv-subnet-${each.key}"
  }
}

# -- LOAD BALANCER -------------------------------------------------------------

resource "aws_lb" "application" {
  name = "${local.project}-application-load-balancer"

  load_balancer_type = "application"
  security_groups    = [aws_security_group.load_balancer.id]
  subnets            = [for sub in aws_subnet.public : sub.id]
}

resource "aws_lb_target_group" "application" {
  name = "${local.project}-http-application"

  port                          = 80
  protocol                      = "HTTP"
  vpc_id                        = aws_vpc.vpc.id
  load_balancing_algorithm_type = "least_outstanding_requests"
}

resource "aws_lb_target_group_attachment" "ec2" {
  for_each = aws_instance.ec2

  port             = 80
  target_id        = each.value.id
  target_group_arn = aws_lb_target_group.application.arn
}

resource "aws_lb_listener" "application" {
  load_balancer_arn = aws_lb.application.arn
  port              = "80"
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.application.arn
  }

  tags = {
    Name = "${local.project}-application-load-listener"
  }
}

2

Answers


  1. Port 80 is going to be blocked by Amazon Linux by default. You’ll need to add this commend to the EC2 instance’s user-data script to open port 80 in the Linux firewall:

    iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT
    
    Login or Signup to reply.
  2. It seems you are encountering a 502 Bad Gateway error while trying to set up an infrastructure on AWS, following the AWS documentation. You have mentioned that both instance checks ("System reachability check passed" and "Instance reachability check passed") are successful, but the related Target Groups are showing as "Unhealthy." You’re seeking assistance to identify what might be causing this issue.

    Based on the provided information, it appears you are using Terraform to define your infrastructure as code. The configuration you shared includes the required version of Terraform, the AWS provider details, and some variable declarations for your project, region, VPC, and subnets.

    To troubleshoot the 502 Bad Gateway error and the unhealthy Target Groups, there are several potential factors to consider:

    1. Security Group Configuration: Ensure that the security groups associated with your instances allow the necessary inbound and outbound traffic for your application. Verify that the appropriate ports are open, and security group rules are correctly configured.

    2. Load Balancer Configuration: Double-check the settings of your load balancer, including listener configurations, target group associations, health checks, and security group settings. Make sure the load balancer is properly routing traffic to the instances.

    3. Health Checks: Verify the health check settings for your target groups. Ensure that the health check path, protocol, and timeout values align with your application’s actual behavior. Adjust the health check settings if necessary.

    4. Instance Configuration: Review the instance configuration, including the operating system, software installed, and any custom scripts or configurations. Ensure that your instances are running the expected services and are properly set up to handle incoming requests.

    5. Application Configuration: Check your application’s configuration files or code for any specific settings related to networking or load balancing. Ensure that your application is correctly configured to handle requests coming through the load balancer.

    6. Logging and Monitoring: Enable logging and monitoring features provided by AWS to gain insights into the health and performance of your instances, load balancer, and target groups. This can help identify any potential issues or bottlenecks.

    Considering your limited experience in AWS infrastructure setup and Terraform, it might be helpful to refer to additional resources and documentation specific to your use case. The AWS documentation provides detailed guides and troubleshooting steps for setting up load balancers and troubleshooting common issues.

    Remember to follow best practices and always consider security measures when deploying infrastructure in AWS. If you are concerned about possible charges, it’s advisable to review the AWS Free Tier guidelines and ensure you are within the limits to avoid any unexpected expenses.

    If you encounter any specific errors, log messages, or additional details, providing them would assist in further diagnosing the issue.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search