AWS ALB ECS health-checks

AWS ALB 502 Bad Gateway: wszystkie cele nie przechodzą weryfikacji stanu. Jak to naprawić

Diagnoza i naprawa błędów ALB 502 Bad Gateway spowodowanych awariami weryfikacji stanu target group - security groups, ścieżki, limity czasu i draining przy wdrożeniach.

·
ALB zwraca 502 Bad Gateway do wszystkich klientów. Target group pokazuje każdy target jako unhealthy. Przyczyna to prawie zawsze jedna z czterech rzeczy: security groups, ścieżka weryfikacji stanu, konfiguracja limitu czasu lub wyrejestrowanie celów podczas wdrożenia. Oto jak zidentyfikować i naprawić każdą z nich.

Objawy

ALB zwraca HTTP 502 na wszystkie żądania. Weryfikacje stanu target group pokazują wszystkie zarejestrowane cele jako unhealthy:

# Sprawdź status zdrowia celów
aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:eu-central-1:123456789012:targetgroup/my-app/abc123

# Wynik pokazuje wszystkie cele jako unhealthy:
# {
#   "TargetHealthDescriptions": [
#     {
#       "Target": { "Id": "10.0.1.42", "Port": 8080 },
#       "TargetHealth": {
#         "State": "unhealthy",
#         "Reason": "Target.ResponseCodeMismatch",
#         "Description": "Health checks failed with these codes: [503]"
#       }
#     }
#   ]
# }

# CloudWatch pokazuje skok ELB 5xx
aws cloudwatch get-metric-statistics \
  --namespace AWS/ApplicationELB \
  --metric-name HTTPCode_ELB_502_Count \
  --dimensions Name=LoadBalancer,Value=app/my-alb/abc123 \
  --start-time 2026-07-07T08:00:00Z \
  --end-time 2026-07-07T09:00:00Z \
  --period 60 \
  --statistics Sum

Sama aplikacja może działać prawidłowo - problem polega na tym, że ALB nie może potwierdzić zdrowia celów i usuwa je wszystkie z rotacji.

Przyczyna

ALB wymaga co najmniej jednego zdrowego celu, by przekazywać ruch. Gdy wszystkie cele nie przechodzą weryfikacji stanu, zwraca 502. Cztery najczęstsze przyczyny:

  • Błędna konfiguracja security groups. Security group ALB może dotrzeć do celów na porcie weryfikacji stanu, ale security group celu nie zezwala na ruch przychodzący z SG ALB-a. Ruch z ALB jest blokowany zanim dotrze do aplikacji.
  • Ścieżka weryfikacji stanu zwraca kod inny niż 200. Skonfigurowana ścieżka (/health, / lub inna) zwraca 4xx lub 5xx. Dzieje się tak gdy aplikacja wymaga uwierzytelnienia na endpoincie weryfikacji stanu, gdy ścieżka nie istnieje lub gdy aplikacja nie zakończyła startu.
  • Zbyt krótki timeout weryfikacji stanu. Timeout jest krótszy niż czas odpowiedzi aplikacji pod obciążeniem. ALB oznacza cele jako unhealthy bo odpowiadają zbyt wolno, nie dlatego że nie działają.
  • Wyrejestrowanie celów podczas wdrożeń. ECS lub ASG wycofuje stare cele zanim nowe przejdą weryfikacje stanu. Jeśli deregistration_delay jest zbyt krótki lub czas startu nowego zadania zbyt długi, pojawia się okno w którym nie istnieje żaden zdrowy target.

Rozwiązanie

Krok 1: Zweryfikuj łączność security groups

ALB musi mieć możliwość dotarcia do celów na porcie weryfikacji stanu. Sprawdź obie security groups:

# Znajdź security group ALB
aws elbv2 describe-load-balancers \
  --names my-alb \
  --query 'LoadBalancers[0].SecurityGroups'

# Znajdź security group celów (zadania ECS lub instancje EC2)
aws ec2 describe-security-groups \
  --group-ids sg-target123 \
  --query 'SecurityGroups[0].IpPermissions'

SG celu musi zezwalać na ruch przychodzący z SG ALB-a na porcie celu:

# Terraform: prawidłowe reguły security group

resource "aws_security_group" "alb" {
  name   = "alb-sg"
  vpc_id = var.vpc_id

  egress {
    from_port       = var.container_port
    to_port         = var.container_port
    protocol        = "tcp"
    security_groups = [aws_security_group.ecs_tasks.id]
  }
}

