My issue is about making a calls to API that is written in Next.js app. The Web app is on the same task of Next.js app. My aplication is deployed to AWS ECS with Application Load Balancer and EC2 launch type task. My task has configured network mode with using awsvpc
. I'm able to connect through HTTPS and that's prove that Security Groups are configured well.
The egress rules are set up for any protocol and any port. While using pages were are made a calls to Next.js API, I'm receiving 504 Gateway Timeout.
Infrastructure has been uploaded using Terraform and I have created VPC and networking stuff also using terraform. The requests are also communicating with Cognito and DynamoDB but IAM policies are added to IAM Task Role
Do you have any ideas what could be an issue?
I have tried checking routing table rules with Internet Gateway and it still doesn't help.
EDIT: Here is my terraform code. I'm using HTTPS connection with certificate generated in AWS ACM
#####
# VPC and subnets
#####
data "aws_vpc" "default_vpc" {
default = true
}
data "aws_subnets" "all_default_subnets" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default_vpc.id]
}
}
#####
# ALB
#####
resource "aws_lb" "alb" {
name = "alb"
load_balancer_type = "application"
security_groups = [ aws_security_group.alb.id ]
subnets = data.aws_subnets.all_default_subnets.ids
enable_deletion_protection = false
}
resource "aws_lb_target_group" "lb_target_group" {
name = "target-alb-name"
port = "80"
protocol = "HTTP"
vpc_id = data.aws_vpc.default_vpc.id
target_type = "ip"
health_check {
healthy_threshold = "3"
interval = "10"
path = "/api/health"
protocol = "HTTP"
unhealthy_threshold = "3"
}
}
resource "aws_lb_listener" "alb_80" {
load_balancer_arn = aws_lb.alb.arn
port = "443"
protocol = "HTTPS"
# My certificate generated from terraform level
certificate_arn = aws_acm_certificate.loadbalancer_cert.arn
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.lb_target_group.arn
}
tags = {
environment = "prod"
}
}
##############################################################
# AWS ECS-SERVICE
##############################################################
resource "aws_ecs_service" "service" {
cluster = aws_ecs_cluster.cluster.id
desired_count = 1
launch_type = "EC2"
name = "service"
task_definition = aws_ecs_task_definition.task_definition.arn
force_new_deployment = true
deployment_minimum_healthy_percent = 0
network_configuration {
subnets = data.aws_subnets.all_default_subnets.ids
security_groups = [aws_security_group.ecs_tasks.id]
assign_public_ip = false
}
load_balancer {
container_name = "ecs-container"
container_port = 3000
target_group_arn = aws_lb_target_group.lb_target_group.arn
}
depends_on = [aws_lb_listener.alb_80]
}
############################################################
# AWS ECS-TASK
############################################################
resource "aws_ecs_task_definition" "task_definition" {
container_definitions = data.template_file.task_definition_json.rendered
execution_role_arn = var.execution_task_role_arn
family = "web-task"
network_mode = "awsvpc"
cpu = "128"
memory = "256"
requires_compatibilities = ["EC2"]
task_role_arn = var.prod_task_role_arn
}
data "template_file" "task_definition_json" {
template = file("${path.module}/task_definition.json")
vars = {
BASE_URL = var.BASE_URL,
APP_AWS_REGION = var.APP_AWS_REGION,
COGNITO_WEB_CLIENT_ID = var.COGNITO_WEB_CLIENT_ID,
COGNITO_USER_POOL_ID = var.COGNITO_USER_POOL_ID,
AWS_ACCESS_KEY_ID = var.AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY = var.AWS_SECRET_ACCESS_KEY,
DYNAMODB_TABLE_NAME = var.DYNAMODB_TABLE_NAME,
COGNITO_REGION = var.COGNITO_REGION,
}
}
###########################################################
# AWS ECS-EC2
###########################################################
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "~> 4.3.0"
name = "ec2-instance"
create_spot_instance = false
iam_instance_profile = aws_iam_instance_profile.ecs_agent.name
user_data = data.template_file.user_data.rendered
ami = var.prod_ami_id
instance_type = var.prod_instance_type
key_name = "key-pairs"
monitoring = true
vpc_security_group_ids = [aws_security_group.ecs_tasks.id]
subnet_id = data.aws_subnets.all_default_subnets.ids[0]
root_block_device = [
{
volume_type = "gp3"
volume_size = 30
delete_on_termination = true
}
]
tags = {
environment = "prod"
}
}
data "template_file" "user_data" {
template = file("${path.module}/user_data.tpl")
}
resource "aws_security_group" "ecs_tasks" {
name = "sg-ecs-tasks"
vpc_id = data.aws_vpc.default_vpc.id
ingress {
protocol="tcp"
from_port=3000
to_port=3000
cidr_blocks=["0.0.0.0/0"]
}
ingress {
protocol="tcp"
from_port=443
to_port=443
cidr_blocks=["0.0.0.0/0"]
}
ingress {
protocol="tcp"
from_port=80
to_port=80
cidr_blocks=["0.0.0.0/0"]
}
egress {
protocol="-1"
from_port=0
to_port=0
cidr_blocks=["0.0.0.0/0"]
}
}
#####
# Security Group Config
#####
resource "aws_security_group" "ecs_tasks" {
name = "sg-ecs-tasks"
vpc_id = data.aws_vpc.default_vpc.id
ingress {
protocol="tcp"
from_port=3000
to_port=3000
cidr_blocks=["0.0.0.0/0"]
}
ingress {
protocol="tcp"
from_port=443
to_port=443
cidr_blocks=["0.0.0.0/0"]
}
ingress {
protocol="tcp"
from_port=80
to_port=80
cidr_blocks=["0.0.0.0/0"]
}
egress {
protocol="-1"
from_port=0
to_port=0
cidr_blocks=["0.0.0.0/0"]
}
}
resource "aws_security_group" "alb" {
name = "sg-alb"
vpc_id = data.aws_vpc.default_vpc.id
ingress {
protocol="tcp"
from_port=3000
to_port=3000
cidr_blocks=["0.0.0.0/0"]
}
ingress {
protocol="tcp"
from_port=443
to_port=443
cidr_blocks=["0.0.0.0/0"]
}
ingress {
protocol="tcp"
from_port=80
to_port=80
cidr_blocks=["0.0.0.0/0"]
}
egress {
protocol="-1"
from_port=0
to_port=0
cidr_blocks=["0.0.0.0/0"]
}
}
user_data for EC2 instance
#!/bin/bash
cat <<'EOF' >> /etc/ecs/ecs.config
ECS_CLUSTER=ecs-cluster
ECS_ENABLE_SPOT_INSTANCE_DRAINING=true
ECS_ENABLE_CONTAINER_METADATA=true
ECS_AVAILABLE_LOGGING_DRIVERS=["json-file","awslogs"]
ECS_IMAGE_PULL_BEHAVIOR=always
EOF
yum update -y yum install -y httpd sudo systemctl start httpd sudo systemctl enable httpd