IL-0264 Healthchecks.io · 2025-11-01networking
Healthchecks.io 의 로드 밸런서가 연결 슬롯을 다 써서 웹사이트와 핑 엔드포인트의 요청이 느려지거나 타임아웃됐다
2025년 11월 1일 23시 30분 UTC 부터 11월 2일 1시 10분 UTC 까지 healthchecks.io 웹사이트와 hc-ping.com 핑 엔드포인트에서 요청이 몇 초씩 걸리거나 타임아웃됐다. Healthchecks.io 는 로드 밸런서의 HAProxy 에서 느슨한 속도 제한을 걸고, 애플리케이션 서버의 NGINX 에서 더 엄격한 속도 제한과 지역 차단을 건다. HAProxy 는 요청이 특히 많은 클라이언트를 tarpit 방식으로 제한하도록 설정돼 있었다. tarpit 은 잠시 기다린 뒤에 HTTP 429 를 보내는 방식이라 그동안 네트워크 소켓 하나가 묶인다. 연결 슬롯이 모자랄 위험을 줄이려고 대기 시간은 1초로 두었다.
11월 1일 23시 24분, 잘못 설정된 클라이언트가 UUID 하나로 보내는 핑을 초당 300건으로 늘렸다. 클라이언트는 tarpit 에도 느려지지 않았다. 요청이 많아 HAProxy 서버가 연결 슬롯 한도에 닿았고, 정상 요청까지 거절했다. 23시 39분에 로드 밸런서 하나가 연결을 거절하다 DNS 응답 목록에서 자동으로 빠지자, 남은 로드 밸런서에 부하가 몰리며 연쇄 반응이 일어났다. 운영자는 0시 11분에 알림을 받고 조사를 시작했다. 1시 6분에는 문제의 IPv4 주소 하나와 IPv6 /64 서브넷을 찾아 이 주소들의 TCP 요청을 거절하도록 로드 밸런서 설정을 바꿨다. 그러자 서비스가 정상으로 돌아왔다. 8시 40분에는 tarpit 대신 바로 HTTP 429 로 응답하도록 속도 제한 설정을 바꿨고, 11월 5일까지 HAProxy 설정과 알림을 더 손봤다.
- 심각도
- –
- 영향 범위
- healthchecks.io website and hc-ping.com ping endpoints: some requests took several seconds or timed out; false monitoring alerts for users
- 영향 사용자
- –
- 지역
- –
- 감지까지
- 41m
- 복구까지
- 1h 40m
증상
Healthchecks.io 의 웹사이트 healthchecks.io 와 핑 엔드포인트 hc-ping.com 에 연결이 간헐적으로 안 됐다. 일부 요청은 끝나는 데 몇 초씩 걸렸고, 어떤 요청은 아예 타임아웃됐다. 운영자는 요란한 알림에 잠에서 깼다.
11월 1일 23시 24분 UTC 부터 UUID 하나로 오는 핑 요청이 초당 10건에서 초당 300건으로 늘어 그대로 이어졌다. 23시 39분에 로드 밸런서 하나가 연결을 거절하기 시작해 DNS 응답 목록에서 자동으로 빠졌다. 그만큼 남은 로드 밸런서에 부하가 몰리면서 연쇄 반응이 시작됐다.
HAProxy 가 이 클라이언트에 걸어 둔 tarpit 속도 제한은 1초를 기다린 뒤에 응답한다. 그런데 클라이언트는 느려지지 않았고, 기다리는 동안 소켓이 묶이면서 HAProxy 가 연결 슬롯 한도에 닿았다. 그 결과 로드 밸런서가 정상 요청까지 거절했다.
Healthchecks.io 사용자에게는 이 사고로 잘못된 모니터링 알림이 갔다. 운영자는 보통 이런 증상이 Healthchecks.io 가 손쓸 수 없는 인프라 문제에서 온다고 봤지만, 이번에는 Healthchecks.io 쪽 문제였다.
원인
- 촉발
- 잘못 설정된 클라이언트가 UUID 하나로 핑 요청을 초당 10건에서 초당 300건으로 늘려 계속 보냈다.
감지
운영자가 11월 2일 0시 11분 UTC 에 요란한 알림에 잠에서 깨어 조사를 시작했다.
조치
- 문제를 일으킨 클라이언트의 IP 주소를 찾았다. IPv4 주소 하나와 IPv6 /64 서브넷이었다.
- 이 주소들에서 오는 TCP 요청을 거절하도록 로드 밸런서 설정을 바꿨고, 서비스가 정상으로 돌아왔다.
후속 조치
- 비슷한 문제를 막으려고 로드 밸런서의 속도 제한 설정을 바꿔 tarpit 방식을 쓰지 않고 바로 HTTP 429 로 응답하게 했다.
- HAProxy 설정에 빠져 있던 timeout http-request 5s 를 넣어 Slowloris 공격을 막게 했다. Slowloris 공격도 연결 슬롯을 바닥낼 수 있고, 하기도 쉽기 때문이다.
- 로드 밸런서에 여유를 더 주려고 HAProxy 설정의 maxconn 값을 올렸다.
- 로드 밸런서의 속도 제한 규칙이 hc-ping.com 뿐 아니라 hchk.io 엔드포인트에도 걸리게 했다.
- HAProxy 프론트엔드의 활성 세션 수가 maxconn 보다 한참 낮은 기준값을 넘으면 알리도록 Netdata 에이전트에 알림 규칙을 더했다.
- 로그를 쓰기 편하도록 HAProxy 로그 형식을 손봤다.
교훈
HAProxy 의 속도 제한 방식은 저마다 장단점이 있다. tarpit 은 요청을 차례로 보내는 클라이언트는 늦출 수 있지만, 클라이언트가 요청을 대량으로 동시에 보내면 로드 밸런서를 오히려 무너뜨릴 수 있다. 운영자는 이번 일을 교훈으로 삼아 속도 제한에 걸린 요청을 deny 방식으로 거절하도록 바꿨다.
출처
관련 사례
같은 원인 · 공통 HAProxy
같은 원인 · 공통 HAProxy
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0264
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0264/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.