Incident Library
  • 원인
  • 구성 요소
  • 증상
  • 기여 요인
  • 사례

사례4건

4건 중 1~4번째

  1. 증상

    2026년 1월 9일 19:40 UTC 에 US 리전의 Inbox Heartbeat Anomaly 알람이 울려 장애가 선언되었다. US 리전에 호스팅된 고객은 Intercom 서비스를 전혀 쓸 수 없었다.

    촉발

    테스트용으로 테이블을 옮기는 MoveTables 명령이 제공업체 Kubernetes 클러스터의 일시적인 네트워크 문제로 실패했다. 이 실패를 처리하는 과정에서 Vitess v22 의 롤백 로직 버그 때문에 운영 데이터베이스에 빈 VSchema 가 적용되었다.

    원인
    구성 요소
    기여 요인
    감지

    19:40 UTC 에 US 리전의 Inbox Heartbeat Anomaly 알람이 울려 장애가 선언되었다. 19:41 UTC 에 엔지니어들과 인시던트 커맨더가 장애를 확인하고 조사를 시작했다.

    조치
    • PlanetScale 엔지니어가 장애 한 시간 전에 찍어 둔 VSchema 스냅샷을 다시 적용해 라우팅 토폴로지를 되살렸다.
    • PlanetScale 엔지니어가 실패한 MoveTables workflow 가 남긴 잔여물을 지웠다.
    • 21:00 UTC 이후 Vitess 를 v21 로 롤백하기 시작했고, 그 뒤 몇 시간에 걸쳐 끝냈다.
    후속 조치
    • PlanetScale 이 회귀를 일으킨 코드 경로를 찾았고 수정을 배포한다.
    • Vitess 수정 패치가 충분히 검증될 때까지 Intercom 인프라의 추가 데이터베이스 업그레이드를 멈춘다.
    • PlanetScale 이 장애 시작 때 Kubernetes 네트워크에서 패킷이 드롭된 원인을 찾는다.
    • 잘못된 토폴로지 갱신이 애플리케이션에 닿지 않게 막을 안전장치를 PlanetScale 과 함께 더 찾는다.
    • 데이터베이스 'branch unfreeze' 가 대기 중이던 버전 업그레이드를 자동으로 시작하게 만든 파이프라인 설정을 PlanetScale 과 함께 검토한다.
    • 의도하지 않은 배포가 일어나지 않도록 유지보수 작업과 버전 업그레이드를 더 엄격하게 나눈다.
  2. 증상

    2025년 9월 15일 13:08 UTC에 내부 모니터링이 요청 실패가 크게 늘고 지연이 늘었다고 알렸다. 그 뒤 9월 18일까지 고객 트래픽에서 요청 실패와 지연 급증이 간헐적으로 이어졌다.

    촉발

    2025년 9월 14일 클라우드 사업자가 Clerk 의 Postgres 데이터베이스를 마이너 버전으로 자동 업그레이드했다. 이 업그레이드에는 Postgres 가 연결 잠금을 다루는 방식의 큰 내부 변경이 들어 있었다.

    원인
    구성 요소
    기여 요인
    감지

    9월 14일 업그레이드 직후 내부 모니터링이 데이터베이스 부하 증가를 잡았지만 견딜 만한 수준이었고 지연에는 영향이 없었다. 9월 15일 13:08 UTC에 내부 모니터링이 요청 실패가 크게 늘고 지연이 늘었다고 알렸다.

    조치
    • 비용이 큰 쿼리 여러 개를 최적화해 데이터베이스의 기본 부하를 영구히 줄였다. 주요 인덱스를 다듬고 전체 재색인을 해 데이터베이스 오버헤드도 줄였다.
    • 안정성을 지키려고 남용 트래픽 차단을 잠시 강화했다. 효과는 있었지만 정상 요청 일부가 HTTP 429 로 거부됐을 수 있다.
    • 9월 17일 07:15 UTC부터 08:10 UTC까지 수동 마이너 버전 업그레이드를 하고 데이터베이스 용량을 늘렸다. 데이터베이스 상태가 눈에 띄게 나아졌고 지연 급증이 다시 사라진 듯했다.
    • 연결 재생성 시각이 서로 맞춰지지 않도록 연결 풀링 전략에 지터를 넣었다. 배포 직후 데이터베이스 부하가 장애 전보다 낮아졌고 지연 급증이 사라졌다.
    후속 조치
    • 업그레이드와 다운그레이드를 더 통제할 수 있고 지금 사업자보다 성능이 나은 데이터베이스 솔루션을 검토한다.
    • 가입과 로그인 인프라를 시스템의 다른 부분에서 떼어 내는 식으로 서비스 격리를 넓힌다.
    • 비용이 큰 쿼리 목록을 계속 따라가며 데이터베이스 성능을 더 끌어올린다.
    • 애플리케이션 하나를 다른 애플리케이션과 격리하는 테넌트 격리 방법을 검토한다. 이 작업은 샤딩과 멀티테넌트 인프라의 최신 방식을 살펴보는 일이라 다른 개선보다 오래 걸릴 가능성이 크다.
    교훈

    Clerk 는 돌아보면 원인이 단순해 보이지만 여러 요인이 겹쳐 찾기 어려웠다고 밝혔다. 첫째, 연결 지표를 60초 간격으로 수집해 15분마다 몇 초 안에 일어나는 재생성 주기가 대시보드에 드문드문한 급증으로만 보였다. 둘째, 같은 시기의 사기 가입 공격이 약 10분 주기로 부하를 만들어 원인을 그쪽으로 의심하게 했다. 셋째, 10분, 15분, 30분 간격의 정기 작업과 예약 쿼리가 급증 시각과 맞아떨어져 조사를 흩뜨렸다. 넷째, 같은 연결 풀링 로직을 쓰는 Backend API 에는 급증이 잘 보이지 않았는데, Clerk 는 Backend API 가 관리하는 연결 수가 훨씬 적어 재생성이 맞춰져도 데이터베이스가 감당했기 때문으로 봤다. 다섯째, 장애 중에 건 배포 동결은 평소 배포가 연결 생성 시각을 흩어 주던 효과를 없애 문제를 키웠다. 이 관계가 직관적이지 않아 연결 동기화를 가리키는 가장 분명한 신호가 가려졌다.

  3. 증상

    업데이트 직후 Open Build Service 참조 서버가 내려갔다. 애플리케이션은 점검 안내 메시지나 HTTP 503 Service Unavailable 오류로 응답했고, 아무도 API 와 웹 화면을 쓸 수 없었다. 팀도 사용자도 이를 알아챘고, 사용자들은 여러 채널로 알려 왔다.

    촉발

    참조 서버에서 zypper 업데이트로 haproxy 패키지를 업데이트했다.

    원인
    구성 요소
    기여 요인
    감지

    팀과 사용자 모두 애플리케이션이 내려간 것을 알아챘다. 사용자들이 여러 소통 채널로 알려 왔다. 문제는 업데이트 직후에 드러났다.

    조치
    • HAProxy 설정 파일을 모두 고쳤다.
    • 다른 서버의 Apache 설정에 남아 있던 점검 모드 플래그를 지웠다.
    • 서버를 재시작했고, 12시 20분 UTC 에 OBS 가 다시 올라왔다.
    후속 조치
    • 점검 모드 설정 블록이 도움이 되는지 문제가 되는지 논의한다.
    • 보조 프록시들의 SSL 인증서 동기화를 다시 살핀다.
    교훈

    "zypper up" 을 실행하면 무엇이 바뀌는지 더 잘 따져 봐야 한다. 업그레이드 중에는 주의가 필요한 것이 있기 때문이다. 보조 서버와 그 설정도 지켜봐야 한다. 평소에는 Salt 로 모든 것을 배포하지만 이번에는 보조 서버의 인증서를 놓쳤다. Apache 를 통해 Passenger 를 시작하면, Apache 에 문제가 있을 때 Passenger 프로세스가 뜨지 않는다. 그러므로 데몬이 문제없이 떠 있어도 Apache 설정 전체를 두 번 확인해야 한다. 긴 휴가 뒤에는 예상하지 못한 일이 생길 것이라고 생각해야 한다.

  4. 증상

    2021-05-21 13:00 UTC 에 CircleCI 엔지니어가 작업 시작이 지나치게 늦어진다는 첫 호출을 받았다. Docker, Machine executor, remote Docker 작업이 늦어지거나 막혔고, 시스템이 GCP 의 CPU 쿼터에 걸려 VM 을 띄우지 못하고 있었다.

    촉발

    2021-05-20 08:37 UTC 에 RabbitMQ 를 3.8.9 에서 3.8.16 으로 올렸다. 3.8.15 에서 들어온 변경으로, 메시지를 받고 ack 하지 않는 컨슈머에 기본 15분 ack 타임아웃이 걸렸다. 변경 기록에는 quorum queue 에만 해당한다고 적혀 있었지만 실제로는 모든 큐 종류에 적용됐다.

    원인
    구성 요소
    기여 요인
    감지

    02:31 UTC 에 VM destroyer 서비스 대기열 하나에 컨슈머가 없다는 알림이 왔고, 파드를 재시작해 정상으로 돌렸다. 그 뒤 03:10 에 다시 컨슈머가 빠지기 시작한 것은 알아채지 못했다. 10:11 에 VM 을 지우는 대기열이 쌓인다는 알림이 울렸다. 이 알림은 임계값에 닿을 때 한 번만 알리게 잘못 설정돼 있었고 온콜을 호출하지 않았다. 엔지니어들은 13:00 에 작업 시작 지연 호출을 받고서야 본격적으로 조사를 시작했다.

    조치
    • 14:13 에 Linux machine 작업이 작업 대기열에 아예 들어오지 못하게 손으로 막았다.
    • 13:26 에 Google Cloud 에 쿼터 증설 티켓을 열었고 14:37 에 GCP 가 쿼터를 늘렸다. 시스템은 그 뒤에도 스스로 회복하지 못했다.
    • 오래된 VM 을 손으로 지우는 계획을 세우고 지우기 시작했다.
    • 17:22 에 자원을 비우고 멈춘 플랫폼을 다시 움직이려고 일부 워크플로를 취소했다.
    • 16:25 에 VM 을 지우는 대기열에 컨슈머가 없음을 확인하고 대기열과의 연결을 되살리려고 VM 서비스 배포를 리셋했다. 대기열이 빠지기 시작했다.
    • Burst Balance 가 바닥난 RDS 데이터베이스를 재부팅해도 효과가 없자 18:20 에 인스턴스를 키워 메모리와 CPU, burst balance 를 늘렸다. 데이터베이스가 돌아오는 동안 VM 프로비저닝 서비스를 줄여 연결이 몰리지 않게 했고, 19:15 에 한 번 더 키웠다.
    • VM 프로비저닝 서비스를 줄이고, vm-create 대기열을 키우던 remote-docker 작업이 실행되지 않게 막아 부하를 덜었다.
    • 21:00 에 새 VM 을 만들고 오래된 VM 을 지우는 파드를 모두 줄여 VM 을 만들고 지우지 못하는 순환을 끊었다.
    • 21:57 에 remote-docker 작업을 프로비저닝 대기열에 넣지 않는 새 분배 백엔드를 배포했고, 22:21 에 프로비저닝 시스템을 줄여 대기열이 빠질 여유를 만들었다.
    • 22:36 부터 두 시간 동안 프로비저닝과 분배 시스템의 구성 요소를 하나씩 안정성을 확인하며 다시 올렸고, 00:39 에 모두 돌아오자 완화용 코드 변경을 되돌렸다.
    후속 조치
    • VM 프로비저닝이 부하 변화에 더 잘 버티고 thundering herd 에서 회복하도록 고친다.
    • VM 프로비저닝을 분리해 그 실패가 Docker 작업에 영향을 주지 않게 한다.
    • RabbitMQ 와 운영 대기열들의 관측성을 점검하고 보강한다.
    • 요청을 묶어 보내 GCP API 요청 한도에 걸리지 않게 한다.
    • 오래 이어지는 장애에 맞게 장애 대응 방식을 보강한다.
내 클러스터에도 있는지 확인하기

이 4건에서 가장 많이 나오는 구성 요소: 데이터베이스, 데이터베이스 프록시와 커넥션 풀러. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.

원인별1