사례4건
4건 중 1~4번째
- 증상
2025-10-21 21:45 UTC, 타임아웃 오류를 줄이려는 배포 직후 자동 모니터링이 기능 플래그 서비스의 오류율 상승을 잡았다. 2분 만에 롤백했지만 오류율은 내려가지 않았고, US 데이터센터에서 평가 요청의 약 38% 가 오류를 냈다.
- 촉발
10월 21일에는 증상만 고치려던 타임아웃 처리 배포가 장애를 일으켰다. 28일에는 플래그 서비스와 무관한 일상 배포가 파드 롤아웃을 일으켰고, 이 롤아웃이 장애로 이어졌다. 24일에는 로드밸런서 뒤에서 모든 트래픽을 IP 하나에서 온 것으로 본 레이트 리밋 배포가 장애를 일으켰다.
- 원인
- 구성 요소
- 기여 요인
- 감지
21일에는 배포 2분 뒤 자동 모니터링이 오류율 상승을 잡았고, 28일에는 온콜이 높은 오류 수 경보를 받았다. PostHog 는 대부분의 경우 2분 안에 감지했다고 정리했다. 24일에는 429 오류 경보가 없어서 18:10 UTC 부터 들어온 고객 신고로 알았고, 감지까지 62분이 걸렸다. CPU 경보가 아예 없어서 공통 원인인 CPU 포화는 오래 드러나지 않았고, 29일에서 30일 사이 장애는 7시간 넘게 이어졌다.
- 조치
- 10월 21일 타임아웃 처리를 바꾼 배포를 2분 안에 롤백했지만 오류는 멈추지 않았다.
- 10월 21일 23:00 UTC 부터 연결과 Redis 쓰기를 조절해 23:28 UTC 에 서비스를 복구했다.
- 10월 28일 롤아웃을 멈추고 US 플래그 파드를 0개로 줄여 Redis 가 회복되기를 기다린 뒤, 파드를 차례로 다시 올렸다.
- 10월 30일 00:03 UTC 에 하드웨어 변경을 롤백해 오류는 대부분 가라앉혔지만 지연은 남았다.
- 파드 리소스 요청을 늘리고 쿠버네티스 플릿 크기를 조정해 노드당 파드 수를 줄였다.
- 로드밸런서와 서비스 사이 Envoy 재시도에 한도를 걸었다.
- 데이터베이스 연결 타임아웃과 다른 중요한 설정을 런타임 설정으로 옮기고, 타임아웃 값을 피크 부하에 맞게 늘렸다.
- 노드마다, 파드마다 CPU 사용률이 80% 를 5분 동안 넘으면 온콜을 호출하는 CPU 경보를 추가했다.
- 후속 조치
- 플래그, 수집, 인프라 팀 엔지니어로 전담 팀을 꾸려 애플리케이션과 인프라 전체를 살피고 남은 병목을 찾는다.
- 플래그 서비스의 Redis 를 본 애플리케이션의 Redis 와 분리하는 방안을 검토한다.
- ArgoCD 동기화를 다시 켜기 전에 플래그 서비스 차트 설정을 ArgoCD 의 현재 값에 맞추고, 배포 전략과 Redis 전략을 정한다.
- 플래그 관련 코드의 필수 코드 오너를 기능 플래그 팀으로 정한다.
- 중요한 플래그 지표와 런북 링크를 한데 모은 대시보드를 만들고, 기능 플래그 런북을 고친다.
- 기존 서비스 지표와 인프라 지표에 빠져 있는 경보를 추가한다.
- readiness 검사가 liveness 검사를 그대로 따라 하지 않고, 데이터베이스에 ping 을 보내는 식으로 부하가 걸렸을 때 약해졌던 의존성을 확인하게 바꾼다.
- 캐시 채우기 작업에 레이트 리밋을 걸어 Redis 에 감당하지 못할 만큼 작업이 몰리지 않게 한다.
- 연결 풀을 모니터링해 풀이 바닥에 가까워지면 자동으로 요청을 조절하고, 동시 연결 수에 상한을 둔다.
- 운영 규모의 부하 시험 체계를 만든다.
- 점진적 롤아웃 기반을 만들어 배포가 미치는 범위를 줄인다.
- Postgres 에서 Redis 로 가는 데이터 흐름을 문서로 정리하고, 데이터 전송이 한꺼번에 몰릴 때 쓸 런북을 만든다.
- 교훈
가장 큰 교훈은 CPU 크기 산정이었다. 노드가 파드 요청에 비해 작으면 노드 하나에 파드가 너무 많이 몰리고, CPU 포화가 과도한 병렬 처리, 연결 풀 고갈, 느린 쿼리처럼 서로 다른 모습으로 나타난다. 증상만 고친 수정 때문에 21일의 장애가 28일에 되풀이됐다. PostHog 는 CPU 를 넉넉히 받은 파드를 적은 수로 돌리는 편이 낫다고 정리했다. 기능 플래그 서비스와 본 애플리케이션이 Redis 를 같이 쓰면 한쪽 과부하가 다른 쪽을 쓰러뜨리는 단일 장애 지점이 된다. CPU 지표는 처음부터 경보로 걸어야 하고, Postgres 에서 Redis 로 가는 전송 급증도 경보 대상이다. 재시도, 캐시 채우기, 연결 생성에 한도가 없으면 장애가 커진다. 과부하 패턴은 운영 트래픽에서만 드러났으므로 부하 시험이 필요하고, 중요한 설정은 배포 없이 바꿀 수 있어야 한다.
- 증상
02:15 UTC 무렵부터 API 수집 엔드포인트의 이벤트 처리가 느려졌다. 실패는 났다가 멎기를 되풀이했고, 끝내 몇 분 동안 수집이 완전히 멈췄다. 기본으로 걸어 둔 알림이 수집 성능과 안정성 문제를 온콜 엔지니어에게 알렸다. 상태 페이지 첫 공지는 수집 서비스의 오류율과 응답 시간이 평소보다 높다는 알림을 조사하고 있다는 내용이었다.
- 촉발
몇 분 사이에 여러 곳에 흩어진 연결에서 비정상적으로 많은 쿼리가 들어왔다.
- 원인
- 구성 요소
- 기여 요인
- 감지
기본으로 걸어 둔 알림이 수집 성능과 안정성 문제를 온콜 엔지니어에게 알렸다. 자동 로드 셰딩 장치도 작동하면서 알림을 더 보냈다. 상태 페이지 첫 공지는 18:28 PST 에 올라왔다.
- 조치
- 엔지니어들이 용량을 확보하려고 수집 호스트 수를 수동으로 크게 늘렸다.
- 몇 분 동안 수집 트래픽 대부분을 끊고 수집 호스트 용량을 다시 확보했다.
- 가장 공격적으로 트래픽을 보내던 발신처의 속도 제한을 트래픽이 가라앉을 때까지 임시로 낮춰 클러스터를 안정시켰다.
- 후속 조치
- 장기 해결책을 마련하는 동안 같은 장애가 반복되지 않도록 수집 호스트 수를 늘려 두었다.
- 이번 장애 경로를 막을 프로젝트를 정하는 일에 집중한다.
- 교훈
Honeycomb 은 이번 장애를 이미 대비책이 있던 장애의 변형으로 보았다. 이번 장애는 그 대비책 일부를 비켜 가는 방식으로 일어났다. 실패했던 호스트들이 쿠버네티스의 CrashLoopBackOff 상태에 걸려 오프라인으로 남으면서 급하게 늘린 용량을 깎아 먹었다. OTel 처럼 배치 단위로 성공과 실패를 알리는 프로토콜에서는 서버가 일부만 버려도 클라이언트가 배치 전체를 다시 보내 트래픽이 크게 불어날 수 있다.
- 증상
2022년 6월 14일 03:03 US/Pacific 부터 us-central1 의 GKE API 호출이 느려지고 오류를 냈다. gcloud 와 Google Cloud Console 에서 보내는 GKE API 호출이 모두 영향을 받았다.
- 촉발
GKE 백엔드로 들어오는 트래픽이 예상하지 못하게 늘었다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- 늘어난 트래픽을 감당하도록 GKE 컨트롤 플레인을 증설했다.
- 교훈
실패한 요청을 클라이언트가 재시도하면 갑자기 늘어난 트래픽이 더 커진다. 관리형 컨트롤 플레인이 느려져도 클러스터 워크로드는 계속 돌지만, 클러스터를 조회하거나 바꾸는 작업은 막힌다.
- 증상
Zalando Fashion Store 의 모든 웹 상품 페이지와 코디 페이지가 한 시간 넘게 고객에게 오류를 많이 냈다. 오류는 쿠버네티스 클러스터 하나에서 도는 핵심 데이터 집계 계층 서비스에서 나왔다.
- 촉발
그리 중요하지 않은 하위 서비스 하나로 가는 호출이 타임아웃 나기 시작했다. 집계 계층이 이 호출에 404 로 응답하자 클라이언트가 재시도했고, 집계 계층으로 가는 요청과 그만큼의 DNS 쿼리가 갑자기 치솟았다.
- 원인
- 구성 요소
- 기여 요인
- 감지
DNS 장애로 클러스터 내부 모니터링이 함께 멈춰 당직 호출이 자동으로 가지 않았다. 집계 계층 서비스 당직 엔지니어가 평소처럼 자동 호출에 기대지 못하고 쿠버네티스 담당 당직 엔지니어에게 직접 전화했다. 그래서 쿠버네티스 당직 엔지니어가 장애를 알기까지 예상보다 오래 걸렸다. 연락을 받은 엔지니어가 CoreDNS 파드가 OOM 으로 죽고 있는 것을 찾아냈다.
- 조치
- 쿠버네티스 당직 엔지니어가 CoreDNS 파드의 메모리 request 와 limit 을 100Mi 에서 2000Mi 로 직접 올렸다.
- 후속 조치
- 노드마다 dnsmasq 를 앞에 둔 CoreDNS 를 띄우는 방식으로 더 튼튼한 DNS 구성을 도입한다. 검토하고 시험한 다른 어떤 구성보다 이 방식의 성능이 좋았다.
- 클러스터 바깥에서 클러스터 전체 상태를 보는 알림을 강화한다. 팀은 클러스터 안 애플리케이션이 영향을 받기 전에, 늦어도 같은 시점에는 클러스터 이상을 알아야 한다.
- 장애 대응 절차와 도구를 개선한다. 자동 당직 호출이 실패해도 당직 엔지니어가 다른 도구로 옮겨 가지 않고 다른 팀에 바로 에스컬레이션할 수 있게 한다. 채팅 봇으로 에스컬레이션을 단순하게 만드는 방안을 추진하고 있다.
- 교훈
쿠버네티스 DNS 구성은 충분히 튼튼하지 않았다. 애플리케이션 하나가 DNS 를 사실상 서비스 거부 공격하듯 몰아붙여 클러스터 전체를 멈추게 할 수 있어서는 안 된다. DNS 쿼리를 늘린 애플리케이션의 영향 범위는 적어도 노드 하나, 가능하면 파드 하나 안에 갇혀야 한다. 팀은 conntrack 을 처리하는 리눅스 커널의 경쟁 상태나 ndots 5 문제 같은 쿠버네티스 DNS 문제를 대부분 알고 있었고, 일부는 완화책도 갖고 있었다. 하지만 이 문제들이 DNS 구성에 얼마나 크게 영향을 주는지는 제대로 알지 못했다. 모니터링도 충분히 튼튼하지 않았다. 일부 알림은 클러스터 밖에서 돌았지만 대부분은 클러스터 안에서 돌았다. 그래서 DNS 가 무너졌을 때 당직 엔지니어가 자동으로 호출되지 않았고 복구 시간이 필요 이상으로 길어졌다.
이 4건에서 가장 많이 나오는 구성 요소: 인메모리 캐시, 애플리케이션 데이터베이스. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.
원인별1
용량 한계4건
- 구성 요소
- 기여 요인
IL-0100노드가 파드의 CPU 요청에 비해 작아 CPU 가 포화되면서 PostHog 기능 플래그 서비스에 열흘 사이 장애가 세 번 났다.PostHog2025IL-0202갑자기 몰린 쿼리와 데이터베이스 쓰기로 Honeycomb 수집 호스트가 메모리 부족으로 죽었고, 쿠버네티스 CrashLoopBackOff 가 용량 회복을 막아 US1 이벤트 수집이 한 시간 넘게 불안정했다Honeycomb2023IL-0140us-central1 의 GKE API 가 지연과 오류를 내면서 고객이 클러스터 상태 확인, 업그레이드, 생성과 삭제를 하지 못했다.Google Cloud2022IL-0001CoreDNS 파드가 메모리 한도 100Mi 에 걸려 OOM 으로 계속 죽으면서 쿠버네티스 클러스터 전체의 DNS 가 멈췄다Zalando2019