이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.

  • Cloud LB 502/503/504를 listener, rule, target group, target health, network path로 어떻게 분리하는가?
  • AWS ALB 같은 managed LB에서 access log와 target health reason을 어떻게 읽는가?
  • 인프라 팀과 LB 장애를 논의할 때 백엔드가 어떤 증거를 준비해야 하는가?

개요

Cloud LB는 managed 서비스라서 직접 프로세스를 볼 수 없지만, 대신 listener/rule/target group/health/access log/metric을 읽어야 한다. 백엔드 개발자는 콘솔의 “healthy” 표시만 보지 말고, 사용자의 요청이 어떤 rule과 target으로 갔고 target이 어떤 status를 반환했는지 확인할 수 있어야 한다.

  • Listener는 port/protocol/certificate 진입점이다.
  • Rule은 Host/Path/Header 조건에 따라 target group을 고른다.
  • Target health는 LB가 target으로 보낼 수 있다고 판단하는 상태다.
  • Access log는 LB status와 target status를 분리해 준다.
  • Security group, subnet, NACL, route table은 LB-to-target 경로를 막을 수 있다.

원리

Cloud LB 장애는 다음 축으로 분리한다.

Client -> DNS -> LB listener -> rule -> target group -> target network -> app

DNS와 TLS가 통과해도 listener rule이 틀리면 다른 target group으로 간다. target이 healthy여도 app dependency가 죽으면 실제 API는 실패한다. 반대로 target이 unhealthy면 앱은 정상이어도 LB가 트래픽을 보내지 않는다.

Status Code 해석

사용자 증상우선 확인
502target connection reset, protocol mismatch, bad gateway
503healthy target 없음, capacity, rule target 없음
504target response timeout, idle timeout
301/302 loopHTTPS redirect, forwarded proto
특정 path 404listener rule/path rewrite
특정 AZ 실패subnet, target health, zone imbalance

Cloud provider별 의미가 다를 수 있으므로 provider access log 필드를 기준으로 확인한다.

코드와 명령으로 확인하기

사용자 관점에서 timing을 본다.

curl -o /dev/null -s -w 'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} first_byte=%{time_starttransfer} total=%{time_total} code=%{http_code}\n' \
  https://api.example.com/health

AWS CLI가 가능하면 target health를 확인한다.

aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:region:acct:targetgroup/name/id

listener rule도 확인한다.

aws elbv2 describe-rules \
  --listener-arn arn:aws:elasticloadbalancing:region:acct:listener/app/name/id/listener-id

권한이 없다면 인프라 팀에 같은 출력과 발생 시각의 access log 샘플을 요청한다.

Access Log에서 볼 것

AWS ALB access log 기준으로는 대략 다음 축이 중요하다.

  • elb_status_code
  • target_status_code
  • request_processing_time
  • target_processing_time
  • response_processing_time
  • target IP/port
  • trace id

LB가 503을 만들고 target status가 -이면 target까지 가지 않았을 수 있다. target status가 500이면 앱이 응답한 것이다. 이 차이가 장애 소유권을 빠르게 좁힌다.

Target Health Reason

Target unhealthy reason은 매우 중요하다.

  • health check timeout
  • health check status mismatch
  • target not registered
  • target deregistration/draining
  • security group/network unreachable
  • TLS/protocol mismatch

health check가 실패했다면 health path를 curl로 직접 확인하고, app access log에 health request가 도달했는지 본다.

인프라 협업 포인트

  • 백엔드는 발생 시각, URL, method, request id, client region/IP 대역, user agent, 앱 로그 도달 여부를 제공한다.
  • 인프라는 listener/rule, target group, target health reason, access log, LB metric, security group 변경을 제공한다.
  • 양쪽이 같은 시간대와 timezone을 써야 한다.
  • 권한이 없어 콘솔을 못 보는 백엔드도 어떤 로그 필드가 필요한지 이름을 알고 요청해야 한다.

실전 팁

  • CloudWatch/monitoring에서 LB 5xx와 target 5xx를 나눠 알람을 둔다. 전자는 LB가 만든 오류, 후자는 target이 만든 오류에 가깝다.
  • health check는 target 상태 판단용이고 synthetic monitoring은 사용자 기능 판단용이다. 둘 다 필요하다.
  • security group 변경, 인증서 교체, listener rule 변경은 앱 배포 없이도 장애를 만든다.
  • 개인 프로젝트에서도 managed LB를 쓰면 access log 저장을 켜고 보관 기간을 정한다.
  • “콘솔 healthy”만으로 장애가 없다고 말하지 않는다. 사용자 path와 target health path가 다를 수 있다.

위험 신호!

  • LB access log가 꺼져 있다.
  • target health reason을 보지 않고 앱만 재시작한다.
  • listener rule 변경에 smoke test가 없다.
  • LB 5xx와 target 5xx가 같은 alert로만 묶여 있다.

확인 질문

확인 질문

  • LB access log에서 elb_status_codetarget_status_code를 나눠 보는 이유는 무엇인가?
    • 오류를 LB가 만들었는지 target app이 만들었는지 구분하기 위해서다.
  • Target이 healthy인데 실제 API가 실패할 수 있는 이유는 무엇인가?
    • health check path가 실제 API보다 얕거나 다른 dependency, path, host, auth 조건을 사용하기 때문이다.
  • Cloud LB 장애 제보에 백엔드가 준비해야 할 최소 증거는 무엇인가?
    • 발생 시각, URL/method, request id, client 영향 범위, 앱 로그 도달 여부, 최근 배포/설정 변경 정보다.

참고 문서