Roblox의 인프라를 더 효율적이고 탄력적으로 만드는 방법

지난 16년 이상 로블록스가 성장해 온 만큼, 수백만 건의 몰입형 3D 공동 경험을 지원하는 기술 인프라의 규모와 복잡성도 함께 커졌습니다. 우리가 지원하는 서버 수는 지난 2년 동안 3배 이상 증가하여, 2021년 6월 30일 기준 약 36,000대에서 현재 약 145,000대에 달합니다. 전 세계 사용자를 위한 이러한 상시 접속 경험을 지원하기 위해서는 1,000개 이상의 내부 서비스가 필요합니다. 비용과 네트워크 지연 시간을 효과적으로 관리하기 위해, 우리는 주로 온프레미스 환경에서 운영되는 맞춤형 하이브리드 프라이빗 클라우드 인프라의 일환으로 이러한 서버를 배포하고 관리합니다.
당사의 인프라는 현재 Roblox 경제에 의존해 사업을 운영하는 크리에이터를 포함해 전 세계 7,000만 명 이상의 일일 활성 사용자를 지원하고 있습니다. 이 수백만 명의 사용자는 모두 매우 높은 수준의 안정성을 기대합니다. 당사의 경험이 지닌 몰입감 있는 특성상, 서비스 중단은 말할 것도 없고 지연이나 랙에 대한 허용 범위는 극히 낮습니다. Roblox는 사람들이 몰입형 3D 경험 속에서 함께 모이는 소통과 연결의 플랫폼입니다. 몰입형 공간에서 아바타를 통해 소통할 때, 사소한 지연이나 오류조차도 문자 대화나 화상 회의에서보다 훨씬 더 두드러지게 느껴집니다.
2021년 10월, 저희는 시스템 전반에 걸친 서비스 중단을 겪었습니다. 이는 한 데이터 센터의 특정 구성 요소에서 발생한 사소한 문제로 시작되었습니다. 하지만 조사 과정에서 문제가 급속히 확산되어 결국 73시간 동안 서비스가 중단되는 결과를 초래했습니다. 당시 저희는 사건의 경위와 이 문제를 통해 얻은 초기 교훈을 공유했습니다. 그 이후로 우리는 이러한 교훈을 연구해 왔으며, 극심한 트래픽 급증, 기상 조건, 하드웨어 고장, 소프트웨어 버그, 혹은 단순히 인간의 실수 같은 요인으로 인해 모든 대규모 시스템에서 발생하는 유형의 장애에 대해 인프라의 복원력을 높이기 위해 노력해 왔습니다. 이러한 장애가 발생할 때, 단일 구성 요소나 구성 요소 그룹의 문제가 전체 시스템으로 확산되지 않도록 어떻게 보장할 수 있을까요? 지난 2년 동안 우리는 이 질문에 집중해 왔으며, 작업은 여전히 진행 중이지만 지금까지의 노력은 이미 결실을 맺고 있습니다. 예를 들어, 2023년 상반기에는 2022년 상반기 대비 월 1억 2,500만 시간의 서비스 중단 시간을 절감했습니다. 오늘 우리는 지금까지 수행한 작업과 더불어, 더 탄력적인 인프라 시스템을 구축하기 위한 장기적인 비전을 공유하고자 합니다.

