Incident Library
적용된 필터 원인설정 변경구성 요소데이터베이스 복제모두 풀기검색어 없이 필터만 적용한 목록입니다. 최근 사례부터입니다.
추천 필터 검색하면 검색어에서 찾은 분류 값이 여기에 나옵니다.

그래프

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

사례6건

6건 중 1~5번째

  1. 증상

    2024년 9월 18일 데이터센터 전환을 앞두고 cookbook 으로 원형 복제를 설정하던 중, 21:28 UTC 쯤 엔지니어가 x1 섹션의 primary master 가 복제를 하지 않는 것을 orchestrator 에서 먼저 알아챘다. es6 섹션도 같은 상태였다.

    촉발

    다음 주 데이터센터 전환을 앞두고 cookbook 이 핵심 데이터베이스를 eqiad 에서 codfw 로 가는 한 방향 복제에서 원형 복제로 바꿨다. ROW 기반 복제를 쓰는 x1 섹션에 codfw 에서 eqiad 로 가는 복제를 설정하고 pt-heartbeat 를 시작하자, eqiad 서버에 없는 heartbeat 행을 갱신하려다 복제가 멈췄다.

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

    원형 복제의 일반 모니터링이 아직 켜지지 않아, 엔지니어가 orchestrator 에서 먼저 알아챘다. 복제 자동화가 처음 도는 날이라 평소보다 많은 사람이 데이터베이스 상태를 지켜보고 있었다. 사용자에게 영향을 준 eqiad 에서 codfw 로 가는 방향의 고장은 Icinga 알림이 잡았다. 온콜 호출을 받은 사람은 없었다.

    조치
    • SET GLOBAL Replication_wild_ignore_table='heartbeat.%'; 로 heartbeat 테이블 복제를 건너뛰게 해 복제가 다시 흐르게 했다.
    • es 호스트에는 원래 고장이 난 방향에 맞춰, binlog 기록을 끈 채 eqiad 서버마다 빠진 codfw heartbeat 행을 직접 넣었다. 명령은 set sql_log_bin=0; INSERT INTO heartbeat.heartbeat (server_id, shard, datacenter) VALUES (<codfw-server-id>, 'es6' [or 'es7'], 'codfw'); 였다. es6 에서 먼저 시험했고, es7 에는 원형 복제를 설정하기 전에 미리 넣었다.
    • x1 codfw 호스트마다 binlog 기록을 끈 채 빠진 heartbeat 행을 넣어, 임시로 걸어 둔 heartbeat 무시 설정을 대신했다. 명령은 set sql_log_bin=0; INSERT INTO heartbeat.heartbeat (server_id, shard, datacenter) VALUES (<eqiad-server-id>, 'x1', 'eqiad'); 였다.
    후속 조치
    • 같은 문제를 다시 겪지 않게 한다. 빠진 행을 찾으면 직접 넣는 방식을 유력하게 본다.
    • 유지 보수 뒤 복제가 의도대로 양방향으로 동작하는지 확인하는 상태 점검을 cookbook 에 넣는다.
    • 유지 보수를 다른 순서로, 또는 섹션마다 따로 돌릴 수 있는 옵션을 더한다.
    • Phabricator 를 마지막에 한 번만 갱신하지 않고 섹션마다 갱신한다.
    • 모니터링의 빈틈을 메운다.
    • x1 과 ROW 를 쓰는 읽기·쓰기 es 호스트에서 pt-heartbeat-wikimedia 가 자기 세션을 STATEMENT 로 쓰도록 고쳐 배포했다.
    교훈

    원형 복제는 평소 운영 방식이 아니어서 heartbeat 테이블을 지우는 첫 조치가 문제를 eqiad 에서 codfw 로 옮기기만 했다. TRUNCATE 는 DDL 이라 늘 STATEMENT 모드로 전달되므로 이번에는 DELETE 보다 나았겠지만, 더 위험해서 고려하지 않았다. ROW 기반 복제, pt-heartbeat, 서버마다 다른 heartbeat 테이블 행이 겹친 문제는 이전 유지 보수 기록에 없었다. 자동화의 점검은 설정 직후 한 번이 아니라 모든 작업이 끝난 뒤에도 복제 채널을 확인했어야 했다. Wikimedia 는 어느 호스트에서도 sql_skip_slave_counter 를 쓰지 않아 더 큰 문제나 데이터 손실을 피한 것을 잘된 점으로 꼽았다.

  2. 증상

    2024년 8월 5일 16:30 UTC 부터 DigitalOcean 의 모든 리전에서 이벤트 처리가 실패해 Droplet 이벤트가 실패했고, 리소스 생성과 Cloud Control Panel, API 를 통한 관리가 멈췄다. Droplet 같은 기존 고객 리소스는 계속 온라인이었고 접근할 수 있었다.

    촉발

    새 데이터센터를 더하는 데이터스토어 클러스터 롤아웃에서 잘못된 복제 설정이 배포됐다. 이 설정은 키가 하나도 없는 새 데이터센터에 데이터스토어의 모든 키 소유권 100%를 줬다.

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

    16:35 UTC 에 서비스 디스커버리를 쓸 수 없다는 첫 보고가 내부에서 올라왔다. 데이터스토어 클러스터 롤아웃이 시작되고 5분 뒤였다.

    조치
    • 17:16 UTC 에 복제 설정 변경을 되돌리고, 데이터스토어 소유자가 된 리전에 되돌린 설정을 적용했다.
    • 18:25 UTC 부터 되돌린 설정을 알아채거나 적용하지 못한 리전을 찾아, 엔지니어가 그 리전의 노드에 직접 설정을 적용하고 데이터스토어 repair 를 돌렸다.
    • 남은 실패 이벤트를 정리하고, 아직 타임아웃되지 않은 대기 이벤트를 처리했다.
    후속 조치
    • 이런 확장 유지보수는 선언한 유지보수 시간 안에 하고, 고객 영향 가능성은 상태 페이지의 유지보수 공지로 알린다.
    • 이런 배포의 절차 문서를 현재 요구 사항에 맞게 고치고, 새 배포의 단계마다 할 일과 기대하는 결과를 분명하게 적는다.
    • 이번에 손으로 한 과정을 자동화해 사람의 실수 가능성을 줄인다.
    • 여러 팀이 내부 데이터스토어의 현재 토폴로지가 알맞은지, 그리고 내부 서비스 디스커버리의 가용성을 지키도록 리전 단위로 나누거나 여러 계층으로 구성할 방법이 있는지 검토한다.
  3. 증상

    2019년 12월 어느 금요일 저녁, 내부 모니터링 도구가 시스템에서 5xx 오류가 평소보다 훨씬 많이 난다고 알렸다. SRE 팀은 주요 애플리케이션인 API 가 RDS MySQL 데이터베이스에 접속하지 못한다는 것을 알아챘다. 원인을 파악하기도 전에 애플리케이션이 스스로 살아났고 알림이 멈췄다.

    촉발

    API 애플리케이션의 RDS MySQL 마스터 인스턴스가 Multi-AZ 장애 조치를 거쳐 다른 AZ 의 대기 인스턴스로 넘어갔다.

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

    내부 모니터링 도구가 5xx 오류가 평소보다 훨씬 많다고 알렸다. 복제 실패는 그 뒤 다른 알림으로 왔다. 데이터 손실은 다음 날 데이터베이스와 애플리케이션 트레이스 로그를 맞춰 보다가 찾았다.

    조치
    • 오래된 데이터가 사용자에게 보이지 않도록 복제본으로 가던 트래픽을 모두 마스터 인스턴스로 옮겼다.
    • 새 장비의 전체 스냅샷이 끝나기를 여섯 시간 기다린 뒤 복제본 다섯 대를 다시 만들고 트래픽을 복제본으로 되돌렸다.
    • 바이너리 로그에서 정확한 쿼리를 찾고 애플리케이션 트레이스 로그로 사건 순서를 따라가 8시간 회의 끝에 RDS 에 저장된 데이터를 바로잡았다.
    • 마스터 인스턴스의 innodb_flush_log_at_trx_commit 값을 2 에서 1 로 바꿨다.
    교훈

    잘못 설정한 변수 하나 때문에 Razorpay 는 처음부터 데이터 손실 위험을 안고 있었다. 팀은 장애를 끝까지 파고들어 근본 원인을 찾았고, 그 과정에서 RDS 가 Multi-AZ 구성과 장애 조치를 어떻게 다루는지 많이 배웠다.

  4. 증상

    10시 51분 Redis 에 장애 조치가 일어난 뒤 애플리케이션 서버가 Redis 에 접속하지 못해 Mackerel 이 요청에 제대로 응답하지 못했다. Mackerel 시스템 전체가 불안정해졌고 생존 여부 감시가 멈췄다.

    촉발

    감시 데이터를 담는 Redis 를 스케일업하려고 복제를 구성하는 작업을 했다. 복제 구성에 시간이 걸리는 동안 Redis 가 응답하지 않았고, keepalived 가 이를 노드 고장으로 판단해 의도하지 않은 장애 조치를 일으켰다.

    원인
    구성 요소
    기여 요인
    조치
    • Redis 를 올바른 쪽으로 다시 전환하고 애플리케이션이 돌아온 것을 잠시 확인했다.
    • 애플리케이션 서버를 차례로 재시작했지만 증상은 나아지지 않았다.
    • 부적절한 메트릭을 보내는 Mackerel 조직을 찾아 그 요청을 차단했다.
    • 애플리케이션 서버의 타임아웃 간격을 조정했다.
    • TSDB 인 Diamond 를 임시로 증설했다.
    • Kinesis 샤드 수와 Redis Cluster 샤드 수를 늘렸다.
    • API 용 애플리케이션 서버를 스케일아웃했다.
    • 잠시 점검 모드로 바꿔 사내에서 확인한 뒤 외부 요청을 조금씩 되돌렸다.
    후속 조치
    • 짧은 부하 증가로는 장애 조치가 일어나지 않도록 Redis 의 keepalived 헬스 체크 횟수를 늘렸다.
    • 애플리케이션 성능에 여유를 두려고 Redis 를 스케일업했다.
    • 애플리케이션 서버 대수를 늘렸다.
    • 애플리케이션을 고쳐 필요한 감시 데이터만 Redis 에 저장하게 해 Redis 메모리 사용량을 줄였다.
    • 부적절한 API 요청을 빨리 찾아내 대시보드에서 볼 수 있는 체계를 만들었다.
    • 부적절한 요청을 보내는 조직을 빨리 차단하는 기능을 만들었다.
    • 부적절한 요청을 더 정확히 찾아내고 API Limit 같은 기능을 더하는 것을 검토한다.
    • 애플리케이션 서버의 내부 처리 모니터링을 강화해 장애가 나기 전에 대응할 수 있게 한다.
    교훈

    Hatena 는 상세한 원인을 밝히지 못했다. 그래도 장애 조치 오작동을 막고, 애플리케이션 성능에 여유를 더 두고, Redis 에 저장하는 데이터를 줄이고, 부적절한 요청을 빨리 찾아 막으면 이번처럼 긴 장애는 막을 수 있다고 보았다. 장애가 나더라도 영향이 좁은 범위에 그치도록 하는 작업을 이어 가겠다고 했다.

  5. 증상

    2017-04-05 10:24 EDT 에 공개 서비스가 동작하지 않는다는 알림이 들어왔다. 제어판과 API 를 쓸 수 없었다. 돌고 있던 Droplet 은 계속 동작했지만, 새 Droplet 이나 다른 자원을 만들거나 관리할 수는 없었다.

    촉발

    자동 테스트를 돌리는 프로세스가 운영 환경 자격 증명을 쓰도록 잘못 설정돼 있었고, 그 결과 주 데이터베이스가 지워졌다.

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

    10:24 EDT 에 공개 서비스가 동작하지 않는다는 알림이 들어왔고, 3분 뒤 마스터의 운영 데이터베이스가 지워진 것을 확인했다.

    조치
    • 10:34 EDT 에 시간 지연 레플리카에서 복구를 시작했다.
    • 11:53 에 시간 지연 레플리카의 백업을 마쳤다.
    • 12:34 에 백업을 마스터로 복사하고 복원을 시작했다.
    • 13:31 에 마스터 복구를 마쳤고 레플리카로 백업을 복사하는 일을 이어 갔다. 15:20 에 모든 시스템이 복원됐다.
    후속 조치
    • 같은 일이 다시 없도록 특정 작업에서 주 시스템에 접근할 수 있는 권한을 크게 줄인다.
    • 데이터베이스 서버 사이의 네트워크 연결을 업그레이드한다.
    • 복구 속도를 높이도록 하드웨어를 바꾼다.
    • 개발자 실수를 막는 안전장치를 더 검토한다.
    • 데이터 복구 절차를 개선한다.
    • 고객에게 영향을 주는 장애가 날 때 실시간 정보를 더 잘 전할 방법을 찾는다.
내 클러스터에도 있는지 확인하기

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

원인별1