Roblox의 5000만 유저 서비스 복구 노하우
2021년 10월, 5000만 이상 유저가 즐기는 게임 Roblox는 73시간 동안 게임 서버가 모두 다운되는 이례적인 서비스 장애를 겪게 됩니다. Roblox의 모든 개발자들에 발등에 불똥이 떨어진 73시간 동안 개발팀에겐 어떤 일이 있었을까요? Roblox 개발팀이 직접 공개한 흥미진진한 장애 부검 요약: → 5000만 이상의 유저가 즐기는 Roblox의 게임 서버는 최대한의 성능과 효율을 뽑아내기 위해 클라우드 서비스가 아닌 하드웨어부터 직접 관리 합니다. 2021년 10월 쯤 Roblox를 구성하는 마이크로 서비스들이 사용하는 서버의 수는 18000대 이상이였습니다. → 대량의 서버에서 효율적으로 컨테이너화된 소프트웨어를 관리하려면 추가적인 소프트웨어가 필요합니다. Roblox 개발팀은 Kubernetes가 아닌 Nomad, Consul, 그리고 Vault로 구성된 HashiStack을 선택했습니다. → HashiStack에서 Consul은 클러스터의 서비스 탐색 기능을 담당합니다. 클러스터에서 실행되는 서비스의 IP/port 정보를 저장하고, 정기적인 건강 점검을 통해 서비스 상태를 모니터링합니다. → 서비스 장애가 발생한 달의 28일경, 개발팀은 Consul 서비스의 CPU 사용량이 정상 범위를 벗어났다는 알림을 받게 됩니다. BoltDB 기반의 Key-Value DB가 Consul 내부 데이터를 저장하는데, 이 DB의 쓰기 성능이 크게 저하된 것을 확인하게 됩니다. → Roblox 서버의 Consul은 서비스 탐색 기능을 담당합니다. Roblox의 모든 서비스가 서로 통신하기 위해선 먼저 Consul에 접속해 목표 서비스의 위치 정보를 얻어야 하는데, 이는 심각한 장애 상황을 초래할 수 있는 단일 실패 지점입니다. 따라서 Consul 서비스의 성능 저하는 곧 Roblox의 전체 서비스 성능 저하로 이어지게 됩니다. → 개발팀은 "서비스 전체 트래픽 증가와 사용량 상승으로 Consul 서비스가 과부하에 도달했다"는 가설을 세웁니다. 팀은 높아진 트래픽에 대응하기 위해 Consul 서비스를 현재 사용 중인 서버보다 2배 더 큰 128코어 서버로 이전합니다. (나중에 이 결정은 후회하게 됩니다) → 고사양 서버로 전환했음에도 불구하고 Consul 서비스는 여전히 높은 CPU 점유율과 저하된 성능을 보입니다. 팀은 Consul에 저장된 데이터가 성능 저하와 관련이 있을 수 있다고 가정하고, Consul 서비스를 중단한 후 장애 발생 전 데이터 스냅샷으로 복구하기로 결정합니다. → 스냅샷을 사용해 복구한 Consul은 곧 다시 불안정한 상태에 빠집니다. 장애 발생 후 14시간이 경과했지만, 팀은 여전히 장애의 원인을 찾지 못하고 있습니다. → 팀은 Consul 서비스를 다시 실행했을 때 급격히 증가하는 트래픽 때문에 불안정 상태가 된 것이 아닐까 추측합니다. 개발팀은 iptable을 이용해 다시 Consul 서비스를 격리하고, 수동으로 iptables를 수정하여 서비스 별로 Consul에 대한 접근을 하나씩 허용해봅니다. 수시간 동안 노력을 계속하였지만, Consul 서비스는 계속해서 문제를 일으킵니다. 또 다시 원점. → Consul 사용 방법이 아닌 Consul 자체가 문제인 것이 아닐까 고민하게 됩니다. 장애가 시작된 며칠 전에 Consul이 마지막으로 업데이트되었기 때문에 이 가설은 초기에 배제되었지만, 이 시점에서는 모든 가능성을 검토해야 합니다. 개발팀은 Consul이 실행 중인 서버에 접속하여 가능한 모든 메트릭을 수집합니다. → Consul이 내부에서 사용하는 KV 사용 코드에서 경합(contention)이 발생하고 있다는 사실을 발견합니다. 장애 초기에 코어가 더 많은 서버로 옮겨져 Consul KV의 경합이 더 악화된 것이 아닐까하는 가설을 세웁니다. 시간을 들여 Consul 서비스를 다시 더 작은 서버로 옮겨보았지만... 상황은 나아지지 않습니다. → Consul KV의 경합에 대해 더 깊이 살펴봅니다. 프로파일러를 돌려보니, 몇 달 전에 Consul 서비스가 새롭게 도입한 스트리밍 기능에서 경합이 발생하고 있다는 것을 알게 됩니다. 이 기능은 몇 달 전에 업데이트 되었지만, 안전한 배포를 위해 각 서비스마다 다른 일정으로 기능을 점차 활성화해왔고, 장애가 발생한 바로 전날에는 인프라에 큰 지분을 차지하는 트래픽 라우팅 서비스가 이 스트리밍 기능을 활성하 했다는 점을 발견합니다. Consul 서비스 전체에서 스트리밍 기능을 비활성화하자, 비정상적인 CPU 사용율이 줄어드는 것을 확인했습니다! 개발팀은 장애 발생 후 48시간이 지나 근본 원인을 발견했습니다. → 근본적인 문제를 해결했지만, Consul 서비스를 살리기 위해 많은 Roblox 마이크로 서비스들이 현재 중단 상태입니다. 다시 Roblox 유저들을 불러모으기 위해서는 모든 서비스가 동작해야 합니다. 이렇게 모든 서비스를 처음부터 부팅하는 것은 이례적인 일입니다. 중단된 모든 캐시 서비스를 재시작하고, 서비스들 간의 의존성을 이해하며, 하나씩 서비스를 복구합니다. 이 과정은 수시간이 더 걸립니다. → 기본적인 서버 복구가 어느 정도 완료되었습니다. 하지만 막 복구된 서비스는 한번에 500만의 동접자를 감당할 수 없기 때문에, DNS 설정을 통해 서서히 Roblox 서버를 열어 조금씩 유저들에게 접속을 허용합니다. Roblox의 열혈팬들은 DNS 설정을 해킹하여 우회접속하는 방법을 찾아내기도 합니다. 모든 트래픽을 100%로 허용한 순간, 73시간 넘게 진행된 서비스 장애의 끝을 선언합니다. 거대한 서비스의 장애는 정말 복잡하고, 복구 과정 역시 순탄치 않습니다. 부끄러울수도 있지만, 이 귀한 경험을 투명하게 공개한 Roblox 개발팀에게 고마움을 전합니다!