백업 시스템 구축
대규모 인프라 시스템에서는 하루에도 수차례 소규모 장애가 발생합니다. 한 대의 서버에 문제가 생겨 서비스를 중단해야 하는 경우, 대부분의 기업은 백엔드 서비스를 여러 인스턴스로 운영하고 있으므로 이를 관리할 수 있습니다. 따라서 단일 인스턴스에 장애가 발생하더라도 다른 인스턴스가 작업 부하를 분담합니다. 이러한 빈번한 장애를 해결하기 위해, 일반적으로 요청이 오류로 반환되면 자동으로 재시도되도록 설정되어 있습니다.
하지만 시스템이나 사용자가 지나치게 공격적으로 재시도할 경우 문제가 발생합니다. 이는 소규모 장애가 인프라 전반에 걸쳐 다른 서비스와 시스템으로 확산되는 원인이 될 수 있습니다. 네트워크나 사용자가 지속적으로 재시도하면, 결국 해당 서비스의 모든 인스턴스에 과부하가 걸리고, 잠재적으로는 전 세계적으로 다른 시스템까지 영향을 미칠 수 있습니다. 2021년 서비스 중단 사태는 대규모 시스템에서 흔히 발생하는 현상의 결과였습니다. 즉, 작은 오류가 시작되어 시스템 전반으로 확산되면서, 모든 것이 다운되기 전에 해결하기 어려울 정도로 순식간에 커지는 현상이었습니다.
서비스 중단 당시, 저희는 하나의 활성 데이터 센터(내부 구성 요소가 백업 역할을 수행)를 운영하고 있었습니다. 기존 데이터 센터가 문제로 인해 다운될 경우, 새로운 데이터 센터로 수동으로 페일오버할 수 있는 기능이 필요했습니다. 저희의 최우선 과제는 로블록스(Roblox)의 백업 배포 환경을 확보하는 것이었기에, 서로 다른 지리적 지역에 위치한 새로운 데이터 센터에 해당 백업을 구축했습니다. 이는 최악의 시나리오, 즉 데이터 센터 내의 구성 요소에 장애가 확산되어 데이터 센터 전체가 작동 불능 상태가 되는 상황을 대비한 추가적인 보호 장치였습니다. 현재 저희는 워크로드를 처리하는 데이터 센터(활성) 하나와 백업 역할을 하는 대기 상태의 데이터 센터(수동) 하나를 운영하고 있습니다. 우리의 장기적인 목표는 이러한 액티브-패시브 구성에서 액티브-액티브 구성으로 전환하는 것입니다. 액티브-액티브 구성에서는 두 데이터 센터 모두 워크로드를 처리하며, 로드 밸런서가 지연 시간, 용량, 상태를 기반으로 두 센터 간에 요청을 분배합니다. 이 구성이 구축되면 Roblox 전체의 신뢰성이 더욱 높아질 것으로 기대되며, 몇 시간이 걸리던 장애 전환을 거의 즉시 수행할 수 있게 될 것입니다.

