GitLab 데이터베이스 삭제 사건: 5개의 백업 시스템이 동시에 침묵한 순간
공식 법원 기록, 공시, 1차 사후 분석 보고서(RCA), 복수의 언론 보도로 검증된 사건입니다. 허구적 사실 날조 0%.

2017년 GitLab 데이터베이스 삭제 사건의 엔지니어링 법의학적 재구성. 한 엔지니어의 잘못된 삭제 명령어(rm -rf) 실행이 어떻게 분산 백업 및 재해 복구 아키텍처에 내재된 5가지 개별적인 실패를 폭로하게 되었는지 분석합니다.
증거가 입증하는 것:
- 한 엔지니어가 보조 레플리카에 연결되어 있다고 착각한 채로 주(Primary) 프로덕션 데이터베이스 노드에서 디렉토리 삭제 명령어를 잘못 실행했습니다.
pg_dump, Azure 디스크 스냅샷 및 S3 동기화를 포함한 5개의 독립적인 백업 및 복구 메커니즘이 사고 당시 잘못 구성되어 있거나 조용히 실패하고 있었습니다.- 이 사고로 인해 6시간 분량의 데이터베이스 메타데이터(이슈, 댓글, 계정)가 영구적으로 손실되었으나 소스 코드 리포지토리는 별도의 스토리지 계층에 온전히 보존되었습니다.
증거가 입증하지 않는 것 (What the evidence does NOT establish):
- 이 사고가 단일 엔지니어의 중대한 과실로 인해 발생했다는 점. 주요 실패 양상은 시스템적이었습니다. 소프트웨어 아키텍처는 모든 안전망이 운영자에게 알림 없이 손상된 상태에서 단일 미검증 명령어가 주요 데이터를 파괴하도록 허용했습니다.
- 내부의 고의적인 파괴 공작 또는 외부 침해. 이 사건은 전적으로 운영 오류와 취약한 백업 인프라로 인해 발생한 자초된 결과입니다.
경영진을 위한 법의학적 요약
2017년 1월 31일, 유명한 개발자 플랫폼인 GitLab은 6시간 분량의 데이터베이스 데이터를 영구적으로 상실하는 심각한 프로덕션 중단 사고를 겪었습니다. 이 사고는 소프트웨어 엔지니어링 커뮤니티에서 “개발자가 프로덕션 데이터베이스에 실수로 rm -rf를 실행한 사건”으로 널리 기억되고 있지만, 공식 사후 분석(Post-mortem)은 이보다 훨씬 더 복잡하고 시스템적인 아키텍처 실패를 드러냅니다.
진정한 재앙은 잘못된 명령어 실행 그 자체가 아니라 5개의 독립적인 재해 복구 메커니즘이 동시에, 그리고 침묵 속에서 실패했다는 점이었습니다. 그 이전 몇 달 동안 표준 PostgreSQL 논리적 백업은 버전 불일치로 인해 실패하기 시작했고, 중요한 스토리지 볼륨에 대한 자동화된 클라우드 스냅샷은 활성화되지 않았으며, 복제 큐는 지연되었습니다. 운영자가 터미널에서 중대한 실수를 저질렀을 때, 그들이 활성화되어 있다고 믿었던 안전망이 이미 부식되어 있었기 때문에 전체 시스템 붕괴가 촉발되었습니다.
복구 과정을 라이브스트리밍하고 기술적 실수를 공개적으로 발표하는 등 근본적인 투명성으로 이 사건을 처리함으로써 GitLab은 업계에 재해 복구 계약을 정기적으로 검증하는 것의 중요성에 대한 훌륭한 사례 연구를 제공했습니다.
불일치 분석
| 시스템 계층 | 예상된 계약 (재해 복구) | 실제 시스템 동작 | 운영상의 결과 | 인식적 상태 |
|---|---|---|---|---|
논리적 백업 (pg_dump) |
안전한 스토리지에 PostgreSQL 데이터베이스의 자동화된 일일 덤프 저장 | 바이너리 버전 불일치(pg_dump 9.2 대 데이터베이스 9.6)로 인해 조용히 실패 | 복원에 사용할 수 있는 기능적인 논리적 백업 부재 | [DOCUMENTED] |
| 클라우드 디스크 스냅샷 | Azure에서 주 데이터베이스 볼륨의 자동화된 블록 레벨 스냅샷 생성 | 파일 서버에는 활성화되어 있었으나 데이터베이스 서버에는 누락됨 | 빠르고 특정한 시점의 인프라 복구 불가 | [DOCUMENTED] |
| S3 백업 동기화 | 백업 파일을 Amazon S3에 동기화하는 자동화된 cron 작업 | 동기화 스크립트가 망가져 비어있는 아카이브를 전송하고 있었음 | 오프사이트 재해 복구 스토리지에 사용 가능한 데이터가 없었음 | [DOCUMENTED] |
| 스트리밍 복제 | 보조 노드로의 지속적인 실시간 데이터 복제 | 보조 노드가 지연되었고, 사고 직전 문제 해결 시도 중에 수동으로 초기화됨 | 주 데이터베이스의 유일하게 남은 복사본이 파괴됨 | [RECONSTRUCTED] |
| LVM 스냅샷 | 주요 구조적 변경 전 생성되는 임시 블록 레벨 스냅샷 | 스냅샷은 존재했으나 전체 데이터베이스 복원을 위해 최적화되지 않음 | 운영자는 손상되기 쉬운 6시간 전의 LVM 스냅샷에서 수동으로 데이터베이스를 재구성해야 했음 | [DOCUMENTED] |
실패의 연쇄 작용
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ GITLAB 데이터베이스 중단 근본 원인 실패 사슬 │
├────────────────────────────────────────────────────────────────────────────────────────┤
│ 1. 백업 붕괴: PostgreSQL 바이너리 버전 불일치로 인해 pg_dump 조용히 실패 │
│ │ │
│ 2. 스냅샷 누락: DB 인스턴스에 대한 Azure 블록 레벨 백업이 활성화되지 않음 │
│ │ │
│ 3. 오프사이트 실패: S3 동기화 스크립트 실패, 비어있는 아카이브 저장 │
│ │ │
│ 4. 복제 지연: 보조 데이터베이스가 주 데이터베이스보다 뒤처져 알림 피로 발생 │
│ │ │
│ 5. 인적 개입: 운영자가 복제를 수정하기 위해 보조 DB를 초기화 시도 │
│ │ │
│ 6. 터미널 혼동: 운영자가 주 노드에서 파괴적인 디렉토리 삭제 명령어 실행 │
│ │ │
│ 7. 완전한 파괴: 주 데이터 삭제; 5개의 모든 안전 메커니즘 비활성화 상태 │
│ │ │
│ 8. 미션 손실: 6시간 분량의 프로덕션 메타데이터 상실; 18시간의 글로벌 서비스 중단 │
└────────────────────────────────────────────────────────────────────────────────────────┘
1막: 이상 징후와 지연된 복제
치명적인 데이터 손실로 이어지는 일련의 사건은 단순히 폴더 하나가 삭제되면서 시작된 것이 아닙니다. 사건은 몇 시간 전 인프라의 일상적인 이상 징후로 인해 발생했습니다.
2017년 1월 31일 저녁, GitLab 운영 팀은 데이터베이스 로드가 급증하는 것을 감지했습니다. 악성 트래픽 또는 최적화되지 않은 트래픽이 주(Primary) PostgreSQL 데이터베이스를 압도하고 있었고 이로 인해 보조(Secondary) 읽기 레플리카가 심각하게 뒤처지게 되었습니다. 보조 데이터베이스를 주 데이터베이스와 완벽하게 동기화하도록 설계된 스트리밍 복제 프로세스가 지연되기 시작했습니다.
복제 지연이 증가함에 따라 자동화된 알림이 발생했습니다. 즉각적인 성능 저하와 싸우던 운영 팀은 건강한 복제를 복원하는 가장 빠른 방법이 지연된 보조 데이터베이스를 초기화하고 복제 프로세스를 처음부터 수동으로 재시작하는 것이라고 판단했습니다. 이것은 다소 공격적이지만 표준적인 운영 절차였습니다.
이 시점에 시스템은 고도로 취약한 상태에 진입했습니다. 즉각적인 페일오버 안전망인 보조 레플리카가 의도적으로 오프라인 상태가 되었습니다. 주 데이터베이스는 이제 모든 프로덕션 메타데이터의 단일 장애점이 되었습니다. 운영자는 자동화된 백그라운드 백업(예: pg_dump 아카이브 및 클라우드 스냅샷)이 백그라운드에 안전하게 누적되고 있다는 잘못된 가정을 바탕으로 절차를 진행했습니다. 하지만 그렇지 않았습니다.
2막: 터미널 혼동과 덫의 아키텍처
보조 데이터베이스가 초기화된 후 한 엔지니어가 복제 프로세스 재시작을 시도했습니다. 그러나 복제는 계속해서 중단되었고 진행되지 않았습니다. 인프라의 고집에 좌절한 엔지니어는 여러 SSH 터미널 창을 열고 주 데이터베이스 서버(db1.cluster.gitlab.com)와 보조 데이터베이스 서버(db2.cluster.gitlab.com) 사이를 빠르게 전환했습니다.
이 덫의 구조는 단순한 기술적인 것이 아니라 인지적인 것이었습니다. 주 서버와 보조 서버의 터미널 프롬프트는 시각적으로 동일했습니다. 뚜렷한 색상 코딩이나 경고 배너도 없었고, 주 노드에서 파괴적인 명령어가 실행되는 것을 막는 시스템적 마찰도 없었습니다.
고집스러운 보조 서버에 연결되어 있다고 착각한 엔지니어는 복제 재시작을 한 번 더 시도하기 위해 PostgreSQL 데이터 디렉토리를 강제로 삭제하기로 결정했습니다. 그들은 데이터베이스 디렉토리를 제거하는 명령어인 rm -rf /var/opt/gitlab/postgresql/data를 입력했습니다.
명령어는 완벽하게 실행되었습니다. 몇 초 이내에 엔지니어는 터미널이 주 프로덕션 데이터베이스인 db1에 연결되어 있다는 것을 알아차렸습니다. 그들은 즉시 Ctrl+C를 눌러 명령어를 취소했지만, 피해는 돌이킬 수 없는 상태였습니다. 단 3초 만에 약 300 기가바이트의 중요한 프로덕션 데이터가 영구적으로 삭제되었습니다.
3막: 5가지 침묵의 실패 발견
패닉은 즉시 재해 복구 모드로 전환되었습니다. 주 데이터베이스는 사라졌지만, 표준 운영 절차에 따르면 이는 관리가 가능한 시나리오였습니다. 팀은 단순히 가장 최근의 자동화된 백업에서 데이터베이스를 복원하기만 하면 되었습니다.
아키텍처 실패의 진정한 규모가 명백해진 것은 바로 이때였습니다. 팀이 5가지 개별 재해 복구 메커니즘에 접근을 시도했을 때 각 메커니즘이 조용히 실패했음을 발견했습니다.
- 논리적 백업: 팀이 자동화된
pg_dump파일을 확인했을 때 사실상 비어 있음을 발견했습니다. PostgreSQL 9.6 데이터베이스에 대해 PostgreSQL 9.2 덤프 도구를 실행하는 미묘한 버전 불일치로 인해 자동화된 작업이 침묵 속에서 실패했고 기가바이트의 데이터 대신 단 몇 킬로바이트의 메타데이터만 포함된 파일이 생성되었습니다. - 클라우드 스냅샷: 팀은 단순히 가상 머신을 롤백할 수 있을 것이라 가정하고 Azure 블록 레벨 디스크 스냅샷으로 전환했습니다. NFS 파일 서버에는 스냅샷이 적극적으로 구성되어 있었지만 데이터베이스 서버에는 한 번도 활성화되지 않았다는 것을 발견했습니다.
- S3 오프사이트 스토리지: 오프사이트의 기적을 바라며 그들은 백업이 동기화되기로 되어있던 Amazon S3 버킷을 확인했습니다. 버킷은 비어 있었습니다. 전송을 담당하는 cron 작업이 몇 주 동안 망가져 있었습니다.
- 복제 노드: 표준 고가용성 페일오버인 보조 데이터베이스는 단 몇 분 전에 팀에 의해 의도적으로 지워졌으므로 완전히 쓸모가 없었습니다.
- 손상되기 쉬운 LVM 스냅샷: 마침내 팀은 관련 없는 인프라 테스트를 위해 약 6시간 전에 다른 엔지니어가 촬영한 단일 LVM(Logical Volume Manager) 스냅샷을 찾았습니다. 그것이 데이터베이스의 유일한 생존 복사본이었습니다.
팀은 이 6시간 된 LVM 스냅샷에서 프로덕션 데이터베이스를 수동으로 추출하고 재구성해야 했습니다. LVM 스냅샷 전송 프로세스가 극도로 느렸기 때문에 복원 프로세스는 18시간 이상 걸렸습니다.
시스템 예방 플레이북
GitLab 운영 중단은 복원이 성공적으로 테스트되기 전까지 백업 메커니즘은 전적으로 이론에 불과하다는 것을 보여주는 전형적인 사례입니다. 이와 유사한 연쇄 실패를 방지하기 위해 현대적인 소프트웨어 인프라는 3가지 등급의 방어 수단을 배치해야 합니다.
1. 마찰 방어 (인지 및 UI 제약)
- 시각적 터미널 구분: 프로덕션 주 노드는 보조 또는 스테이징 노드와 시각적으로 차별화되어야 합니다. 서로 다른 bash 프롬프트 색상(예: 주 데이터베이스는 밝은 빨간색)을 구현하면 즉각적인 인지적 마찰을 제공합니다.
- 필수 동료 검증: 중요한 디렉토리에서
rm -rf와 같은 파괴적인 명령어는 보조 운영자의 승인이나 고도로 구체적인 질의응답 플래그를 요구해야 합니다.
2. 경계 제약 (아키텍처 안전성)
- 자동화된 복원 테스트: 샌드박스 환경에서 정기적이고 자동적으로 복원되지 않는 백업은 무효한 것으로 간주해야 합니다. 자동화된 파이프라인은 최신
pg_dump를 가져와 임시 데이터베이스를 인스턴스화하고 데이터 무결성을 보장하기 위해 검증 쿼리를 실행해야 합니다. - 역할 기반 접근 제어 (RBAC) 강화: 일상적인 유지 관리 계정은 주 데이터베이스 디렉토리를 삭제하는 데 필요한 근본적인 파일 시스템 권한을 보유해서는 안 됩니다. 데이터베이스 해체에는 상승된 임시 자격 증명이 필요해야 합니다.
3. 비상 브레이크 (시스템 중단)
- 변경 불가능한 클라우드 스냅샷: 클라우드 인프라는 운영 체제의 내부 구성과 완전히 분리된 하이퍼바이저 수준에서 정책 중심의 불변 블록 레벨 스냅샷을 강제해야 합니다. 엔지니어가 OS 파일을 삭제하더라도 하이퍼바이저 스냅샷은 그대로 유지됩니다.
- 조용한 실패에 대한 알림: 전송된 바이트 수가 0인 상태로 완료되거나 0이 아닌 상태 코드로 종료되는 백업 작업은 가장 높은 수준의 페이징 알림을 트리거해야 합니다. 성공적인 백업의 부재는 단순한 백그라운드 경고가 아니라 중대한 시스템 장애입니다.
엔지니어링 진화: 당시와 현재 (Then vs Now)
| 방어 계층 | 당시 (2017 아키텍처) | 현재 (최신 표준) |
|---|---|---|
| 백업 검증 | cron 작업이 종료되면 성공한 것으로 간주 | 데이터 무결성을 증명하기 위해 샌드박스 환경에서 자동화된 복원 테스트 진행 |
| 터미널 운영 | 스테이징, 보조 및 주 노드 간에 시각적으로 동일한 bash 프롬프트 | 인지적 마찰: 빨간색의 프로덕션 프롬프트 및 파괴적인 명령어에 대한 필수 질의응답 (Challenge-response) |
| 스냅샷 불변성 | 중요한 데이터베이스 계층에 대해 스냅샷이 완전히 부재함 | OS 수준의 rm -rf에 영향을 받지 않는, 하이퍼바이저 수준에서 강제되는 불변의 블록 레벨 클라우드 스냅샷 |
| 알림 우선순위 | 지연된 복제 큐가 일반적인 알림 피로를 유발함 | 조용한 백업 실패 또는 0바이트 덤프는 최우선(sev-1) 프로덕션 중단으로 취급됨 |
아키비스트의 판결
아키비스트의 분석: 2017년 GitLab 데이터베이스 삭제 사건은 종종 단일 개인의 실패로 잘못 분류됩니다. 하지만 사실 이 사건은 심층 방어(defense-in-depth)의 시스템적 실패를 보여주는 교과서적인 사례입니다.
파괴적인 명령어를 실행한 엔지니어는 길고 긴 조직적, 아키텍처적 부패 사슬의 마지막 방아쇠에 불과했습니다. 강력한 엔지니어링 문화는 스트레스가 심한 장애 상황 동안 운영자가 완벽한 인지 능력을 유지하는 것에 의존하지 않습니다. 오히려 재앙적인 입력을 적극적으로 거부하는 시스템에 의존합니다. 5개의 개별적인 재해 복구 메커니즘이 중대한 운영 경보를 발생시키지 않고 조용히 실패하도록 방치함으로써, 아키텍처는 단 한 번의 터미널 오류가 완전한 데이터 파괴로 이어질 것을 보장한 셈입니다.
이 사건이 남긴 진정한 유산은 기술적 오류가 아닙니다. 이어진 GitLab의 근본적인 투명성이야말로 글로벌 엔지니어링 커뮤니티에 ’테스트되지 않은 백업은 결코 백업이 아니다’라는 영구적이고 부정할 수 없는 진리를 제공했습니다.
자주 묻는 질문 (FAQ)
2017년 GitLab 데이터베이스 운영 중단 사고의 원인은 무엇인가요?
한 엔지니어가 보조 노드가 아닌 주(Primary) 프로덕션 데이터베이스 서버에서 실수로 데이터베이스 디렉토리 삭제 명령어(rm -rf)를 실행했습니다. 이 인적 오류는 당시 5개의 표준 백업 및 복제 메커니즘이 모두 침묵 속에서 실패하고 있었다는 사실과 겹쳐 심각한 서비스 중단을 초래했습니다.
GitLab 사고 중 실제로 손실된 데이터는 어느 정도인가요?
GitLab은 해당 6시간 동안 생성된 사용자 계정, 이슈, 머지 리퀘스트 및 댓글을 포함하여 약 6시간 분량의 데이터베이스 데이터를 잃었습니다. 다행히 Git 리포지토리 데이터(소스 코드)는 별도의 파일 서버에 저장되어 있었기 때문에 전혀 영향을 받지 않았습니다.
데이터베이스가 삭제되었을 때 GitLab의 백업은 왜 작동하지 않았나요?
GitLab은 5가지의 개별적인 백업 실패를 겪었습니다. 표준 pg_dump 백업은 PostgreSQL 버전 불일치로 인해 실패하고 있었고, Azure 디스크 스냅샷은 데이터베이스 서버에 활성화되어 있지 않았습니다. LVM 스냅샷은 존재했지만 신속한 데이터베이스 복원을 위해 최적화되지 않았으며, 자동화된 S3 백업 동기화는 중단된 상태였습니다. 마지막으로 보조 복제 노드는 문제 해결 시도 중 사고 직전에 이미 초기화되어 있었습니다.
복구 과정에서 GitLab의 투명성은 어떠했나요?
GitLab은 근본적인 투명성으로 널리 찬사를 받았습니다. 그들은 복구 단계를 자세히 설명하는 공개적이고 실시간으로 업데이트되는 Google 문서를 유지했으며, 데이터베이스 복원 프로세스를 YouTube에 라이브스트리밍하고 소셜 미디어에서 공개적으로 소통하여 치명적인 실패를 사고 커뮤니케이션의 훌륭한 사례로 바꾸었습니다.
사고 이후 GitLab은 어떤 엔지니어링 변경을 구현했나요?
사고 이후 GitLab은 재해 복구 아키텍처를 전면 개편했습니다. 그들은 백업 복원의 자동화되고 모니터링되는 테스트를 구현했고, PostgreSQL pg_dump 버전 불일치를 수정했으며, 주 노드의 파괴적인 명령어에 대한 더 엄격한 접근 제어를 시행하고, 데이터 내구성을 보장하기 위해 보조 복제 인프라를 재설계했습니다.
인적 오류가 GitLab 삭제의 진짜 원인인가요?
인간의 오타가 기술적인 방아쇠였지만, 시스템적 실패는 심층 방어의 부재와 모든 백업 메커니즘의 조용한 붕괴였습니다. 개별 엔지니어를 비난하는 것은 시스템이 기능적 안전망 없이 치명적인 단일 지점 파괴를 허용했다는 복잡한 아키텍처 붕괴를 단순화하는 것입니다.
공식 1차 출처
- Official GitLab Postmortem of database outage of January 31
- GitLab Database Incident Live Tracking Document (Archive)
- PostgreSQL pg_dump Documentation
증거 보관소 & 팩트체크 출처
ErrorLedger 인식론적 검증 표준 및 공공 증거 기록Court Filings & Public Records