Incident Library

IL-0210 GitHub · 2018-10-21databasenetworking

43초 네트워크 단절 뒤 MySQL 프라이머리가 미국 서부로 넘어가 GitHub.com 이 24시간 11분 동안 느려지고 오래된 데이터를 보여 줬다

GitHub 은 사용자용 서비스 대부분을 자체 데이터센터에서 운영하고, Git 객체가 아닌 메타데이터를 기능별로 나눈 여러 MySQL 클러스터에 저장한다. 쓰기는 클러스터마다 프라이머리로, 읽기는 대부분 복제본으로 보낸다. 토폴로지 관리와 자동 페일오버는 Raft 합의 위에 만든 Orchestrator 가 맡는다. 2018년 10월 21일 22:52 UTC 에 광 장비 교체 작업으로 동부 네트워크 허브와 동부 주 데이터센터 사이가 43초 동안 끊겼다. 이 사이 동부 주 데이터센터에 있던 Orchestrator 는 리더 자리에서 물러났고, 서부 데이터센터와 동부 퍼블릭 클라우드의 Orchestrator 노드가 쿼럼을 이뤄 클러스터들의 프라이머리를 서부로 넘겼다. 연결이 돌아오자 애플리케이션은 바로 서부 프라이머리에 쓰기 시작했고, 동부에 남은 몇 초 분량의 복제되지 않은 쓰기 때문에 양쪽 데이터가 갈라졌다.

대응 팀은 23:07 UTC 에 배포 도구를 잠갔고, 23:09 UTC 에 상태를 노란색으로, 23:13 UTC 에 빨간색으로 올렸다. 서부에 30분 넘게 쓰인 데이터를 지키려고 동부로 되돌리는 대신 서부의 현재 상태에서 복구를 이어 가기로 했다. 데이터 정합성을 사이트 사용성과 복구 시간보다 앞에 두어 웹훅 전송과 GitHub Pages 빌드를 멈췄다. 계획은 백업에서 복원하고, 두 사이트의 복제본을 맞추고, 안정된 토폴로지로 돌아간 뒤, 쌓인 작업을 처리하는 것이었다. MySQL 백업은 4시간마다 퍼블릭 클라우드 블롭 저장소에 쌓였는데, 수 테라바이트를 내려받고 압축을 풀고 체크섬을 확인해 새 서버에 적재하는 데 몇 시간이 걸렸다. 복원 절차는 매일 시험했지만 클러스터 전체를 백업으로 다시 만든 것은 이번이 처음이었다. 10월 22일 06:51 UTC 에 여러 클러스터가 동부에서 복원을 마쳤고, 팀은 외부 저장소의 처리량 한계를 피하려고 서부에서 직접 복원하는 방법을 찾았다.

11:12 UTC 에 모든 프라이머리가 동부로 돌아와 응답이 크게 빨라졌지만, 수십 대의 읽기 복제본이 몇 시간씩 뒤처져 사용자는 어긋난 데이터를 봤다. 복제 따라잡기는 선형 추정보다 오래 걸렸고, 업무 시간의 쓰기 부하로 지연이 더 늘었다. 앞서 동부 퍼블릭 클라우드에 띄우기 시작한 읽기 복제본이 준비되자 읽기 부하를 나눌 수 있었고 복제가 따라잡았다. 16:24 UTC 에 원래 토폴로지로 페일오버했고, 웹훅 이벤트 500만 건 이상과 Pages 빌드 8만 건의 밀린 작업을 처리했다. 이 과정에서 웹훅 페이로드 약 200,000건이 내부 TTL 을 넘겨 버려져 TTL 을 늘렸다. 23:03 UTC 에 밀린 작업을 모두 처리하고 상태를 녹색으로 돌렸다. 장애는 24시간 11분 이어졌고, 사용자 데이터는 잃지 않았지만 몇 초 분량의 쓰기는 손으로 맞추는 작업이 남았다.

심각도
–
영향 범위
GitHub.com degraded for 24 hours and 11 minutes: out-of-date and inconsistent data, slow pages, and no webhook delivery or GitHub Pages builds for most of the incident; a few seconds of database writes needed manual reconciliation
영향 사용자
–
지역
US East Coast and US West Coast data centers
감지까지
2m
복구까지
24h 11m

증상

