You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过AWS ALB访问EKS上Next.js应用时持续出现503错误求助

问题:AWS EKS + ALB 部署Next.js应用持续返回503错误

我使用Terraform在AWS上部署基于Docker镜像的Next.js应用,配置了Application Load Balancer(ALB)将流量路由到EKS集群中的应用,但通过ALB的URL访问时,一直收到503 Service Temporarily Unavailable错误。

配置概况

  1. ALB:将端口80的HTTP流量转发到目标组
  2. 目标组:指向运行Next.js应用的EKS工作节点,监听端口3000
  3. EKS:包含Next.js应用的Deployment,以及对应的Service将流量导向Pod

相关Terraform配置

ALB配置(alb.internet_facing.tf)

resource "aws_lb" "internet_facing_alb" {
   name               = "internet-facing-alb"
   internal           = false
   load_balancer_type = "application"
   security_groups    = [aws_security_group.internet_facing_alb_sg.id]
   subnets            = module.vpc.public_subnets
   tags = {
     Environment = "${var.stage}"
   }
}

监听器配置(alb.listener.app_nextjs.tf)

resource "aws_lb_listener" "http_listener" {
   load_balancer_arn = aws_lb.internet_facing_alb.arn
   port              = 80
   protocol          = "HTTP"
   default_action {
     type             = "forward"
     target_group_arn = aws_lb_target_group.nextjs_tg.arn
   }
}

目标组配置(alb.tg.app_nextjs.tf)

resource "aws_lb_target_group" "nextjs_tg" {
   name        = "${var.name}-nextjs-tg"
   target_type = "instance"
   port        = 3000
   protocol    = "HTTP"
   vpc_id      = module.vpc.vpc_id
}

安全组配置

ALB安全组(sg.alb.internet_facing.tf)

# Security Group for Application Load Balancer (Public subnet)
resource "aws_security_group" "internet_facing_alb_sg" {
name        = "${var.stage}-alb-sg"
description = "Security group for Application Load Balancer"
vpc_id      = module.vpc.vpc_id

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

# ingress {
#   from_port   = 443
#   to_port     = 443
#   protocol    = "tcp"
#   cidr_blocks = ["0.0.0.0/0"]
# }

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

tags = {
    Name = "${var.stage}-alb-sg"
}
}

EKS节点安全组(sg.k8s.eks.wk.node.tf)

# security_group listening traffic from alb nextjs_container_port
# Security Group for EKS Nodes
resource "aws_security_group" "eks_nodes_sg" {
name        = "${var.stage}-eks-nodes-sg"
description = "Security group for EKS Nodes"
vpc_id      = module.vpc.vpc_id

# Allow inbound traffic from the ALB to the application port (3000)
ingress {
    from_port       = 80                        # Should be the port that the ALB sends traffic to, typically 3000 if that's where your app listens
    to_port         = var.nextjs_container_port # The port your Next.js app is listening on
    protocol        = "tcp"
    security_groups = [aws_security_group.internet_facing_alb_sg.id]
}

# Allow all outbound traffic
egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
}

tags = {
    Name = "${var.stage}-eks-nodes-sg"
}
}

补充EKS配置

EKS Service(deployment/k8s.service.nextjs.tf)

resource "kubernetes_service" "nextjs_service" {
metadata {
    name      = "nextjs-service"
    namespace = "ns-nextjs"  # Correct namespace name
    annotations = {
    "service.beta.kubernetes.io/aws-load-balancer-type"                 = "alb"
    "service.beta.kubernetes.io/aws-load-balancer-backend-protocol"     = "http"
    "service.beta.kubernetes.io/aws-load-balancer-healthcheck-path"     = "/"
    "service.beta.kubernetes.io/aws-load-balancer-healthcheck-port"     = 80
    "service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval" = 30
    "service.beta.kubernetes.io/aws-load-balancer-target-group-arn" = aws_lb_target_group.nextjs_tg.arn
    }
}

spec {
    selector = {
    app = var.nextjs_docker_app_name
    }

    port {
    protocol    = "TCP"
    port        = 80
    target_port = var.nextjs_container_port
    }

    # Uncomment below for SSL
    # port {
    #   protocol    = "TCP"
    #   port        = 443
    #   target_port = var.nextjs_container_port
    #   }

    type = "LoadBalancer"
}
depends_on = [module.eks]
}

