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

사례6건

6건 중 1~5번째

  1. 증상

    2025년 1월 21일 23시 UTC쯤, 보관 데이터를 담는 데이터베이스 인스턴스의 남은 저장 공간이 거의 없다는 자동 알림이 울렸다. 23시 26분부터 워크플로 대기열이 늘면서 워크플로와 잡의 시작과 취소가 느려지고 UI에서 워크플로를 보기 어려워졌다.

    촉발

    1월 16일에 보관 데이터베이스의 함수 하나를 고친 코드 변경이 의도치 않게 로그 메시지를 지나치게 많이 만들어 냈다.

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

    23시쯤 보관 데이터베이스의 남은 저장 공간이 거의 없다는 자동 알림이 울렸다. 같은 시각에 요청량 알림이 따로 울려 팀은 워크플로 지연을 곧바로 이 문제와 연결하지 못했다. 그 알림이 해결된 뒤에도 대기열이 늘자 다른 팀이 조사에 나섰다.

    조치
    • 23시 44분에 워크플로 대기열을 처리하는 이벤트 소비자를 증설했다.
    • 23시 55분에 문제가 난 보관 데이터베이스의 읽기 복제본을 독립된 주 인스턴스로 승격했다.
    후속 조치
    • 로그 메시지를 지나치게 많이 만들던 데이터베이스 함수를 고쳤다.
    • 워크플로 보관 호출의 재시도 정책에 최대 지속 시간을 두어 기본 타임아웃보다 일찍 실패하게 하고, 보관 서비스에 문제가 생겨도 워크플로 서비스가 받는 영향을 줄인다.
    • 장기적으로 워크플로 보관 과정을 이벤트 기반 방식으로 바꿔 두 서비스를 떼어 놓는다.
    • 데이터베이스에 예측 모니터링과 이상 탐지 모니터링을 더해, 이상한 움직임이 위험 수준에 닿기 전에 알림을 받는다.
    교훈

    보관 데이터베이스의 문제를 알리는 알림은 울렸지만, 데이터베이스가 예측보다 훨씬 빨리 차서 고객 영향이 나기 전에 대응할 시간이 거의 없었다. 워크플로 서비스가 보관 서비스를 동기로 호출하기 때문에 보관 쪽 문제가 워크플로 전체의 지연으로 번졌다.

  2. 증상

    2024-12-13 11:25 AM EST 에 Gadget 은 커넥션 한도를 올리려고 주 Postgres 데이터베이스를 그 자리에서 재시작했는데, 서버가 내려간 뒤 다시 올라오지 않았다. 그동안 Gadget 앱으로 오는 모든 요청이 실패했다.

    촉발

    Gadget 은 플랫폼이 커지며 Postgres 의 max_connections 한도에 닿아 생기던 짧은 장애를 끝내려고, 이 값을 올리는 긴급 설정 변경을 결정했다. max_connections 는 서버를 재시작해야만 바뀌므로 11:25 AM EST 에 데이터베이스를 그 자리에서 재시작했다.

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

    Gadget 은 11:25 AM EST 에 재시작한 데이터베이스가 기대대로 다시 올라오지 않는 것을 11:26 AM 에 확인했다.

    조치
    • 데이터베이스 서버를 하드웨어 리셋해 메모리 조각화를 없앴고, 11:50 AM EST 에 데이터베이스가 다시 올라왔다.
    • 데이터베이스가 멈춘 동안 오토스케일러가 줄인 컴퓨트를 당시의 거의 4배로 다시 띄웠고, 이 확장은 성공했지만 서비스 저하가 20분 더 이어졌다.
    후속 조치
    • 이번처럼 중단을 일으키는 데이터베이스 작업은 앞으로 replica 를 만들어 장애 조치하는 방법으로만 한다. 새 replica 를 먼저 띄우면 넘어가기 전에 운영 인프라 안에서 동작을 확인할 수 있다.
    • Black Friday 와 Cyber Monday 전의 용량 계획을 훨씬 공격적으로 세워 부하 6배 증가에 대비하고, 충분한 시간을 두고 종합 부하 시험을 해서 준비가 됐는지 확인한다.
    • 계획된 중단은 상태 페이지와 커뮤니티 Discord 로 미리 알리고, 계획된 점검과 서비스 장애의 차이를 분명히 알리도록 표준 운영 절차를 다듬는다.
    • 계획해 온 데이터베이스 샤딩 프로젝트를 끝내 Gadget 앱마다 다른 데이터베이스를 쓰게 한다. 그러면 데이터베이스 설정 변경에 카나리 배포와 블루/그린 구성을 써서 고객 앱에 닿기 전에 충분히 시험하고, 장애 범위도 좁힐 수 있다.
    • 이미 진행 중인 무중단 데이터베이스 장애 조치 시스템을 완성해 어떤 앱도 멈추지 않고 데이터베이스 크기와 설정을 바꿀 수 있게 한다.
    • 오토스케일러의 최소 규모를 크게 높였다. 앞으로 장애가 나도 컴퓨트가 훨씬 덜 줄어 복구가 빨라진다.
    교훈

    Gadget 은 그 자리에서 재시작하는 방법을 고른 것을 판단 착오로 보았다. 확신할 수 없고 겪어 본 적 없는 상태로 시스템을 몰아넣은 위험한 선택이었다는 것이다. Gadget 은 모든 실패 상태를 미리 알 수는 없어도 처음 보는 실패 상태로 들어가는 일은 대개 피할 수 있다고 했다. Black Friday 와 Cyber Monday 의 용량 계획이 두 배로 잡혀 거의 5배의 부하를 감당하지 못했다. 제대로 계획했다면 점검 시간을 미리 잡고 스테이징에서 연습할 수 있었다. 새 데이터베이스 설정을 사용자에게 영향 없이 운영과 비슷한 환경에서 시험할 방법도 없었다. 통합 테스트는 합성 Postgres 데이터베이스와 쿠버네티스 인프라에서 돌기 때문에, 몇 달 동안의 운영 부하가 만드는 메모리 조각화나 메모리 사용 문제를 재현하지 못한다.

  3. 증상

    2022년 1월 3일부터 17일까지 이어진 100% 할인 이벤트 기간에, 인프런은 1월 3일, 4일, 7일, 17일 오전 9시와 오후 10시 무렵마다 쓸 수 없을 만큼 느려졌다. 트래픽은 평소의 5~20배였고, 매번 데이터베이스의 슬로우 쿼리와 부하가 함께 나타났다.

    촉발

    2022년 1월 강의 125개를 0원에 등록할 수 있는 100% 할인 이벤트가 크게 퍼지면서 평소 대비 5~20배의 트래픽이 들어왔다.

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

    모니터링과 슬로우 쿼리 알람으로 문제를 알아챘고, 문제가 되는 쿼리를 30분 안에 찾았다. 1월 17일에는 오후 10시부터 RDS 의 여러 수치가 요동치는 것을 보았다.

    조치
    • 관심회사 조회 API 의 쿼리 일부가 인덱스를 쓰지 않는 것을 로그와 실행계획으로 확인하고 바로 인덱스를 추가했다.
    • 용량이 큰 캐시 행의 캐시 초기화와 재생성 주기를 바꿨다.
    • 쓰기 DB 에 부하를 준 조회용 쿼리부터 읽기 DB 로 옮겼다.
    • 시간을 벌려고 데이터베이스를 r5.8xlarge 8대로 늘렸다.
    • 느린 강의 조회 쿼리에 인덱스를 추가하거나 쿼리를 바꿔 인덱스를 쓰게 했고, 개선할 수 없는 쿼리를 쓰는 기능은 껐다.
    • select * 로 읽던 강의 조회 쿼리에서 실제로 쓰지 않는 고용량 강의 소개 컬럼을 모두 뺐다.
    • IN 절에 담는 강의 ID 를 20개씩 나눠 Promise.all 로 처리하게 바꿔, 쿼리가 다시 인덱스를 쓰게 했다.
    • PostgreSQL 을 10.16 에서 11.13 으로 올렸다.
    • 5초 넘게 도는 쿼리를 강제로 끝내도록 쿼리 타임아웃을 5초로 걸었다.
    • Max Connection 을 늘렸다.
    • 강의 테이블에 수동으로 vacuum 을 돌려 Dead Tuple 을 정리했다.
    • 용량이 큰 강의 소개 컬럼을 강의 테이블에서 떼어 별도 테이블로 옮겼다.
    후속 조치
    • 한 테이블의 장애가 전체 서비스의 장애로 번지는 구조를 개선한다.
    • 성능 개선이 쉽지 않은 테이블과 캐시 구조를 개선한다.
    • 직관적이지 않은 SQL 코드를 개선한다.
    • 타입과 테스트 코드가 없어 안심하고 고치기 어려운 코드를 개선한다.
    • 배치 작업을 안정적으로 돌릴 환경을 갖춘다.
    • 모놀리식 구조는 알맞은 선에서 유지하고, 장애가 잘 번지는 일부 도메인만 따로 분리한다.
    교훈

    그동안 데이터베이스 병목이 모두 읽기 DB 의 슬로우 쿼리로 보여 팀은 읽기 DB 만 모니터링했다. 이 때문에 근본 원인인 쓰기 DB 강의 테이블의 Dead Tuple 을 늦게 찾았다. 원인 쿼리는 빨리 찾았지만, 무분별한 쿼리 추상화와 타입과 테스트 코드가 없는 코드 때문에 수정과 배포가 늦어졌다. 그만큼 장애 시간도 길어졌다. 첫 주 장애를 돌아보면 어느 페이지가 문제가 될지 예상할 수 없었고, 대부분의 페이지가 트래픽이 몰리면 언제든 장애가 날 수 있는 상태였다. 팀은 조직의 구조와 성숙도가 갖춰지지 않은 상태에서 마이크로서비스 아키텍처인 MSA 로 바로 옮기면 더 큰 문제가 생긴다고 보았다. 그래서 모놀리식 구조를 알맞은 선에서 유지하면서 일부 도메인만 분리하기로 했다.

  4. 증상

    2021-11-08 18:50 UTC 배포 직후 오류와 알림이 바로 들어왔고, 모든 executor 에서 고객 작업이 "not running" 상태로 막혔다.

    촉발

    18:50 UTC 에 분배 서비스의 PostgreSQL 데이터베이스에서 필드 타입을 바꾸는 배포를 내보냈다. 이 스키마 변경은 하위 호환되지 않았다.

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

    18:50 UTC 배포 직후 분배 실패와 관련된 오류와 알림이 바로 보였다.

    조치
    • 오류와 알림을 보고 곧바로 변경을 롤백했다. 롤백 뒤에는 두 배포 사이에 쓰인 데이터를 읽지 못해 분배가 계속 실패했다.
    • 분배 시스템이 그 필드를 무시하게 하는 수정을 빠르게 만들고 빌드해 직접 배포했다.
    • 몰려들 작업에 대비해 주 컴퓨트 클러스터를 직접 늘렸다. 이 수동 확장은 CircleCI 장애 대응 절차의 표준 단계다.
    • 작업 큐가 줄어 정상 처리가 이어지는 것을 잠시 지켜본 뒤 장애를 해결로 처리했다.
    후속 조치
    • 같은 장애가 다시 나지 않도록 테스트 전략의 빈틈을 찾아 고친다.
    • 비슷한 배포가 시스템의 모든 작업에 영향을 주지 않도록, 분배 서비스가 예상하지 못한 데이터를 만났을 때의 동작을 바꾼다.
    • 예상하지 못한 장애가 났을 때 더 빨리 복구할 수 있게 한다.
  5. 증상

    2017-11-06 12:33 US/Pacific 부터 App Engine Memcache 를 모든 리전의 애플리케이션에서 쓸 수 없었다. Google 은 12:34 에 자동 알림을 받았고, 상태 페이지는 Memcache 를 쓰는 모든 프로젝트가 영향을 받는다고 알렸다.

    촉발

    설정 업데이트 뒤 애플리케이션과 데이터센터의 매핑 설정을 담은 글로벌 데이터베이스의 엔티티를 읽을 수도 쓸 수도 없게 됐다.

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

    Google 은 장애가 시작된 1분 뒤인 12:34 US/Pacific 에 자동 알림을 받았다.

    조치
    • 14:21 에 데드라인을 충분히 길게 준 업데이트 요청으로 설정을 고쳤다. 데이터베이스의 모든 복제본이 동기화되고 클라이언트가 매핑 설정을 다시 읽을 수 있게 됐다.
    • Memcache 로 보내는 트래픽을 천천히 다시 늘렸고 오류율이 줄어들었다.
    후속 조치
    • 임시 완화로 글로벌 설정을 읽는 쪽의 수를 줄여 쓰기 때 경합이 생기지 않게 한다.
    • 이 설정을 리전 단위로 나눠 비슷한 실패가 번지는 범위를 줄인다.
내 클러스터에도 있는지 확인하기

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

원인별3

배포 결함2건

  1. IL-0552 보관 데이터베이스의 저장 공간이 차서 CircleCI 워크플로 시작이 늦어지고 UI에서 워크플로가 잘 보이지 않았다
  2. IL-0328 배포 뒤 CircleCI 의 모든 executor 에서 작업이 "not running" 상태로 멈췄다

용량 한계3건

  1. IL-0312 max_connections 를 올리려고 재시작한 주 PostgreSQL 데이터베이스가 다시 올라오지 않아 Gadget 의 모든 앱 요청이 멈췄다
    Gadget2024
  2. IL-0456 100% 할인 이벤트 기간에 인프런 서비스가 Aurora PostgreSQL 병목으로 여섯 번 멈췄다
    Inflab2022
  3. IL-0383 PagerDuty 알림 파이프라인이 이틀 연속 장애를 겪어 이벤트를 받지 못하고 알림이 늦거나 가지 않았다

설정 변경1건

  1. IL-0292 App Engine Memcache 가 글로벌 설정을 읽지 못해 모든 리전에서 1시간 50분 동안 멈췄다