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

API Gateway V2与ALB私有集成持续返回503故障排查求助

问题排查:API Gateway V2与ALB私有集成无流量到达ALB

问题背景

已通过Terraform完成API Gateway V2与内部Application Load Balancer(ALB)的VPC Link私有集成部署,所有资源状态显示正常:

  • VPC Link状态正常
  • ALB目标组健康检查通过
  • 自定义Lambda授权器返回正确响应(API Gateway日志可佐证)
  • API Gateway的路由、授权器、集成配置关联无误

但请求始终无法到达ALB:S3中无ALB访问日志/连接日志,VPC流日志也未记录进入ALB的流量。

配置代码

resource "aws_apigatewayv2_vpc_link" "alb_connection" {
  name               = "${local.full_name}-vpc-link"
  security_group_ids = [aws_security_group.alb_sg.id]
  subnet_ids         = data.aws_subnets.web.ids
  tags               = module.network_label.tags
}

resource "aws_cognito_resource_server" "alb_connection" {
  identifier = "${var.environment}.${var.area}.${var.application}"
  name       = "${var.environment}-${local.full_name}-rs"

  dynamic "scope" {
    for_each = var.scopes

    content {
      scope_name        = scope.value
      scope_description = "Allow ${scope.value} access to ${local.full_name}/${var.area}"
    }
  }

  user_pool_id = one(data.aws_cognito_user_pools.selected.ids)
}

resource "aws_apigatewayv2_authorizer" "alb_connection" {
  name             = "http-api-request-authorizer"
  api_id           = data.aws_apigatewayv2_api.gateway.id
  authorizer_type  = "REQUEST"
  identity_sources = ["$request.header.Authorization"]
  authorizer_uri   = data.aws_lambda_function.authorizer.invoke_arn

  enable_simple_responses           = true
  authorizer_payload_format_version = "2.0"
}

resource "aws_apigatewayv2_route" "alb_connection" {
  api_id    = data.aws_apigatewayv2_api.gateway.id
  route_key = "ANY /${var.area}/{proxy+}"
  target    = "integrations/${aws_apigatewayv2_integration.alb_connection.id}"

  authorizer_id      = aws_apigatewayv2_authorizer.alb_connection.id
  authorization_type = "CUSTOM"
  # authorization_scopes = ["${aws_cognito_resource_server.alb_connection.identifier}/${each.value}"]
}

resource "aws_apigatewayv2_integration" "alb_connection" {
  api_id                 = data.aws_apigatewayv2_api.gateway.id
  description            = "Integration connecting ${var.api_gateway_name} to ${local.full_name}"
  integration_type       = "HTTP_PROXY"
  integration_uri        = aws_lb_listener.this.arn
  payload_format_version = "1.0" # Required for HTTP_PROXY integrations (private integrations)

  integration_method = "ANY"
  connection_type    = "VPC_LINK"
  connection_id      = aws_apigatewayv2_vpc_link.alb_connection.id

  request_parameters = {
    "append:header.authforintegration" = "$context.authorizer.authorizerResponse"
  }

  response_parameters {
    status_code = 403
    mappings = {
      "append:header.auth" = "$context.authorizer.authorizerResponse"
    }
  }
}

resource "aws_lb" "alb" {

  # Set the basic fields of the load balancer
  name                       = "${local.full_name}-alb-${random_string.id.result}"
  internal                   = true
  load_balancer_type         = "application"
  enable_deletion_protection = false
  security_groups            = [aws_security_group.alb_sg.id]
  subnets                    = data.aws_subnets.web.ids

  # Setup logging for access
  access_logs {
    bucket  = data.aws_s3_bucket.audit.id
    prefix  = local.full_path
    enabled = true
  }

  # Setup connection logs
  connection_logs {
    bucket  = data.aws_s3_bucket.audit.id
    prefix  = local.full_path
    enabled = true
  }

  tags = module.alb_group_label.tags

  # Ensure a new instance of this load balancer is created before the old one is destroyed to avoid downtime
  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_s3_bucket_policy" "allow_log_access" {
  bucket = data.aws_s3_bucket.audit.id
  policy = data.aws_iam_policy_document.alb_access_policy.json
}

resource "aws_lb_target_group" "target_group" {
  name        = "${local.full_name}-tg-${random_string.id.result}"
  target_type = "ip"
  protocol    = "HTTP"
  port        = var.service_port
  vpc_id      = data.aws_vpc.main.id

  tags = module.alb_group_label.tags

  slow_start = var.slow_start
  health_check {
    enabled             = true
    port                = var.service_port
    interval            = 30
    timeout             = 5
    protocol            = "HTTP"
    path                = var.health_check
    matcher             = "200"
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }

  # Ensure a new instance of this target group is created before the old one is destroyed to avoid downtime
  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_lb_listener" "this" {
  load_balancer_arn = aws_lb.alb.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = aws_acm_certificate.ssl_certificate.arn
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.target_group.arn
  }
  tags = module.alb_group_label.tags

  # Need to ensure that the listener is destroyed before the target group or we won't be able to destroy the target
  # group at all.
  lifecycle {
    create_before_destroy = true
    replace_triggered_by = [
      aws_lb_target_group.target_group
    ]
  }
}

可能的原因及解决方法

1. ALB安全组入站规则未放通API Gateway流量

API Gateway通过VPC Link访问ALB时,使用对应区域的execute-api服务IP段。需检查aws_security_group.alb_sg的入站规则:

  • 添加HTTPS(443端口)的入站规则,来源设置为当前区域的com.amazonaws.<region>.execute-api前缀列表(可通过aws ec2 describe-prefix-lists --region <你的区域>获取前缀列表ID,格式为pl-xxxxxx)

2. API Gateway集成的Host头不匹配ALB证书域名

API Gateway默认会将自身域名作为Host头转发给ALB,如果ALB的ACM证书未覆盖该域名,会导致TLS握手失败,流量被丢弃。
修改集成配置,强制设置Host头为ALB的DNS名称:

resource "aws_apigatewayv2_integration" "alb_connection" {
  # ... 其他配置保持不变
  request_parameters = {
    "overwrite:header.Host" = aws_lb.alb.dns_name
    "append:header.authforintegration" = "$context.authorizer.authorizerResponse"
  }
}

3. 路由路径匹配失败

确认请求路径严格匹配路由规则ANY /${var.area}/{proxy+}:

  • 例如var.area为api时,请求路径需为/api/xxx格式
  • 查看API Gateway执行日志,确认请求是否命中目标路由

4. VPC Link子网配置异常

  • 确认VPC Link关联的子网data.aws_subnets.web.ids与ALB子网属于同一VPC
  • 检查子网路由表,确保允许同VPC内的流量互通(默认允许,自定义路由表需验证)
  • 确认子网有足够的可用IP,VPC Link需要在每个子网创建ENI用于流量转发

5. 授权器实际未通过验证

虽然授权器返回响应,需确认其返回的isAuthorized字段为true:

  • 查看API Gateway日志中的授权阶段结果,若isAuthorized为false,API Gateway会直接返回403,不会转发流量到ALB

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:29:53