{"id":"IL-0273","org":"GitHub","date":"2016-01-28","docs":[],"title":{"en":"A power disruption took GitHub's Redis clusters offline, the app could not boot, and GitHub served 503s for 2 hours","ko":"주 데이터센터의 전원이 잠깐 끊긴 뒤 Redis 클러스터가 돌아오지 않아 GitHub 가 2시간 6분 동안 HTTP 503 을 냈다"},"domain":["database"],"impact":{"scope":"GitHub was unavailable and returned HTTP 503 responses for two hours and six minutes","users":"all GitHub users","region":"unknown"},"review":{"written_by":"session","reviewed_at":null,"reviewed_by":null},"lessons":{"en":"Dependencies between components fail in new ways unless they are tested, and a power loss cannot be fully prevented, so the goal is fast and reliable recovery. The application should start without non-essential backends, and internal systems needed to recover from an outage, such as server provisioning, must be as reliable as the system being recovered.","ko":"복잡한 시스템은 구성 요소마다 의존을 이해해도 그 의존을 엄격하게 시험하지 않으면 새로운 방식으로 실패할 수 있다. 인프라의 큰 부분이 전원을 잃는 일을 완전히 막을 수는 없지만, 복구를 빠르고 믿을 만하게 하고 사용자 피해를 줄일 수는 있다. 예상하지 못한 장애에서 복구하는 데 필요한 내부 시스템은 복구 대상 시스템만큼 믿을 만해야 한다."},"related":[],"sources":[{"url":"https://github.blog/news-insights/company-news/january-28th-incident-report/","kind":"blog","archived":"https://web.archive.org/web/20260518064605/https://github.blog/news-insights/company-news/january-28th-incident-report/"}],"summary":{"en":"A short power disruption in GitHub's primary data center rebooted slightly over a quarter of the servers. The servers that did not come back all shared one hardware class: after the power cycle they could not see their own physical drives, a known firmware issue. These servers spanned many racks and rows, so several Redis clusters lost every member at once even though their members sat in different racks. GitHub's application code had come to have a hard dependency on Redis in its boot path, so application processes failed to start while Redis was offline, and the site returned 503 responses. Early on, the team suspected the internal network and raised DDoS defenses before tracing the offline servers to a single hardware class.\n\nOne group of engineers worked with on-site facilities technicians to drain the flea power from the failed servers and start them from a cold state so the disks became visible. Another group rebuilt the affected Redis clusters on alternate hardware, slowed because a number of crucial internal systems ran on the offline hardware, which made provisioning new servers more difficult. Once the Redis data was restored on standby equipment and the Redis-server processes were back, the application processes recovered, the HAProxy load balancers returned the application servers to the backend pool, and the maintenance page was removed two hours and six minutes after the outage began. The following hours went into confirming that all systems worked normally and that no data had been lost.","ko":"2016년 1월 28일 00:23am UTC 에 GitHub 주 데이터센터의 전원 공급 시스템이 잠깐 끊겨 전체 서버의 25% 를 조금 넘는 서버와 여러 네트워크 장비가 재부팅됐다. 로드 밸런서와 프런트엔드 서버 다수는 멀쩡했지만 이들이 의존하는 시스템에 닿을 수 없어 애플리케이션이 HTTP 503 을 냈다. 여러 ChatOps 시스템이 재부팅된 서버에 있어 초반 대응이 늦어졌고, 상태 페이지는 8분 뒤에야 빨간색이 됐다. Redis 연결 예외와 연결 시도 증가 때문에 처음에는 네트워크 장애와 DDoS 를 의심했다.\n\n조사해 보니 꺼진 서버는 모두 같은 하드웨어 종류였고, 전원이 다시 들어온 뒤 자기 드라이브를 인식하지 못해 부팅하지 못했다. 이것은 알려진 펌웨어 문제였다. 이 서버들이 여러 랙과 랙 열에 흩어져 있어 여러 Redis 클러스터가 멤버 전부를 잃었다. 애플리케이션 코드에는 부팅할 때 Redis 클러스터가 반드시 있어야 하는 의존성이 모르는 사이에 들어가 있었다. 그래서 Redis 가 꺼지자 애플리케이션 프로세스가 시작하지 못했다.\n\n한쪽 엔지니어들은 현장 기술자와 함께 flea power 를 빼 완전히 꺼진 상태에서 서버를 다시 켜 디스크가 보이게 했다. 다른 쪽 엔지니어들은 영향받은 Redis 클러스터를 다른 하드웨어에 다시 만들었다. 중요한 내부 시스템 여럿이 꺼진 하드웨어에 있어 새 서버를 준비하기가 어려웠고, 그래서 이 작업이 더뎠다. 대기 장비에 Redis 데이터를 복원해 Redis 서버 프로세스를 다시 올리자 애플리케이션 프로세스가 회복됐고, HAProxy 로드 밸런서가 정상 응답하는 서버를 백엔드 풀에 되돌렸다. 사이트 동작을 확인한 뒤 점검 페이지를 내리고 상태를 노란색으로 바꿨다. 첫 장애에서 2시간 6분 뒤였다. 데이터 손실은 없었다."},"trigger":{"en":"At 00:23 UTC a brief disruption in the systems that supply power to the servers and equipment of GitHub's primary data center rebooted slightly over 25% of the servers and several network devices.","ko":"2016년 1월 28일 00:23am UTC 에 주 데이터센터에서 서버와 장비에 전원을 대는 시스템이 잠깐 끊겼고, 전체 서버의 25% 를 조금 넘는 서버와 여러 네트워크 장비가 재부팅됐다."},"severity":"unknown","symptoms":["service-unavailable"],"timeline":{"detected_after":null,"resolved_after":"2h 6m"},"date_kind":"incident","detection":{"en":"The reboots generated alerts to several on-call engineers, starting with notifications for unreachable servers and a spike in exceptions related to Redis connectivity.","ko":"서버에 닿을 수 없다는 알림과 Redis 연결 예외 급증 알림이 여러 온콜 엔지니어에게 갔다."},"components":["cache","datacenter-facility"],"root_cause":"dependency-failure","remediation":[{"text":{"en":"Worked with on-site facilities technicians to drain flea power from the failed servers and start them cold so their disks were visible","ko":"현장 기술자와 함께 flea power 를 빼 완전히 꺼진 상태에서 서버를 다시 켜, 디스크가 다시 보이게 했다."}},{"text":{"en":"Rebuilt the affected Redis clusters on alternate hardware","ko":"영향받은 Redis 클러스터를 다른 하드웨어에 다시 만들기 시작했다."}},{"text":{"en":"Restored the Redis cluster data onto standby equipment and brought the Redis-server processes back online","ko":"Redis 클러스터 데이터를 대기 장비에 복원하고 Redis 서버 프로세스를 다시 올렸다."}},{"text":{"en":"Removed the maintenance page after the HAProxy load balancers returned the recovered application servers to the pool","ko":"사이트 동작을 확인한 뒤 점검 페이지를 내리고 상태를 노란색으로 바꿨다."}}],"action_items":[{"text":{"en":"Update the server firmware with the known issue across the fleet","ko":"전원이 다시 들어온 뒤 서버가 자기 드라이브를 보지 못하게 한 알려진 펌웨어 문제를 전체 서버에서 업데이트한다."}},{"text":{"en":"Make tooling open issues automatically when new firmware updates are available, so their changelogs are reviewed","ko":"새 펌웨어 업데이트가 나오면 도구가 팀에 이슈를 자동으로 열어, 변경 내역을 GitHub 환경과 대조해 검토하게 한다."}},{"text":{"en":"Add tests that make sure application processes start even when certain external systems are unavailable","ko":"애플리케이션 테스트에서 일부 외부 시스템이 없어도 애플리케이션 프로세스가 시작하는지 명시적으로 확인한다."}},{"text":{"en":"Improve circuit breakers so functionality degrades gracefully when backend services are down","ko":"백엔드 서비스가 꺼졌을 때 기능을 단계적으로 줄일 수 있도록 서킷 브레이커를 개선한다."}},{"text":{"en":"Review the availability requirements of internal systems such as server provisioning so they are on par with user-facing systems","ko":"새 서버 준비처럼 중요한 운영 작업을 맡는 내부 시스템의 가용성 요건을 사용자용 시스템과 같은 수준으로 다시 검토한다."}},{"text":{"en":"Strengthen communication between teams during incidents","ko":"팀 사이의 소통을 강화한다."}},{"text":{"en":"Predefine escalation strategies for all-hands incidents","ko":"모든 인원이 대응에 나서야 하는 상황의 에스컬레이션 방식을 미리 정해, 사고 조정자가 문서를 찾는 대신 복구를 관리하는 데 시간을 쓰게 한다."}},{"text":{"en":"Improve status messaging to users during incidents","ko":"장애 동안 사용자에게 보내는 안내를 개선해, 무슨 일이 일어나는지와 다음 안내가 언제 올지 알 수 있게 한다."}}],"contributing":["known-bug-unpatched","single-point-of-failure","test-coverage-gap","circular-dependency"],"recurrence_of":null,"symptoms_text":{"en":"At 00:23 UTC on 28 January 2016 GitHub became unavailable and returned HTTP 503 responses with the unicorn error page. On-call engineers received alerts for unreachable servers and a spike in exceptions related to Redis connectivity, after slightly over 25% of the servers and several network devices in the primary data center rebooted.\n\nThe load balancers and many frontend application servers were unaffected, but the systems they depend on were not available. Many of GitHub's ChatOps systems ran on servers that had rebooted, which caused confusion and delay at the start of the response, and status.github.com was not set to red until 00:32 UTC, eight minutes after the site became inaccessible.\n\nThe unreachable servers, the Redis connectivity errors and more connection attempts than usual pointed first to a problem in the internal network, and the team spent time early on bringing up DDoS defenses and checking network health; a DDoS attack turned out not to be the cause. Because several Redis clusters could not be reached on any of their members, engineers compared device uptimes across the facility: some servers reported uptimes of a few minutes while the network equipment had not rebooted, and all the servers still offline belonged to one hardware class.\n\nAs time passed, application processes were not starting as expected. The process tables and logs on the application servers showed that the processes failed to start because the Redis clusters were offline, which left the site without backend capacity. Remote console screenshots of the failed servers showed boot failures because the physical drives were no longer recognized.","ko":"2016년 1월 28일 00:23am UTC 에 여러 온콜 엔지니어에게 알림이 갔고, GitHub 가 HTTP 503 응답과 함께 유니콘 그림이 있는 오류 페이지를 내기 시작했다. 로드 밸런서와 프런트엔드 애플리케이션 서버 다수는 멀쩡했지만, 그 서버들이 요청을 처리하는 데 의존하는 시스템들에 닿을 수 없었다.\n\n처음 온 알림은 서버에 닿을 수 없다는 것과 Redis 연결 관련 예외가 치솟는다는 것이었다. 연결 시도도 늘어 네트워크 문제처럼 보였다. 팀은 내부 네트워크 장애를 의심했고, DDoS 공격일 수 있다고 보고 DDoS 방어를 올리고 네트워크 상태를 살피는 데 초반 시간을 썼다. 나중에 DDoS 는 원인이 아닌 것으로 드러났다.\n\n여러 ChatOps 시스템이 재부팅된 서버에 있어 대응 초반에 혼란과 지연이 있었다. status.github.com 은 사이트에 접속할 수 없게 된 지 8분 뒤인 00:32am UTC 에야 빨간색으로 바뀌었다.\n\n여러 Redis 클러스터의 모든 멤버에 닿을 수 없어서 데이터센터 장비의 가동 시간을 살폈다. 일부 서버는 가동 시간이 몇 분이었지만 네트워크 장비는 재부팅되지 않은 상태였다. 꺼진 서버는 모두 같은 하드웨어 종류였고, 문제없이 재부팅된 서버는 다른 하드웨어 종류였다. 이 서버들은 여러 랙과 랙 열에 흩어져 있어서, 멤버를 여러 랙에 나눠 둔 클러스터도 멤버 전부가 재부팅됐다.\n\n시간이 지나도 애플리케이션 프로세스가 예상대로 뜨지 않았다. 애플리케이션 서버의 프로세스 목록과 로그를 보니 Redis 클러스터가 꺼져 있어서 프로세스가 시작하지 못하고 있었다. 꺼진 하드웨어의 원격 콘솔 화면에는 물리 드라이브를 더 이상 인식하지 못해 부팅이 실패한 것이 보였다."},"updated_at":"2026-11-14T12:33:52.462740Z","url":"https://benchlet.com/incidentlib/app/cases/IL-0273","org_slug":"github"}