EKS Deployment(k8s.app.deployment.nextjs.tf)

resource "kubernetes_deployment" "nextjs_deployment" {
metadata {
    name      = "${var.stage}-nextjs-app"
    namespace = "ns-nextjs" # Correct namespace name
    annotations = {
    "nextjs-docker-image" = var.nextjs_docker_image
    }
}

spec {
    replicas = 2 # var.nextjs_replica_count
    selector {
    match_labels = {
        app = var.nextjs_docker_app_name
    }
    }

    template {
    metadata {
        labels = {
        app = var.nextjs_docker_app_name
        }
    }

    spec {
        container {
        image = var.nextjs_docker_image
        name  = var.nextjs_docker_app_name

        port {
            container_port = var.nextjs_container_port
        }

        resources {
            limits = {
            cpu    = "0.5"
            memory = "512Mi"
            }
            requests = {
            cpu    = "250m"
            memory = "256Mi"
            }
        }

        liveness_probe {
            http_get {
            path = "/"
            port = var.nextjs_container_port
            }
            initial_delay_seconds = 3
            period_seconds        = 3
        }

        readiness_probe {
            http_get {
            path = "/"
            port = var.nextjs_container_port
            }
            initial_delay_seconds = 30
            period_seconds        = 10
        }
        }
    }
    }
}
depends_on = [
    module.eks,
    kubernetes_service.nextjs_service
]

}

问题排查与修复方案

1. 安全组端口范围错误

EKS节点安全组的ingress规则中,from_port = 80与目标组监听的3000端口不匹配,导致ALB的流量被节点安全组拦截。

修复:
将节点安全组的ingress规则的from_port和to_port统一设置为var.nextjs_container_port(即3000):

ingress {
    from_port       = var.nextjs_container_port
    to_port         = var.nextjs_container_port
    protocol        = "tcp"
    security_groups = [aws_security_group.internet_facing_alb_sg.id]
}

2. 目标组与Service的配置冲突

你同时手动创建了instance类型的目标组,又在EKS Service中配置了ALB注解并绑定该目标组,存在两个核心问题:

  • 手动创建的目标组不会自动注册EKS节点的NodePort(Service为LoadBalancer类型时会分配随机NodePort,而非3000)
  • Service注解中指定的健康检查端口为80,与目标组监听的3000端口不匹配,导致健康检查失败

修复二选一:

方案A:保留手动ALB/目标组

  • 修改目标组配置,添加健康检查规则,路径设为/,端口设为var.nextjs_container_port
  • 将EKS Service的type改为NodePort,并将目标组的监听端口改为Service分配的NodePort(或固定NodePort)
  • 手动将EKS工作节点注册到目标组

方案B:通过EKS Service自动生成ALB(推荐)

  • 删除手动创建的aws_lb、aws_lb_listener、aws_lb_target_group资源
  • 调整Service注解,移除aws-load-balancer-target-group-arn,让AWS Load Balancer Controller自动创建ALB和目标组,Kubernetes会自动处理节点/ Pod注册及健康检查

3. 目标组无健康注册目标

ALB返回503的常见原因是目标组中没有健康的后端节点。

验证与修复:

  • 登录AWS控制台,查看目标组的「目标」标签页,确认EKS节点已注册且状态为「健康」
  • 在EKS节点上执行curl localhost:<节点端口>(节点端口为Service的NodePort或容器端口3000),验证Next.js应用是否正常响应
  • 确保Next.js应用的根路径/返回200状态码,检查容器的liveness/readiness探针是否正常通过

内容的提问来源于stack exchange,提问作者kawa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:38:09