resource "aws_security_group" "ecs_tasks" {
  name   = "ecs-tasks-sg"
  vpc_id = var.vpc_id

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

Krok 2: Napraw ścieżkę weryfikacji stanu i oczekiwane kody

Upewnij się, że ścieżka weryfikacji stanu istnieje i zwraca 200 bez uwierzytelnienia:

# Przetestuj endpoint weryfikacji stanu bezpośrednio z bastiona lub z wnętrza VPC
curl -v http://10.0.1.42:8080/health
# Musi zwrócić HTTP 200 z ciałem odpowiedzi

Jeśli aplikacja zwraca 204 lub inne kody sukcesu, zaktualizuj matcher:

resource "aws_lb_target_group" "app" {
  name     = "my-app-tg"
  port     = 8080
  protocol = "HTTP"
  vpc_id   = var.vpc_id

  health_check {
    enabled             = true
    path                = "/health"
    port                = "traffic-port"
    protocol            = "HTTP"
    matcher             = "200-299"
    interval            = 30
    timeout             = 10
    healthy_threshold   = 2
    unhealthy_threshold = 3
  }
}

Krok 3: Dostosuj limity czasu dla wolno startujących aplikacji

Jeśli aplikacja potrzebuje czasu na start (JVM, rozbudowane dependency injection):

resource "aws_lb_target_group" "app" {
  # ...

  health_check {
    path                = "/health"
    interval            = 30
    timeout             = 15
    healthy_threshold   = 2
    unhealthy_threshold = 5  # Pozwól na więcej niepowodzeń podczas startu
  }
}

Dla ECS skonfiguruj również grace period weryfikacji stanu kontenera:

resource "aws_ecs_service" "app" {
  name            = "my-app"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = 2

  health_check_grace_period_seconds = 120  # Daj kontenerom czas na start

  load_balancer {
    target_group_arn = aws_lb_target_group.app.arn
    container_name   = "app"
    container_port   = 8080
  }
}

Krok 4: Zapobiegaj 502 podczas wdrożeń

Ustaw deregistration delay dłuższy niż czas odpływu połączeń i zapewnij, że minimum healthy percent utrzymuje stare cele przy życiu:

resource "aws_lb_target_group" "app" {
  # ...
  deregistration_delay = 120  # Utrzymuj odpływ połączeń przez 2 minuty
}

resource "aws_ecs_service" "app" {
  # ...
  deployment_minimum_healthy_percent = 100  # Utrzymuj stare taski aż nowe będą zdrowe
  deployment_maximum_percent         = 200  # Pozwól na podwójną pojemność podczas wdrożenia

  deployment_circuit_breaker {
    enable   = true
    rollback = true
  }
}

Weryfikacja

Po zastosowaniu poprawek potwierdź, że cele stają się zdrowe:

# 1. Sprawdź zdrowie celów - wszystkie powinny pokazywać "healthy"
aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:eu-central-1:123456789012:targetgroup/my-app/abc123 \
  --query 'TargetHealthDescriptions[*].TargetHealth.State'
# Oczekiwane: ["healthy", "healthy"]

# 2. Zweryfikuj, że ALB zwraca 200, nie 502
curl -s -o /dev/null -w "%{http_code}" https://my-app.example.com/health
# Oczekiwane: 200

# 3. Potwierdź brak błędów ELB 502 w CloudWatch
aws cloudwatch get-metric-statistics \
  --namespace AWS/ApplicationELB \
  --metric-name HTTPCode_ELB_502_Count \
  --dimensions Name=LoadBalancer,Value=app/my-alb/abc123 \
  --start-time "$(date -u -d '5 minutes ago' +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --period 60 \
  --statistics Sum
# Oczekiwane: 0

# 4. Przetestuj, że wdrożenie nie powoduje 502
aws ecs update-service --cluster main --service my-app --force-new-deployment
# Monitoruj: brak skoków 502 podczas wdrożenia

Błędy ALB 502 podczas wdrożeń lub skalowania to nie tylko uciążliwość - to utracone przychody. Każde żądanie, które trafia na 502, to klient widzący stronę błędu. Naprawa nie jest skomplikowana, ale wymaga poprawnej konfiguracji wszystkich czterech warstw jednocześnie (reguły SG, konfiguracja weryfikacji stanu, limity czasu, strategia wdrożenia). Jedna źle skonfigurowana warstwa wystarczy, by położyć całą usługę.

 

Jerzy Kopaczewski

Potrzebujesz wdrożeń bez przestojów na AWS ECS?

Umów bezpłatną 30-minutową rozmowę. Projektujemy architektury ALB + ECS z prawidłowymi weryfikacji stanumi, wdrożeniami blue-green i circuit breakerami.