이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- 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 -> appDNS와 TLS가 통과해도 listener rule이 틀리면 다른 target group으로 간다. target이 healthy여도 app dependency가 죽으면 실제 API는 실패한다. 반대로 target이 unhealthy면 앱은 정상이어도 LB가 트래픽을 보내지 않는다.
Status Code 해석
| 사용자 증상 | 우선 확인 |
|---|---|
| 502 | target connection reset, protocol mismatch, bad gateway |
| 503 | healthy target 없음, capacity, rule target 없음 |
| 504 | target response timeout, idle timeout |
| 301/302 loop | HTTPS redirect, forwarded proto |
| 특정 path 404 | listener 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/healthAWS CLI가 가능하면 target health를 확인한다.
aws elbv2 describe-target-health \
--target-group-arn arn:aws:elasticloadbalancing:region:acct:targetgroup/name/idlistener 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_codetarget_status_coderequest_processing_timetarget_processing_timeresponse_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_code와target_status_code를 나눠 보는 이유는 무엇인가?
- 오류를 LB가 만들었는지 target app이 만들었는지 구분하기 위해서다.
- Target이 healthy인데 실제 API가 실패할 수 있는 이유는 무엇인가?
- health check path가 실제 API보다 얕거나 다른 dependency, path, host, auth 조건을 사용하기 때문이다.
- Cloud LB 장애 제보에 백엔드가 준비해야 할 최소 증거는 무엇인가?
- 발생 시각, URL/method, request id, client 영향 범위, 앱 로그 도달 여부, 최근 배포/설정 변경 정보다.