사례3건
3건 중 1~3번째
- 증상
Logs 클러스터의 노드 하나가 죽었고, 다시 시작하는 중에 찾을 수 없는 데이터가 너무 많아 뜨지 못했다. 엔지니어가 확인해 보니 S3 에 저장된 데이터 대부분이 없었다.
- 촉발
인덱스를 materialize 하는 일상적인 mutation 이 끝나면서 ClickHouse 의 zero-copy replication 버그가 터졌고, 복제본 하나가 데이터베이스의 모든 데이터 파트를 더는 아무도 참조하지 않는다고 잘못 판단했다.
- 원인
- 구성 요소
- 기여 요인
- 감지
19:40 UTC 에 클러스터 노드 하나가 죽었고, 재시작하다 없는 데이터가 많아 뜨지 못했다. 엔지니어가 이를 조사하다 S3 에 저장된 데이터 대부분이 없는 것을 발견했다. 그 전 8시간 동안 자동 알람은 하나도 울리지 않았다.
- 조치
- zero-copy replication 을 쓰지 않는 새 테이블로 전환하고 최근 메시지를 따라잡았다.
- 보존 기간 3일인 Kafka 기록에서 데이터를 새 테이블로 백필했다. 2월 20일 10:05 UTC 에 시작해 12:21 에 끝났다.
- 후속 조치
- 모든 클러스터에서 Zero Copy Replication 을 바로 끈다.
- Logs ClickHouse 설정 전체를 감사하고 운영 환경에서 실험 기능을 쓰지 않게 한다.
- 저장소 버킷에 S3 Versioning 을 켜서 데이터베이스가 버그로 파괴적인 명령을 내도 객체를 되살릴 수 있게 한다.
- 제품을 정식 출시하기 전에 설정과 데이터 무결성 전략을 표본 점검한다. 이 점검으로 단일 장애 지점을 찾아 고친다.
- 교훈
Logs 제품을 따로 떼어 둔 덕분에 다른 제품과 기능은 전혀 영향을 받지 않았고, Kafka 보존 기간 3일 덕분에 최근 데이터는 잃지 않았다. 반면 MVP 와 알파 단계에 쓰려던 실험 설정이 운영 환경까지 그대로 남았다. PostHog 는 들어오는 데이터와 핫 데이터의 상태만 감시해 과거 데이터가 지워지는 것을 보지 못했다. 공유 저장소를 쓰면서 데이터 내구성을 데이터베이스 복제에만 맡겨 단일 장애 지점이 생겼고, S3 Versioning 이 없어 지워진 파일을 되살릴 수 없었다.
- 증상
5.44pm UTC 쯤 Google Container Registry 에서 이미지를 받을 때 cannot get manifest 오류가 많이 났다. 약 10분 뒤 사용자들이 워크스페이스를 시작할 수 없다고 보고했고, 이미 돌던 워크스페이스는 데이터를 잃었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
5.44pm UTC 쯤 팀이 GCR 에서 이미지를 받을 때 cannot get manifest 오류율이 높아진 것을 알아챘다. 약 10분 뒤 사용자들이 워크스페이스를 시작할 수 없다고 보고했고, 당번 팀이 장애 대응을 시작했다.
- 조치
- GCR 연결 문제를 조사하는 동안 예방 조치로 werft 작업을 돌려 EU 와 US 에 새 워크스페이스 클러스터를 만들기 시작했다. 만드는 데 약 20분 걸렸다.
- 새 클러스터에 문제가 없음을 확인하고 트래픽을 새 클러스터로 돌렸다. 곧 워크스페이스가 시작됐고 사용자들이 Discord 에서 시작된다고 알려 왔다.
- 후속 조치
- 노드와 클러스터가 실패해도 남는 클라우드 사업자의 영구 볼륨에 사용자 데이터를 저장한다.
- 워크스페이스가 시작할 수 없는 상태가 되어도 사용자가 파일을 내려받을 수 있게 한다. 지금은 워크스페이스가 멈춰 있을 때만 내려받을 수 있다.
- 백업 절차 개선을 우선으로 진행한다.
- DNS 서버 하나에 기대지 않고 GCP 내부 DNS, Google 의 공개 DNS 8.8.8.8, Cloudflare 의 1.1.1.1 세 곳을 쓰도록 바꿨다. 하나에 문제가 나도 나머지에 연결할 수 있다.
- DNS 복원력을 높이는 작업을 더 진행한다.
- 여러 리전의 클러스터 지원을 늘린다. 지금은 US 와 EU 두 곳뿐이고, 나중에는 여러 클라우드를 쓰는 것도 계획한다.
IL-0229손상된 SmartEdge 데이터 파일을 받은 bunny.net 의 전 세계 DNS 서버가 크래시를 되풀이해 플랫폼 대부분이 2시간 넘게 멈췄다.bunny.net2021- 증상
2021-06-22 UTC 8:25 에 업데이트를 내보내고 몇 분 만에 전 세계에 있는 100대 가까운 bunny.net DNS 서버가 거의 모두 죽었다. bunny.net 은 트래픽의 60% 넘게 잃었고, 수백 Gbit 의 처리량이 사라졌으며, 750,000개가 넘는 웹사이트가 영향을 받았다.
- 촉발
2021-06-22 UTC 8:25 에 최적화 데이터베이스의 다운로드 크기를 줄이려는 업데이트가 손상된 파일을 Edge Storage 에 올렸다. DNS 서버가 이 파일을 읽자 BinaryPack 직렬화 라이브러리가 stack overflow 예외를 일으켰고, 예외 처리를 건너뛴 채 DNS 프로세스가 종료됐다.
- 원인
- 구성 요소
- 기여 요인
- 감지
팀은 무슨 일인지 알아채는 데 시간이 걸렸다. 업데이트 10분 뒤에야 DNS 서버가 다시 시작했다가 죽기를 되풀이하고 있고, 이 상태로는 되살릴 방법이 없다는 것을 알았다.
- 조치
- UTC 8:45 에 SmartEdge 시스템을 끄는 업데이트를 DNS 노드에 손으로 배포했다. 하지만 손상된 GeoDNS 데이터베이스 때문에 요청이 Madrid 로 몰렸다.
- 9:40 무렵 임시 조치로 모든 요청을 가장 큰 리전인 Frankfurt 로 보내는 라우팅 업데이트를 준비해 DNS 서버 몇 대에 손으로 배포했다. 트래픽의 상당 부분이 돌아왔다.
- 자체 시스템을 쓰지 않으려고 배포 시스템과 파일을 모두 외부 클라우드 스토리지 서비스로 옮겼다.
- 10:15 에 배포 시스템과 DNS 소프트웨어를 새 스토리지에 연결하도록 바꾸고 배포했다. 10:30 에 트래픽이 돌아왔지만 잘못된 GeoDNS 데이터베이스 버전 때문에 요청은 여전히 Madrid 로 갔다.
- 10:45 에 외부 서비스를 거쳐 데이터베이스를 동기화하고 최신 파일 세트를 배포해 서비스를 되살렸다. 11:00 에 상황이 안정되기 시작했다.
- 후속 조치
- 긴급 수정으로 BinaryPack 라이브러리를 단계적으로 걷어 낸다.
- 앞으로 쓰는 외부 라이브러리를 더 폭넓게 시험한다.
- 내부 API 를 외부의 독립 서비스로 완전히 옮긴다. 그 서비스가 내려가면 업데이트를 못 하지만, bunny.net 시스템이 내려가도 무너지는 인프라에 갇히지 않고 빠르게 대응할 수 있다.
- 중요하지 않다고 본 소프트웨어 하나가 여러 클러스터에 걸친 단일 장애 지점이 되지 않게 하는 방법을 조사한다.
- DNS 시스템이 모든 백업 데이터의 로컬 사본을 갖추고 장애를 자동으로 감지하게 해, 시스템끼리 최대한 독립시키고 장애가 연쇄로 번지지 않게 한다.
- 교훈
bunny.net 은 내부 인프라의 핵심 부분까지 모든 시스템이 서로 기대도록 설계했다. 그 때문에 손상된 파일 하나가 여러 겹의 이중화를 무너뜨리고 복구할 길까지 막았다. 자체 인프라를 자기 생태계 안에 지으면 한 곳의 장애가 연쇄로 번질 수 있다. 업데이트는 카나리 방식으로 잘게 배포하려 했지만, 중요하지 않다고 본 소프트웨어 하나가 여러 클러스터에 동시에 걸친 단일 장애 지점이 됐다. 급하게 고치는 동안 오타와 실수가 늘었고, 결국 침착하게 모든 것을 다시 확인한 뒤의 마지막 배포로 복구했다.
이 3건에서 가장 많이 나오는 구성 요소: 오브젝트 스토리지, CDN 과 엣지 네트워크. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.