셀 기반 인프라로의 전환
다음 우선순위는 데이터 센터 전체가 마비될 가능성을 줄이기 위해 각 데이터 센터 내부에 견고한 방화벽을 구축하는 것이었습니다. 셀(일부 기업에서는 클러스터라고 부름)은 본질적으로 일련의 머신으로 구성된 집합체이며, 우리가 이러한 방화벽을 구축하는 방식입니다. 우리는 추가적인 중복성을 확보하기 위해 셀 내부 및 셀 간에 서비스를 복제합니다. 궁극적으로 우리는 Roblox의 모든 서비스가 셀 내에서 실행되도록 하여, 견고한 방화벽과 중복성의 이점을 모두 누릴 수 있게 하고자 합니다. 셀이 더 이상 작동하지 않는 경우, 안전하게 비활성화할 수 있습니다. 셀 간 복제를 통해 해당 셀이 복구되는 동안에도 서비스는 계속 실행될 수 있습니다. 경우에 따라 셀 복구는 셀의 완전한 재프로비저닝을 의미할 수도 있습니다. 업계 전반에서 개별 서버나 소수의 서버를 초기화하고 재프로비저닝하는 것은 꽤 흔한 일이지만, 약 1,400대의 서버를 포함하는 전체 셀에 대해 이를 수행하는 것은 흔하지 않습니다.
이를 위해 셀들은 대체로 균일해야 하며, 그래야만 워크로드를 한 셀에서 다른 셀로 신속하고 효율적으로 이동할 수 있습니다. 우리는 서비스가 셀에서 실행되기 전에 충족해야 할 특정 요구 사항을 설정했습니다. 예를 들어, 서비스는 컨테이너화되어야 하며, 이는 서비스의 이동성을 크게 높이고 누구도 OS 수준에서 구성 변경을 할 수 없도록 방지합니다. 우리는 셀에 대해 '인프라스트럭처-어즈-코드(Infrastructure-as-Code)' 철학을 채택했습니다. 소스 코드 저장소에 셀 내 모든 구성 요소의 정의를 포함시켜, 자동화 도구를 사용하여 처음부터 빠르게 재구축할 수 있도록 했습니다.
현재 모든 서비스가 이러한 요구 사항을 충족하는 것은 아니므로, 서비스 소유자가 가능한 한 이를 충족할 수 있도록 지원해 왔으며, 준비가 되면 서비스를 셀로 쉽게 마이그레이션할 수 있도록 새로운 도구를 구축했습니다. 예를 들어, 새로운 배포 도구는 서비스 배포를 셀 간에 자동으로 "스트라이핑(striping)"하므로, 서비스 소유자는 복제 전략을 고민할 필요가 없습니다. 이러한 엄격한 기준은 마이그레이션 과정을 훨씬 더 어렵고 시간 소모적으로 만들지만, 장기적으로는 다음과 같은 이점을 가져다줄 것입니다:
- 오류를 차단하고 다른 셀로 확산되는 것을 방지하는 것이 훨씬 쉬워집니다;
- 인프라 엔지니어들이 더 효율적으로 작업하고 신속하게 대응할 수 있으며;
- 최종적으로 셀에 배포되는 제품 수준 서비스를 구축하는 엔지니어들은 자신의 서비스가 어떤 셀에서 실행되는지 알 필요도, 걱정할 필요도 없습니다.
더 큰 과제 해결
화재 문이 불길을 차단하는 것과 마찬가지로, 셀은 인프라 내에서 견고한 방화벽 역할을 하여 단일 셀 내에서 장애를 유발하는 문제를 효과적으로 격리합니다. 결국, Roblox를 구성하는 모든 서비스는 셀 내부 및 셀 간에 중복 배치될 것입니다. 이 작업이 완료되면 문제가 여전히 확산되어 전체 셀을 작동 불능 상태로 만들 수는 있겠지만, 문제가 해당 셀을 넘어 확산되는 것은 극히 어려워질 것입니다. 또한 셀을 상호 교환 가능하게 만드는 데 성공한다면, 다른 셀로 페일오버하여 문제가 최종 사용자에게 영향을 미치지 않도록 할 수 있으므로 복구 속도가 훨씬 빨라질 것입니다.
여기서 까다로운 점은 오류 전파 가능성을 줄이기 위해 셀들을 충분히 분리하면서도, 시스템의 성능과 기능을 유지하는 것입니다. 복잡한 인프라 시스템에서 서비스들은 쿼리, 정보, 워크로드 등을 공유하기 위해 서로 통신해야 합니다. 이러한 서비스를 셀 단위로 복제함에 따라, 셀 간 통신을 어떻게 관리할지 신중하게 고려해야 합니다. 이상적인 상황에서는 상태가 불량한 한 셀의 트래픽을 상태가 양호한 다른 셀로 리디렉션합니다. 하지만 셀을 비정상 상태로 만드는 "치명적인 쿼리"는 어떻게 관리해야 할까요? 해당 쿼리를 다른 셀로 리디렉션하면, 우리가 피하고자 했던 바로 그 방식으로 그 셀이 비정상 상태가 될 수 있습니다. 우리는 셀을 비정상 상태로 만드는 트래픽을 감지하고 차단하는 동시에, 비정상 셀에서 "정상적인" 트래픽을 분리해 내는 메커니즘을 찾아야 합니다.
단기적으로는 각 컴퓨팅 셀에 컴퓨팅 서비스의 복제본을 배포하여, 데이터 센터로 들어오는 대부분의 요청을 단일 셀에서 처리할 수 있도록 했습니다. 또한 셀 간에 트래픽을 부하 분산하고 있습니다. 장기적인 관점에서, 서비스 메시에서 활용될 차세대 서비스 디스커버리 프로세스를 구축하기 시작했으며, 2024년에 이를 완료할 계획입니다. 이를 통해 페일오버 셀에 부정적인 영향을 미치지 않는 경우에만 셀 간 통신을 허용하는 정교한 정책을 구현할 수 있게 될 것입니다. 또한 2024년에는 종속 요청을 동일한 셀 내의 서비스 버전으로 안내하는 방법이 도입될 예정이며, 이는 셀 간 트래픽을 최소화하여 오류가 셀 간으로 전파될 위험을 줄여줄 것입니다.
피크 시간대에는 백엔드 서비스 트래픽의 70% 이상이 셀 외부에서 처리되고 있으며, 셀 생성 방법에 대해 많은 것을 배웠습니다. 하지만 2024년 및 그 이후에도 서비스 마이그레이션을 지속함에 따라 더 많은 연구와 테스트가 필요할 것으로 예상됩니다. 진행함에 따라 이러한 방화벽은 점점 더 견고해질 것입니다.

