Scale Out을 해도 시스템이 터지는 이유
이 글은 「대용량 트래픽 제어하기」 시리즈 2편이다.
1편에서 트래픽 증가가 단순한 서버 수 부족 문제가 아니라는 점을 살펴봤다면, 2편에서는 Scale Out을 했음에도 불구하고 시스템이 불안정해지는 이유를 실제 운영 관점에서 깊게 다룬다. 핵심은 “확장은 했는데, 왜 더 자주 터지는가”다.
Scale Out 이후에 나타나는 첫 번째 착각
Scale Out을 적용하면 다음과 같은 기대를 하게 된다.
- Pod 수 증가
- 처리량 증가
- 응답 지연 감소
하지만 운영 환경에서는 전혀 다른 장면이 펼쳐지기도 한다.
- Pod는 늘어났지만 응답 시간은 그대로
- 트래픽 피크 타임에 Pod가 연쇄 재시작
- 장애 빈도가 오히려 증가
이 괴리는 대부분 리소스와 실행 환경에 대한 오해에서 시작된다.
HPA는 왜 기대와 다르게 동작할까
Kubernetes에서 자동 Scale Out의 핵심은 HPA다.
많은 경우 HPA가 “알아서 잘 늘려줄 것”이라고 기대한다.
그러나 HPA의 판단 기준은 매우 단순하다.
- 현재 사용률
- requests 대비 사용 비율
HPA는 실제 서비스 품질이나 응답 시간을 직접 보지 않는다.
즉, 잘못된 기준 위에서 자동화가 돌아가면 결과도 잘못될 수밖에 없다.
requests 설정이 Scale Out의 출발점인 이유
HPA는 requests를 기준으로 사용률을 계산한다.
여기서 문제가 발생한다.
- requests가 너무 낮은 경우
- 실제보다 사용률이 높게 계산
- 불필요한 Scale Out 발생
- requests가 실제 사용량과 동떨어진 경우
- Scale Out 타이밍 왜곡
- 트래픽 대응 실패
requests는 단순한 숫자가 아니라, HPA 판단의 기준선이다.
limits가 시스템을 불안정하게 만드는 순간
limits는 보호 장치지만, 잘못 설정되면 장애 트리거가 된다.
특히 메모리 limits는 치명적이다.
- 트래픽 증가
- 객체 생성 증가
- 힙 사용량 급증
- limits 초과
- OOMKill 발생
이 과정은 Scale Out 상황에서 더 자주 발생한다.
새로 생성된 Pod는 Warmup되지 않은 상태이기 때문이다.
OOMKill은 왜 Scale Out과 함께 나타날까
Scale Out이 발생하는 시점은 보통 다음과 같다.
- 트래픽 급증
- CPU 사용률 상승
- HPA 트리거
이 시점에 생성된 Pod는 다음 특성을 가진다.
- Cold Start 상태
- JVM 최적화 미완료
- 메모리 사용 패턴 불안정
결과적으로 새 Pod는 기존 Pod보다 OOMKill에 훨씬 취약하다.
JVM 애플리케이션이 특히 취약한 이유
JVM 기반 애플리케이션은 컨테이너 환경에서 다음 특성을 가진다.
- 힙 외 메모리 사용
- GC 시점에 따른 메모리 변동
- 초기 기동 시 메모리 급증
Scale Out 시 생성되는 Pod는 이 모든 단점을 한꺼번에 안고 시작한다.
이 때문에 JVM 애플리케이션은 다음 상황에 취약하다.
- 트래픽 피크 시 Scale Out
- 배포 직후
- 장애 복구 직후
Warmup되지 않은 Pod가 만드는 문제
Warmup이 완료되지 않은 Pod는 다음 특성을 보인다.
- 초기 응답 지연
- GC 빈도 증가
- 처리량 저하
하지만 Service와 Load Balancer는 이를 구분하지 않는다.
결과적으로 가장 불안정한 Pod가 트래픽을 받게 된다.
이 구조는 다음 문제를 만든다.
- 응답 지연 전파
- 타임아웃 증가
- Retry 증가
- 추가 부하 발생
Scale Out은 병목을 숨기지 않는다
Scale Out을 해도 다음 병목은 그대로 남는다.
- DB 쓰기 성능
- 외부 API 응답 지연
- 메시지 큐 처리 속도
오히려 Scale Out은 병목 지점으로 더 많은 요청을 빠르게 밀어 넣는다.
이때 시스템은 “느리게 실패”하기 시작한다.
느리게 실패하는 시스템의 위험성
느리게 실패하는 시스템은 다음 특징을 가진다.
- 요청은 살아 있음
- 스레드는 점유됨
- 커넥션은 반환되지 않음
이 상태가 누적되면 시스템은 결국 완전히 멈춘다.
Scale Out은 이 과정을 더 빠르게 진행시킬 수 있다.
Scale Out은 왜 만능 해결책이 아닌가
여기까지의 내용을 요약하면 다음과 같다.
- HPA는 단순한 기준으로 동작
- requests / limits 설정이 잘못되면 자동화도 실패
- JVM 특성상 Cold Start는 위험
- 병목은 확장되지 않는 지점에 존재
즉, Scale Out은 조건부로만 효과적인 전략이다.
다음 편에서 다룰 내용
2편에서는 Scale Out 이후 발생하는 문제의 원인을 내부로 파고들었다.
다음 3편에서는 관점을 전환한다.
- 장애는 왜 전파되는가
- Retry는 왜 독이 되는가
- 서킷 브레이커는 무엇을 보호하는가
- 빠르게 실패하는 시스템이 왜 중요한가
정리
Scale Out은 대용량 트래픽 대응의 시작점일 뿐, 안정성의 보장은 아니다. HPA, requests / limits, JVM 메모리 특성을 이해하지 못하면 자동 확장은 오히려 장애를 가속한다. 대용량 트래픽을 제어하려면 “얼마나 늘릴 것인가”보다 “어디서 멈출 것인가”를 먼저 고민해야 한다.
다음 편:
대용량 트래픽 제어하기 3편 – 장애를 확산시키지 않는 시스템 설계