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

그래프

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

사례2건

2건 중 1~2번째

  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. 증상

    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 구성과 장애 조치를 어떻게 다루는지 많이 배웠다.

내 클러스터에도 있는지 확인하기

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

원인별1