상시 가동 인프라 마이그레이션
Roblox는 전 세계 사용자를 지원하는 글로벌 플랫폼이므로, 사용량이 적은 시간대나 "다운타임" 동안 서비스를 이동할 수 없습니다. 이로 인해 모든 머신을 셀로 이전하고 해당 셀에서 서비스를 실행하도록 하는 과정이 더욱 복잡해집니다. 수백만 개의 상시 가동 경험은, 이를 실행하는 머신과 이를 지원하는 서비스를 이동하는 동안에도 계속 지원되어야 합니다. 이 과정을 시작했을 때, 우리는 이러한 워크로드를 마이그레이션할 수 있도록 유휴 상태로 방치된 수만 대의 머신을 보유하고 있지 않았습니다.
하지만 향후 성장을 대비해 구매해 둔 소수의 추가 서버는 보유하고 있었습니다. 우선 이 서버들을 활용해 새로운 셀을 구축한 다음, 워크로드를 해당 셀로 마이그레이션했습니다. 우리는 신뢰성뿐만 아니라 효율성도 중요하게 생각하기 때문에, "예비" 머신이 바닥나자마자 외부에서 머신을 추가로 구매하는 대신, 이전에 워크로드를 마이그레이션했던 머신을 초기화하고 재프로비저닝하여 더 많은 셀을 구축했습니다. 그런 다음 재프로비저닝된 머신으로 워크로드를 마이그레이션하고, 이 과정을 다시 처음부터 반복했습니다. 이 과정은 복잡합니다. 서버가 교체되어 셀로 구축될 수 있게 되더라도, 서버가 이상적이고 질서 정연한 방식으로 확보되는 것은 아닙니다. 서버는 데이터 홀 전체에 물리적으로 분산되어 있어, 우리는 조각난 방식으로 서버를 프로비저닝해야 합니다. 이로 인해 하드웨어 위치를 대규모 물리적 장애 도메인과 일치시키기 위해 하드웨어 수준의 조각 모음(defragmentation) 프로세스가 필요합니다.
인프라 엔지니어링 팀의 일부는 레거시(또는 "셀 이전") 환경에서 기존 워크로드를 셀로 마이그레이션하는 작업에 집중하고 있습니다. 이 작업은 수천 개의 다양한 인프라 서비스와 수천 개의 백엔드 서비스를 새로 구축된 셀로 모두 마이그레이션할 때까지 계속될 것입니다. 몇 가지 복잡한 요인으로 인해 이 작업은 내년 내내, 어쩌면 2025년까지 걸릴 것으로 예상됩니다. 첫째, 이 작업에는 강력한 툴링이 구축되어야 합니다. 예를 들어, 새로운 셀을 배포할 때 사용자에게 영향을 주지 않으면서 수많은 서비스를 자동으로 재조정할 수 있는 도구가 필요합니다. 또한, 기존 인프라에 대한 가정을 바탕으로 구축된 서비스들도 확인되었습니다. 셀 환경으로 전환함에 따라 향후 변경될 수 있는 요소에 의존하지 않도록 이러한 서비스들을 수정해야 합니다. 또한 셀 아키텍처와 잘 맞지 않는 알려진 설계 패턴을 검색하는 방법과, 마이그레이션된 각 서비스에 대한 체계적인 테스트 프로세스를 모두 구현했습니다. 이러한 프로세스는 서비스가 셀과 호환되지 않아 발생할 수 있는 사용자 관련 문제를 사전에 방지하는 데 도움이 됩니다.
현재 약 3만 대의 머신이 셀 단위로 관리되고 있습니다. 이는 전체 서버 규모의 극히 일부에 불과하지만, 지금까지 플레이어에게 부정적인 영향을 주지 않고 매우 원활하게 전환이 이루어졌습니다. 저희의 궁극적인 목표는 시스템이 매월 99.99%의 사용자 가동 시간을 달성하는 것입니다. 즉, 이용 시간의 0.01% 이하만 중단되는 것을 의미합니다. 업계 전반적으로 다운타임을 완전히 없앨 수는 없지만, 저희의 목표는 로블록스의 다운타임을 거의 감지할 수 없을 정도로 줄이는 것입니다.
확장 과정에서 미래를 대비하며
초기 노력은 성공을 거두고 있지만, 셀(cell) 관련 작업은 아직 끝나지 않았습니다. 로블록스가 계속 확장됨에 따라, 저희는 이 기술과 다른 기술을 통해 시스템의 효율성과 복원력을 개선하기 위해 지속적으로 노력할 것입니다. 이러한 과정을 거치면서 플랫폼은 문제에 대한 복원력이 점점 더 강화될 것이며, 발생하는 문제들은 플랫폼 이용자들에게 점점 덜 눈에 띄고 방해가 되지 않게 될 것입니다.
요약하자면, 현재까지 우리는 다음과 같은 성과를 거두었습니다:
- 두 번째 데이터 센터를 구축하고 능동/수동(active/passive) 구성을 성공적으로 달성했습니다.
- 액티브 및 패시브 데이터 센터 내에 셀을 생성하고, 백엔드 서비스 트래픽의 70% 이상을 해당 셀로 성공적으로 마이그레이션했습니다.
- 나머지 인프라를 계속 마이그레이션해 나가는 과정에서 모든 셀을 일관되게 유지하기 위해 준수해야 할 요구사항과 모범 사례를 마련했습니다.
- 셀 간에 더 견고한 "방화벽"을 구축하는 지속적인 프로세스를 시작했습니다.
이 셀들이 서로 더 상호 교환 가능해질수록 셀 간의 간섭은 줄어들 것입니다. 이는 모니터링, 문제 해결, 심지어 워크로드의 자동 전환에 이르기까지 자동화 수준을 높이는 데 있어 우리에게 매우 흥미로운 기회를 열어줍니다.
9월에는 데이터 센터 전반에 걸쳐 액티브/액티브(active/active) 실험을 시작했습니다. 이는 신뢰성을 높이고 장애 전환 시간을 최소화하기 위해 테스트 중인 또 다른 메커니즘입니다. 이 실험을 통해 완전한 액티브/액티브 환경으로 나아가기 위해 재설계해야 할, 주로 데이터 액세스와 관련된 여러 시스템 설계 패턴을 파악할 수 있었습니다. 전반적으로 실험은 성공적이었으며, 현재 제한된 수의 사용자 트래픽에 대해 계속 운영 중입니다.



