사례3건
3건 중 1~3번째
IL-0063Redis 스테이트풀셋을 다시 만들자 Redis 클러스터가 한꺼번에 재시작되며 일부가 망가졌고, 재연결 폭주로 백엔드가 OOM 으로 죽어 AdGuard VPN 이 약 50분 멈췄다.AdGuard VPN2025- 증상
8:10 UTC 에 팀은 Redis 스테이트풀셋을 고아 삭제했다. 고아 삭제는 파드와 디스크는 그대로 두고 스테이트풀셋 객체만 지우는 방식이다. 스테이트풀셋을 다시 만들자 쿠버네티스가 8:10 부터 8:15 UTC 사이에 스테이트풀셋 전체를 빠르게 재시작했다. 처음에는 백엔드 서비스가 Redis 연결 오류를 냈지만 서비스 전체가 곧바로 무너지지는 않았다.
- 촉발
팀은 디스크를 온라인으로 늘린 뒤 Git 의 선언적 설정을 실제 상태와 맞추려고 Redis 스테이트풀셋을 고아 삭제했다. 고아 삭제는 파드와 디스크는 남기고 스테이트풀셋 객체만 지우는 방식이다. 그다음 늘린 크기를 적은 저장소 템플릿으로 스테이트풀셋을 다시 만들었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
Redis 클러스터 여러 인스턴스의 디스크 여유 공간이 바닥나고 있다는 알림이 시작이었다. 그 뒤의 장애는 스테이트풀셋을 다시 만든 직후 백엔드 서비스가 Redis 연결 오류를 내면서 드러났다.
- 조치
- 망가진 Redis 클러스터를 손으로 복구했다. 마스터에서 쓸모없어진 노드 ID 를 지우고, 해당 레플리카를 리셋한 뒤 클러스터에 다시 붙이고 복제가 따라잡기를 기다렸다.
- 실제로 메모리가 바닥난 구성 요소를 찾아낸 뒤, 백엔드 서비스를 확장하고 그 구성 요소의 메모리 한도를 올렸다.
- 프로브를 잠시 느슨하게 해, 백엔드 인스턴스가 ready 와 not ready 를 오가지 않고 바로 트래픽을 받게 했다.
- 10:00 UTC 에 임시 조치를 되돌렸다.
- 후속 조치
- 빠져 있던 스타트업 프로브를 넣는다. 데이터셋을 다 읽기 전에는 파드를 ready 로 표시하지 않는다.
- 재시작한 파드가 옛 마스터 IP 주소에 묶여 있을 때 쓸 수 있도록 Redis 용 자체 컨트롤 플레인을 만든다.
- 서비스 전체의 단일 장애점이 된 이 Redis 클러스터 의존을 줄인다. 중요한 정보 일부를 서버마다 따로 둔 Redis 클러스터 같은 다른 데이터 저장소로 옮기고, 백엔드 일부 구성 요소에 Kafka 를 쓰기 시작한다.
- 교훈
장애를 일으킨 것은 디스크 확장이 아니라 상태를 맞추려고 컨트롤러 객체를 다시 만든 단계였다. 고칠 수 없는 필드가 있으면 객체를 통째로 바꾸는 위험한 방법을 쓰게 된다. 그렇게 바꾸면 쿠버네티스가 워크로드를 넓은 범위에서 다시 조정할 수 있다. 스타트업 프로브와 엄격한 레디니스 프로브가 있어야 롤링 재시작이 현재 파드가 정말 준비될 때까지 기다린다. 이번 장애에서 가장 뼈아픈 것은 프로브가 없었다는 점이다. 분산 클러스터가 다시 붙고 복제를 따라잡는 데는 시간이 걸리므로, 의존하는 서비스는 그동안 기능을 줄여서라도 버티도록 설계해야 한다.
- 증상
2024년 8월 27일 14:20 UTC부터 15:16 UTC까지 일부 HubSpot 고객이 계정에 로그인하지 못했고 콘텐츠에 접근하거나 도구를 쓰지 못했다. 모니터링은 플랫폼 전반에서 성능이 크게 떨어진 것을 잡았다.
- 촉발
트래픽 관리 시스템의 핵심 구성 요소를 평소대로 운영하던 중 로드 밸런서 스택이 경로 처리 설정을 갱신했다. 외부 문서에는 알려져 있었지만 HubSpot 은 몰랐던 문제 때문에 이 갱신이 헬스 체크 응답을 잠시 막았다.
- 원인
- 구성 요소
- 기여 요인
- 감지
HubSpot 은 14:20 UTC에 내부에서 문제를 확인했다. 14:23 UTC에는 모니터링 시스템이 플랫폼 전반의 성능 저하를 잡았고 장애 대응 팀이 소집됐다.
- 조치
- 14:59 UTC에 팀이 남은 로드 밸런서 인스턴스의 용량을 늘리는 작업에 들어갔다.
- 15:04 UTC에 새 로드 밸런서 인스턴스가 올라와 시스템의 부하를 덜었고 트래픽이 안정되기 시작했다. 15:16 UTC에 시스템이 완전히 복구됐다.
- 후속 조치
- 헬스 체크가 잘못 타임아웃되지 않도록 설정을 고쳤다.
- 설정 갱신 같은 작업 중에도 헬스 체크가 끊기지 않고 먼저 처리되도록 헬스 체크 시스템을 다시 설계한다.
- 갑작스러운 트래픽 급증 때 더 많은 트래픽을 받을 수 있도록 로드 밸런서 용량을 늘렸다.
- 트래픽 급증을 더 일찍 감지하고 실시간으로 부하를 나눠 특정 인스턴스 묶음에 부하가 몰리지 않도록 로드 밸런싱 구조를 고친다.
- 대규모 장애 때 상태 페이지가 자동으로 갱신되도록 했다.
- 상태 갱신이 더 빠르고 정확해지도록 모니터링 시스템을 소통 도구와 더 긴밀하게 연결한다.
- 트래픽이 많은 상황을 재현하는 부하 테스트를 넓혀 약한 곳을 미리 찾는다.
- 장애 상황을 일부러 만들어 플랫폼의 복원력을 정기적으로 시험하는 카오스 엔지니어링을 도입한다.
- 최대 허용 연결 수 대비 현재 연결 수의 비율을 포함해 트래픽 흐름을 자세히 보는 새 지표를 넣었다.
- 트래픽 흐름에 맞춰 자원 용량을 자동으로 조절하는 오토스케일링을 구현한다.
- 교훈
핵심 문제는 설정 갱신 중에 헬스 체크가 잠시 막혀 로드 밸런서 여러 대가 비정상으로 잘못 판정된 것이었다. 여러 인스턴스가 동시에 내려가자 남은 인스턴스에 부하가 몰려 연쇄 장애가 됐다. 넘치는 연결을 거부하는 보호 장치가 있었지만 트래픽 급증이 너무 빠르고 커서 감당하지 못했다. 모니터링은 장애를 빨리 잡았지만, HubSpot 은 비정상적인 트래픽 급증을 더 일찍 알아챘다면 연쇄 장애를 막을 수 있었다고 봤다. 상태 페이지 갱신이 늦어 고객에게 오래되거나 불완전한 정보가 갔다.
IL-0044kube-prometheus-stack 업그레이드 뒤 Prometheus 가 WAL 재생 중 메모리를 50Gi 넘게 써서 시작할 때마다 OOMKilled 로 죽었다Saifeddine Rajhi2024- 증상
kube-prometheus-stack 헬름 차트를 업그레이드하는 중에 여러 파드가 Ready 가 되지 않았다. 그중 prometheus-prometheus-operator-prometheus-0 파드는 3/4 Running 상태였고 최근에 OOMKilled 로 종료된 기록이 있었다.
- 촉발
kube-prometheus-stack 헬름 차트를 업그레이드하던 중 Prometheus 가 시작하면서 WAL 을 재생했고, 이 과정에서 메모리 사용량이 메모리 제한을 넘었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
팀은 kube-prometheus-stack 헬름 차트를 업그레이드하던 중 Prometheus 파드를 포함한 여러 파드가 Ready 가 되지 않는 것을 보았다. kubectl describe pod 와 Prometheus 로그로 OOMKilled 를 확인했다.
- 조치
- Prometheus 파드에 kubectl exec 로 들어가 promtool tsdb analyze . 를 실행해 haproxy_server_http_responses_total 처럼 카디널리티가 높은 지표를 찾았다.
- 후속 조치
- WAL 재생 중 메모리 오버헤드가 10% 에서 15% 정도의 허용 범위 안에 있는지 확인하고, Prometheus 를 메모리 제한에 가깝게 운영하지 않는다.
- Prometheus 의 저장, 스크레이프, remote write 설정을 정기적으로 최적화하고, 최적화가 들어간 새 릴리스로 업그레이드한다.
- OOM 크래시 루프에서 자동으로 복구하는 장치를 만든다. 예를 들어 OOM 이벤트가 나면 WAL 을 자동으로 지운다.
- 메모리 사용량이 일정 기준을 넘으면 스크레이프를 멈추는 강제 스크레이프 제한을 둔다.
- 교훈
Prometheus 를 메모리 제한에 가깝게 운영하면 WAL 재생 중의 작은 오버헤드로도 OOM 이 난다. 가비지 컬렉션은 들쭉날쭉하고 카디널리티나 쿼리는 갑자기 늘 수 있으므로 메모리에 여유를 둔다. Prometheus 메모리 문제의 상당 부분은 카디널리티에서 온다. Prometheus 가 떠 있지 않을 때는 promtool tsdb analyze 로 카디널리티가 높은 지표를 찾는다. 메모리 제한만 올려서는 답이 되지 않았다. 메모리가 치솟는 것은 재생 단계뿐이었기 때문이다.
이 3건에서 가장 많이 나오는 구성 요소: 컨테이너 메모리 한도, 인메모리 캐시. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.