2018년 10월 21일 22:54 UTC 에 내부 모니터링 시스템이 여러 시스템에서 장애가 났다는 알림을 쏟아내기 시작했다. 23:02 UTC 에 첫 대응 팀은 여러 데이터베이스 클러스터의 토폴로지가 예상하지 못한 상태라는 것을 확인했다.

Orchestrator API 로 복제 토폴로지를 조회하자 미국 서부 데이터센터의 서버만 나왔다. 애플리케이션 계층은 연결이 돌아오자마자 서부의 새 프라이머리로 쓰기를 보내고 있었다.

동부 데이터센터의 데이터베이스에는 서부로 복제되지 않은 몇 초 분량의 쓰기가 남아 있었다. 서부 클러스터는 40분 가까이 새 쓰기를 받았기 때문에 양쪽에 서로 없는 쓰기가 생겼고, 프라이머리를 동부로 안전하게 되돌릴 수 없었다.

동부에서 돌아가는 애플리케이션이 서부 MySQL 에 쓰면서 대륙을 오가는 지연이 생겼다. 쓰기를 하는 페이지가 느리게 열렸고, 사용자는 오래되고 서로 맞지 않는 정보를 봤다. 장애 대부분의 시간 동안 웹훅 이벤트가 전달되지 않았고 GitHub Pages 사이트도 빌드되거나 게시되지 않았다.

클러스터를 백업으로 복원하는 데 몇 시간이 걸렸다. 수 테라바이트를 원격 블롭 저장소에서 내려받고, 압축을 풀고, 체크섬을 확인하고, 새 MySQL 서버에 적재하는 데 시간 대부분이 들었다.

10월 22일 11:12 UTC 에 프라이머리를 모두 동부로 되돌린 뒤에도 수십 대의 읽기 복제본이 프라이머리보다 몇 시간씩 뒤처져 있었다. 읽기 요청은 큰 복제본 풀에 나뉘어 들어갔으므로 요청마다 몇 시간 늦은 복제본에 닿을 가능성이 컸고, 사용자는 서로 맞지 않는 데이터를 봤다.

대응 팀은 복제 텔레메트리로 따라잡는 시간을 선형으로 추정해 상태 페이지에 복구까지 두 시간이라고 적었다. 실제 따라잡기는 직선이 아니라 거듭제곱 꼴로 줄어드는 곡선을 따랐다. 유럽과 미국에서 업무가 시작되며 쓰기 부하가 늘자 13:15 UTC 에는 복제 지연이 오히려 커졌다.

쌓인 웹훅 이벤트 500만 건 이상과 Pages 빌드 8만 건을 다시 처리하기 시작하자 웹훅 페이로드 약 200,000건이 내부 TTL 을 넘겨 버려졌다.

증상 스플릿 브레인장애 조치 실패복제 지연지연 시간 증가

원인

촉발
10월 21일 22:52 UTC 에 고장 난 100G 광 장비를 교체하는 정기 유지보수 작업 중 미국 동부 네트워크 허브와 동부 주 데이터센터 사이의 연결이 끊겼다. 연결은 43초 만에 돌아왔다.

감지

22:54 UTC 에 내부 모니터링 시스템이 알림을 내기 시작해 여러 엔지니어가 알림을 분류했다. 23:02 UTC 에 첫 대응 팀이 Orchestrator API 를 조회해 복제 토폴로지에 서부 데이터센터 서버만 남은 것을 확인했다.

조치

후속 조치

교훈

GitHub 은 Orchestrator 가 설정대로 움직였지만 애플리케이션 계층은 그 토폴로지 변경을 견디지 못했다고 봤다. 리전 안의 리더 선출은 대체로 안전하지만, 갑자기 생긴 대륙 간 지연이 이번 장애를 키운 큰 요인이었다. 자동 페일오버 설정은 애플리케이션이 기대하는 것과 맞춰야 한다.

GitHub 은 이만큼 복잡한 서비스 체계에서는 운영 통제를 조이거나 대응을 빠르게 하는 것만으로는 안정성을 지킬 수 없다고 판단했다. 그래서 가정을 더 적극적으로 시험하고, 장애 시나리오를 사용자에게 닿기 전에 검증하기로 했다. 복구 예상 시간은 모든 변수를 고려하지 못해 틀렸다.

출처

관련 사례

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

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: 데이터베이스, 데이터베이스 장애 조치 관리자, 데이터베이스 복제. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.