사례6건
6건 중 1~5번째
- 증상
2025-03-10 16:23 UTC 무렵 FR-PAR 리전의 모든 제품에서 공용 인터넷 연결이 크게 흔들렸다. 인터넷 트래픽 대부분이 사실상 버려졌고, FR-PAR-2 가용 영역과 나머지 PAR 리전 사이의 공용 인터넷 연결이 심하게 끊겼다.
- 촉발
Scaleway 네트워크 팀이 FR-PAR 리전 백본에 새 데이터 센터를 붙이던 중 라우터 구성을 잘못 넣었다. 이 실수로 OpCore DC3 와 DC5 사이의 1Tbps 넘는 트래픽이 100Gbps 링크 하나로 돌아갔다.
- 원인
- 구성 요소
- 기여 요인
- 감지
라우터 구성 실수는 빨리 발견되어 4분 안에 롤백됐다.
- 조치
- 잘못 넣은 라우터 구성을 4분 안에 롤백해 16:27 UTC 에 올바른 구성을 되돌렸다.
- 후속 조치
- 변경 관리를 고쳐 동료 검토와 운영 공지 절차를 강화한다.
- 백본 수준의 네트워크 구성을 적용하기 전에 안전장치와 시험을 더 거치도록 운영 절차를 고친다.
- Object Storage 동기화 소프트웨어의 문제를 찾아 수정을 만들고 시험했으며, 이 수정을 배포하고 있다.
- 증상
Facebook 데이터 센터 사이의 서버 연결과 데이터 센터와 인터넷 사이의 서버 연결이 한꺼번에 완전히 끊겼다. DNS 서버는 동작하고 있었지만 인터넷에서 닿지 않아 누구도 Facebook 서버를 찾을 수 없었다. 백본이 통째로 빠지자 DNS 서버가 있는 작은 시설들이 스스로 비정상이라고 판단해 BGP 광고를 거둬들였기 때문이다.
- 촉발
일상적인 유지보수 작업 중에 전 세계 백본 용량의 가용성을 평가하려고 내린 명령이 의도치 않게 백본 네트워크의 모든 연결을 끊었다. 이런 명령을 검사해 실수를 막는 감사 도구가 버그 때문에 이 명령을 멈추지 못했다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- 주 네트워크 접근과 out-of-band 접근이 모두 끊겨, 팀은 엔지니어를 데이터 센터 현장에 보내 문제를 디버깅하고 시스템을 다시 시작하게 했다.
- 보안 접근 절차를 거쳐 현장 인력이 서버를 다룰 수 있게 된 뒤 문제를 확인하고 백본을 다시 온라인으로 올렸다.
- storm 훈련에서 얻은 경험을 살려 서비스를 다시 켜면서 늘어나는 부하를 조심스럽게 관리했다.
- 후속 조치
- 전 세계 백본이 끊기는 상황을 storm 훈련으로 시뮬레이션할 방법을 찾는다.
- 테스트와 훈련, 전반적인 복원력을 강화해 이런 사고가 최대한 드물게 일어나게 한다.
- 교훈
무단 접근을 막으려고 강화한 보안이, 공격이 아니라 스스로 낸 실수에서 비롯된 장애의 복구를 늦췄다. Meta 는 드문 사고에서 복구가 느려지더라도 평소의 보안을 크게 높이는 편이 낫다고 봤다. 서비스, 데이터 센터, 리전 전체를 내리는 storm 훈련이 부하를 다시 올리는 데 도움이 됐지만, 전 세계 백본이 끊기는 상황은 훈련해 본 적이 없었다.
- 증상
Mackerel 을 온프레미스 데이터 센터에서 AWS 로 옮긴 뒤 애플리케이션 동작을 확인하다가, 특정 시간대의 데이터가 사라진 것을 발견했다. 2017년 8월 7일 14시 30분부터 15시 30분 사이에 PostgreSQL 서버에서 갱신된 데이터가 없었다.
- 촉발
새 마스터인 db001 로 접속을 바꾸고 한 시간 뒤 db001 과 네트워크 통신이 끊겼고, 복제가 멈춰 있던 스탠바이 서버 db002 로 의도하지 않은 장애 조치가 일어났다.
- 원인
- 구성 요소
- 기여 요인
- 감지
마이그레이션 작업 뒤 애플리케이션 동작을 확인하던 중 특정 시간대의 데이터가 사라진 것을 발견했다.
- 조치
- db001 에 남은 테이블 데이터로 손으로 복구할 수 있는지 검토했지만, 이미 많은 데이터가 갱신되어 테이블 사이 정합성을 지키며 db002 에 반영하기 어렵다고 보고 포기했다.
- 점검 전 베이스 백업, db001 에 남은 WAL, 백업 서버로 보내 둔 WAL 아카이브로 PostgreSQL 의 PITR 복구를 시도했지만, 갈라진 두 타임라인을 이어서 복구할 수 없어 포기했다.
- 장애 조치 직후 db002 를 마스터로 하고 새 슬레이브 서버 db003 을 만들어 db002 와 db003 으로 이중화했다.
- 장애가 난 db001 은 조사용으로 점검 상태에 남겨 두었다.
- db002 에서 db001 과 같은 문제가 나지 않는지 일정 시간 지켜본 뒤 마이그레이션 점검을 마쳤다.
- 후속 조치
- PostgreSQL 레플리카 생성 스크립트가 recovery.conf 에 recovery_target_timeline = 'latest' 를 기본으로 넣도록 바꾼다.
- Serverspec 같은 서버 구성 관리 테스트 도구에 recovery.conf 안에 recovery_target_timeline = 'latest' 문자열이 있는지 확인하는 항목을 더한다.
- 교훈
Hatena 는 이 문제가 평소 운영에서는 일어나지 않지만, PostgreSQL 버전을 올리거나 다른 리전으로 옮길 때 같은 구성을 다시 쓸 수 있다고 보았다. recovery_target_timeline = 'latest' 는 평소 스탠바이 서버에 두어도 문제가 없으므로, 사람이 빠뜨릴 여지를 없애려고 슬레이브를 만들 때 기본으로 넣도록 운영을 바꿨다. 이 설정을 쓰려는 사람은 자기 구성에서 문제가 없는지 먼저 확인하라고 덧붙였다.
- 증상
OpenStack 호스트 서버가 다운되어 ElasticSearch 노드 하나가 내려간 뒤, API 서버 쪽 ElasticSearch 헬스 체크가 false 를 반환했다. Head 플러그인으로 본 클러스터 상태는 그린이었다.
- 촉발
OpenStack 호스트 서버가 다운되어 30대짜리 ElasticSearch 클러스터의 노드 하나가 내려갔다.
- 원인
- 구성 요소
- 기여 요인
- 감지
API 서버가 ElasticSearch 에 하는 헬스 체크가 false 를 반환했다. 클러스터 상태는 Head 플러그인에서 그린으로 보였다.
- 조치
- 호스트가 언제 다시 다운될지 몰라, 복구된 ElasticSearch 노드 서버를 다른 호스트 서버로 마이그레이션했다.
- 마이그레이션 뒤 ElasticSearch 프로세스를 띄워 노드를 클러스터에 다시 넣었다.
- 헬스 체크를 되살리려고 1번 노드부터 로그를 보며 차례로 전체 재시작했지만, 스무 번째 노드까지 재시작했을 즈음 API 서버 지연이 생겨 멈췄다.
- 다시 1번 노드부터 차례로 전체 재시작해 API 서버 지연과 헬스 체크를 되살렸다.
- _cluster/reroute 의 allocate 명령으로 unassigned 샤드를 옮기려 했지만 오류가 나서 실패했다.
- A 인덱스의 53번 샤드는 22번 노드에만 파일이 남아 있었다. 그래서 프로세스를 멈추고 그 파일을 디렉터리만 남은 3번 노드와 10번 노드로 복사한 뒤, 22번 노드의 상태 파일만 "primary" 를 true 로 바꿨다.
- B 인덱스의 51번 샤드는 lucene-core 검사로 27번 노드 쪽이 망가진 것을 확인했다. 27번 노드의 파일을 지운 뒤 28번 노드의 파일을 27번 노드와 다른 노드로 복사하고, 28번 노드만 "primary" 를 true 로 바꿨다.
- C 인덱스의 2번 샤드는 27번 노드에만, 4번 샤드는 25번 노드에만 파일이 남아 있었다. 그래서 각 파일을 다른 두 노드로 복사하고, 복사한 쪽의 상태 파일은 "primary" 를 false 로 바꿨다.
- 후속 조치
- 오래된 ElasticSearch 버전을 그만 쓰고 버전을 올린다.
- 교훈
재시작할 때는 자동 재배치를 끄고 작업해야 했다. 노드 하나를 재시작한 뒤에는 로그만 볼 것이 아니라 재배치가 완전히 끝나는 것을 보고 나서 다음 노드를 재시작해야 했다.
- 증상
2012-12-24 PST 오후 12시 24분부터 US-East 리전의 ELB 제어 평면에서 로드 밸런서를 관리하는 API 호출의 지연과 오류율이 올랐다. 이때는 돌고 있는 로드 밸런서의 요청 처리에 영향이 없었다.
- 촉발
운영 환경에 접근할 수 있는 아주 적은 수의 개발자 가운데 한 명이 유지보수 프로세스를 실수로 운영 ELB 상태 데이터를 대상으로 실행해 데이터 일부를 논리적으로 지웠다. 그 개발자는 그때 실수를 알아채지 못했다.
- 원인
- 구성 요소
- 기여 요인
- 감지
데이터가 지워진 뒤 ELB 제어 평면에서 로드 밸런서를 관리하는 API 호출의 지연과 오류율이 올랐고, 기술팀은 이 API 오류부터 살폈다. 사라진 상태 데이터는 팀이 성능이 떨어진 로드 밸런서를 깊이 파고든 뒤에야 찾았다. 데이터를 지운 개발자는 그때 실수를 알아채지 못했다.
- 조치
- PST 오후 5시 2분에 확장과 축소 워크플로를 포함한 ELB 제어 평면 워크플로 여러 개를 꺼서, 돌고 있는 다른 로드 밸런서가 사라진 상태 데이터의 영향을 받지 않게 했다.
- 영향받은 로드 밸런서 가운데 일부를 월요일 밤에 손으로 복구했다.
- 처음 쓴 복원 방법이 몇 시간 걸리고도 쓸 수 있는 스냅샷을 만들지 못하자 다른 복구 절차를 찾아, 12월 25일 PST 오전 2시 45분에 데이터가 지워지기 직전 시점의 ELB 상태 데이터 스냅샷을 복원했다.
- 복원한 데이터에 스냅샷 이후의 시스템 상태 변경을 합쳤고, 오전 5시 40분에 병합과 새 상태 데이터 검증을 마쳤다.
- 영향받지 않은 로드 밸런서를 건드리지 않고 영향받은 로드 밸런서마다 제대로 복구되도록 ELB 워크플로와 API 를 천천히 다시 켰다. 오전 8시 15분에 대부분의 API 와 백엔드 워크플로가 다시 켜졌고, 오전 10시 30분에 영향받은 로드 밸런서가 거의 모두 정상으로 돌아왔다.
- 후속 조치
- 운영 ELB 상태 데이터의 접근 통제를 바꿨다. 상시 권한으로 잘못 설정된 접근을 되돌렸고, 운영 ELB 데이터에 접근할 때마다 사고 건별 Change Management 승인을 받게 했다.
- 이번에 배운 것을 반영해 데이터 복구 절차를 고쳤다. AWS 는 비슷한 일이 생기면 ELB 상태 데이터를 훨씬 빨리 복구할 수 있다고 봤다.
- ELB 제어 평면 워크플로가 중앙 서비스 데이터와 현재 로드 밸런서 상태를 더 신중하게 맞추도록 다시 짜, 논리적 데이터 손실이나 손상이 생겨도 손으로 복원하지 않고 자동으로 복구되게 한다.
이 6건에서 가장 많이 나오는 구성 요소: 백본망, 데이터베이스. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.
원인별1
운영 실수6건
- 구성 요소
- 기여 요인
IL-0348FR-PAR 리전의 모든 제품에서 공용 인터넷 연결이 끊기고 여러 제품이 오래 불안정했다Scaleway2025IL-0221유지보수 명령이 Facebook 백본 네트워크의 연결을 모두 끊어 데이터 센터와 DNS 서버가 인터넷에서 닿지 않게 됐다.Meta2021IL-0431AWS 로 옮기는 점검 중 PostgreSQL 이 의도하지 않게 장애 조치되어 한 시간 동안 갱신된 데이터가 사라졌다Hatena2017IL-0434ElasticSearch 0.19 클러스터 전체 재시작 뒤 샤드 12개가 unassigned 로 남아 데이터 일부를 읽을 수 없었다CyberAgent2016IL-0224유지보수 작업이 운영 ELB 상태 데이터 일부를 지워 US-East 리전의 Elastic Load Balancer 일부가 오류를 내고 나머지는 확장하거나 바꿀 수 없게 됐다.IL-0337US East 리전 한 가용 영역에서 네트워크 변경으로 EBS 노드가 복제본과 끊겨 EBS 볼륨이 멈췄다