← 아티클 목록

로드밸런서 헬스체크 실패 진단 — 502·간헐 장애 잡기

2026-12-14#networking#로드밸런서#트러블슈팅

로드밸런서 뒤 인스턴스가 멀쩡히 떠 있는데 LB는 unhealthy로 빼버리고 502가 납니다. "서버는 살아 있다"와 "LB가 죽었다고 본다" 사이의 간극이 헬스체크입니다. LB가 어떤 요청을 보내고 무엇을 기대하는지를 그대로 재현하면 원인이 좁혀집니다.

먼저 백엔드를 직접 친다

LB를 거치지 말고, LB가 보는 그대로 인스턴스에 직접 헬스체크 경로를 호출합니다.

로컬 또는 서버
curl -v http://10.0.1.23:8080/health

LB 설정의 경로·포트·프로토콜을 똑같이 맞추는 게 핵심입니다. 여기서 결과가 갈립니다.

직접 호출 결과의미1순위 점검
200 정상앱은 정상, LB→백엔드 경로 문제보안그룹·서브넷·포트
Connection refused그 포트에 안 들음리슨 포트·바인드 주소
404 / 503경로·앱 상태 문제헬스체크 경로·앱 로그
응답 느림(>타임아웃)타임아웃 초과로 fail헬스체크 타임아웃·앱 지연

원인별 해결

① 200인데 LB는 unhealthy — 앱은 정상이니 LB→백엔드 경로가 막힌 겁니다. 보안그룹/방화벽이 LB의 헬스체크 소스를 허용하는지 봅니다.

로컬 터미널
ss -tlnp | grep :8080         # 0.0.0.0 인가 127.0.0.1 인가

127.0.0.1:8080으로 바인드돼 있으면 외부(LB)에서는 못 닿습니다. 0.0.0.0으로 띄워야 합니다.

② Connection refused — 헬스체크 포트와 앱 리슨 포트가 다른 전형적 케이스. LB 타깃 포트와 ss 출력의 포트를 맞춥니다.

③ 404 / 503 — 헬스체크 경로가 틀렸거나(/health 없는데 호출), 앱이 의존성(DB) 끊겨 503을 반환. 앱 로그를 봅니다.

④ 간헐적 fail — 가장 까다롭습니다. 응답이 가끔 헬스체크 타임아웃을 넘기는 경우입니다. 헬스체크가 무거운 경로(DB 조회 포함)를 치고 있지 않은지, 임계값(connection 수, GC)이 없는지 봅니다.

로컬 터미널
for i in $(seq 20); do curl -o /dev/null -s -w "%{http_code} %{time_total}\n" http://10.0.1.23:8080/health; done

응답 시간이 들쭉날쭉하면 타임아웃을 늘리기 전에 헬스체크 경로를 가볍게(의존성 없는 /healthz) 만드는 게 먼저입니다.

진단 순서 체크리스트

로컬 또는 서버
curl -v http://<backend-ip>:<port>/<health-path>   # 백엔드 직접 호출
ss -tlnp | grep :<port>                             # 리슨 포트·바인드 주소
# LB 타깃 포트 == 앱 리슨 포트 인가
# 헬스체크 경로가 앱에 실제로 존재하는가
# 보안그룹이 LB 소스를 허용하는가
# 헬스체크 타임아웃 > 앱 응답 시간 인가

unhealthy 판정의 90%는 "직접 호출하면 보이는" 포트·경로·바인드 주소 불일치입니다.


LB 헬스체크 경로·포트·타임아웃을 직접 끊어보며 502를 재현·진단하는 실습은 네트워크 트랙에서 회원가입 없이 무료로 할 수 있습니다.