Le contenu de ce site a été traduit à l'aide de l'intelligence artificielle (IA) ou d'une technologie de traduction automatique, et peut contenir des erreurs.

Skip to content

Roblox : retour au service

À partir du 28 octobre et jusqu'au 31 octobre, Roblox a connu une panne de 73 heures.¹ Cinquante millions de joueurs utilisent régulièrement Roblox chaque jour et, pour créer l'expérience que nos joueurs attendent, notre infrastructure implique des centaines de services en ligne internes. Comme pour tout service à grande échelle, nous subissons de temps à autre des interruptions de service, mais la durée prolongée de cette panne la rend particulièrement notable. Nous présentons nos sincères excuses à notre communauté pour cette interruption.

Nous partageons ces détails techniques afin de permettre à notre communauté de comprendre la cause profonde du problème, la manière dont nous y avons remédié et les mesures que nous prenons pour éviter que des incidents similaires ne se reproduisent à l'avenir. Nous tenons à réaffirmer qu'il n'y a eu aucune perte de données utilisateur ni aucun accès non autorisé à des informations pendant l'incident.

Les équipes d'ingénierie de Roblox et le personnel technique de HashiCorp ont uni leurs efforts pour rétablir le service Roblox. Nous tenons à remercier l'équipe de HashiCorp, qui a mobilisé des ressources exceptionnelles et a travaillé sans relâche à nos côtés jusqu'à ce que les problèmes soient résolus.

Résumé de la panne

Cette panne était unique tant par sa durée que par sa complexité. L'équipe a dû relever plusieurs défis successifs pour en comprendre la cause profonde et rétablir le service.

  • La panne a duré 73 heures.
  • La cause profonde était due à deux problèmes. L'activation d'une fonctionnalité de streaming relativement nouvelle sur Consul sous une charge de lecture et d'écriture inhabituellement élevée a entraîné une contention excessive et de mauvaises performances. De plus, nos conditions de charge particulières ont déclenché un problème de performances pathologique dans BoltDB. Le système open source BoltDB est utilisé au sein de Consul pour gérer les journaux d'écriture anticipée (WAL) pour l'élection du leader et la réplication des données. 
  • Le fait qu'un seul cluster Consul prenne en charge plusieurs charges de travail a exacerbé l'impact de ces problèmes.
  • Les difficultés rencontrées pour diagnostiquer ces deux problèmes, initialement sans rapport entre eux et profondément enfouis dans l'implémentation de Consul, ont largement contribué à la durée prolongée de l'indisponibilité. 
  • Les systèmes de surveillance critiques qui auraient permis de mieux cerner la cause de la panne dépendaient des systèmes affectés, tels que Consul. Cette combinaison a considérablement entravé le processus de triage.
  • Nous avons adopté une approche réfléchie et prudente pour remettre Roblox en service après un arrêt prolongé complet, ce qui a également pris un temps considérable.
  • Nous avons intensifié nos efforts d'ingénierie pour améliorer notre surveillance, supprimer les dépendances circulaires dans notre pile d'observabilité, ainsi que pour accélérer notre processus de démarrage. 
  • Nous travaillons à la mise en place de plusieurs zones de disponibilité et centres de données.
  • Nous corrigeons les problèmes dans Consul qui étaient à l'origine de cet incident.

Préambule : notre environnement de cluster et HashiStack

L'infrastructure principale de Roblox fonctionne dans les centres de données Roblox. Nous déployons et gérons notre propre matériel, ainsi que nos propres systèmes de calcul, de stockage et de réseau sur ce matériel. L'ampleur de notre déploiement est considérable, avec plus de 18 000 serveurs et 170 000 conteneurs.

Afin de faire fonctionner des milliers de serveurs sur plusieurs sites, nous utilisons une suite technologique communément appelée « HashiStack ». Nomad, Consul et Vault sont les technologies que nous utilisons pour gérer les serveurs et les services à travers le monde, et qui nous permettent d’orchestrer les conteneurs qui prennent en charge les services Roblox.

Nomad est utilisé pour la planification des tâches. Il détermine quels conteneurs vont s’exécuter sur quels nœuds et sur quels ports ils sont accessibles. Il valide également l’état de santé des conteneurs. Toutes ces données sont transmises à un registre de services, qui est une base de données de combinaisons IP:Port. Les services Roblox utilisent le registre de services pour se localiser mutuellement afin de pouvoir communiquer. Ce processus est appelé « découverte de services ». Nous utilisons Consul pour la découverte de services, les contrôles de santé, le verrouillage de session (pour les systèmes HA construits par-dessus) et comme magasin KV.

Consul est déployé sous la forme d’un cluster de machines remplissant deux rôles. Les « votants » (5 machines) détiennent de manière autoritaire l’état du cluster ; les « non-votants » (5 machines supplémentaires) sont des répliques en lecture seule qui aident à faire face à l’augmentation des requêtes de lecture. À tout moment, l’un des votants est élu par le cluster comme leader. Le leader est chargé de répliquer les données vers les autres votants et de déterminer si les données écrites ont été entièrement validées.  Consul utilise un algorithme appelé Raft pour l’élection du leader et pour distribuer l’état à travers le cluster de manière à garantir que chaque nœud du cluster s’accorde sur les mises à jour. Il n’est pas rare que le leader change à plusieurs reprises au cours d’une même journée à la suite d’une élection.

Voici une capture d'écran récente du tableau de bord Consul chez Roblox après l'incident. La plupart des indicateurs opérationnels clés mentionnés dans cet article de blog s'affichent à des niveaux normaux. Le temps d'application KV, par exemple, est considéré comme normal lorsqu'il est inférieur à 300 ms et s'élève à 30,6 ms à ce moment-là. Le leader Consul a été en contact avec d'autres serveurs du cluster au cours des 32 dernières millisecondes, ce qui est très récent.

1. Fonctionnement normal du Consul sur Roblox

Au cours des mois qui ont précédé l'incident d'octobre, Roblox est passé de Consul 1.9 à Consul 1.10 afin de tirer parti d'une nouvelle fonctionnalité de streaming. Cette fonctionnalité de streaming est conçue pour réduire considérablement la charge CPU et la bande passante réseau nécessaires à la distribution des mises à jour sur des clusters à grande échelle comme celui de Roblox.

Détection initiale (28/10 à 13h37)

Dans l'après-midi du 28 octobre, les performances de Vault ont baissé et un seul serveur Consul présentait une charge CPU élevée. Les ingénieurs de Roblox ont commencé à enquêter. À ce stade, les joueurs n'étaient pas affectés.

Triage initial (28/10 13h37 – 29/10 02h00)

L'enquête initiale a suggéré que le cluster Consul dont dépendent Vault et de nombreux autres services était défaillant.  Plus précisément, les métriques du cluster Consul indiquaient une latence d'écriture élevée pour le magasin KV sous-jacent dans lequel Consul stocke les données. La latence au 50e centile pour ces opérations était généralement inférieure à 300 ms, mais elle atteignait désormais 2 secondes. Les problèmes matériels ne sont pas inhabituels à l'échelle de Roblox, et Consul peut survivre à une panne matérielle. Cependant, si le matériel est simplement lent plutôt que défaillant, cela peut affecter les performances globales de Consul. Dans ce cas, l’équipe a soupçonné une dégradation des performances matérielles comme cause première et a entamé le processus de remplacement de l’un des nœuds du cluster Consul. Il s’agissait de notre première tentative de diagnostic de l’incident. À peu près à ce moment-là, des collaborateurs de HashiCorp ont rejoint les ingénieurs de Roblox pour aider au diagnostic et à la résolution. À partir de ce point, toutes les références à « l’équipe » et à « l’équipe d’ingénierie » désignent à la fois le personnel de Roblox et celui de HashiCorp.

Même avec le nouveau matériel, les performances du cluster Consul continuaient de baisser. À 16 h 35, le nombre de joueurs en ligne est tombé à 50 % de la normale.

2. CCU pendant le Player Drop de 16 h 35 PST

Cette baisse a coïncidé avec une dégradation significative de l'état du système, qui a finalement entraîné une panne totale du système. Pourquoi ? Lorsqu'un service Roblox souhaite communiquer avec un autre service, il s'appuie sur Consul pour disposer d'informations à jour sur l'emplacement du service avec lequel il souhaite communiquer. Cependant, si Consul est défaillant, les serveurs ont du mal à se connecter. De plus, Nomad et Vault s'appuient sur Consul ; ainsi, lorsque Consul est défaillant, le système ne peut pas planifier de nouveaux conteneurs ni récupérer les secrets de production utilisés pour l'authentification. En bref, le système a échoué parce que Consul constituait un point de défaillance unique et qu'il était défaillant.

À ce stade, l'équipe a élaboré une nouvelle théorie sur ce qui n'allait pas : une augmentation du trafic. Peut-être que Consul était lent parce que notre système avait atteint un point de basculement et que les serveurs sur lesquels il tournait ne pouvaient plus gérer la charge ? C'était notre deuxième tentative pour diagnostiquer la cause première de l'incident.

Compte tenu de la gravité de l'incident, l'équipe a décidé de remplacer tous les nœuds du cluster Consul par de nouvelles machines plus puissantes. Ces nouvelles machines disposaient de 128 cœurs (soit un doublement) et de disques SSD NVMe plus récents et plus rapides. À 19 h, l'équipe avait migré la majeure partie du cluster vers les nouvelles machines, mais le cluster n'était toujours pas opérationnel. Le cluster signalait que la majorité des nœuds n'étaient pas en mesure de suivre le rythme des écritures, et la latence au 50e centile sur les écritures KV était toujours d'environ 2 secondes au lieu des 300 ms habituels ou moins.

Première tentative de remise en service (29/10, 02 h 00 – 04 h 00)

Les deux premières tentatives visant à rétablir le bon fonctionnement du cluster Consul ont échoué. Nous constations toujours une latence élevée pour les écritures KV, ainsi qu’un nouveau symptôme inexplicable : le leader Consul était régulièrement désynchronisé par rapport aux autres votants. 

L'équipe a décidé d'arrêter l'ensemble du cluster Consul et de réinitialiser son état à l'aide d'un instantané datant de quelques heures auparavant – au début de la panne. Nous savions que cela risquait d'entraîner une perte mineure de données de configuration du système (mais pas de données utilisateur). Compte tenu de la gravité de la panne et de notre certitude de pouvoir restaurer manuellement ces données de configuration si nécessaire, nous avons estimé que cela était acceptable. 

Nous nous attendions à ce que la restauration à partir d’un instantané pris alors que le système était en bon état ramène le cluster à un état sain, mais nous avions une autre préoccupation. Même si Roblox n’avait plus de trafic généré par les utilisateurs transitant par le système à ce stade, les services internes de Roblox étaient toujours actifs et continuaient de communiquer avec Consul pour connaître l’emplacement de leurs dépendances et mettre à jour leurs informations de santé. Ces lectures et écritures généraient une charge importante sur le cluster. Nous craignions que cette charge ne replonge immédiatement le cluster dans un état défaillant, même si la réinitialisation du cluster avait réussi. Pour répondre à cette préoccupation, nous avons configuré iptables sur le cluster afin de bloquer l’accès. Cela nous permettrait de remettre le cluster en service de manière contrôlée et nous aiderait à comprendre si la charge que nous imposions à Consul, indépendamment du trafic utilisateur, faisait partie du problème.

La réinitialisation s'est déroulée sans encombre et, au départ, les métriques semblaient bonnes. Lorsque nous avons supprimé le blocage iptables, la charge liée à la découverte de services et aux contrôles de santé provenant des services internes est revenue comme prévu. Cependant, les performances de Consul ont recommencé à se dégrader et nous nous sommes finalement retrouvés à la case départ : le 50e centile des opérations d'écriture KV était de nouveau à 2 secondes. Les services dépendant de Consul commençaient à se marquer comme « en mauvaise santé », et finalement, le système retomba dans l’état problématique désormais familier. Il était désormais 04h00. Il y avait clairement quelque chose dans notre charge sur Consul qui causait des problèmes, et après plus de 14 heures d’incident, nous ne savions toujours pas de quoi il s’agissait.

Deuxième tentative de rétablissement du service (29/10 04 h 00 – 30/10 02 h 00)

Nous avions écarté toute défaillance matérielle. Un matériel plus rapide n’avait pas aidé et, comme nous l’avons appris par la suite, avait potentiellement nui à la stabilité. La réinitialisation de l’état interne de Consul n’avait pas aidé non plus. Il n'y avait aucun trafic utilisateur entrant, mais Consul restait lent. Nous avions utilisé iptables pour réintroduire progressivement le trafic dans le cluster. Le cluster était-il simplement repoussé vers un état instable par le volume considérable de milliers de conteneurs essayant de se reconnecter ? Il s'agissait de notre troisième tentative pour diagnostiquer la cause première de l'incident.

L'équipe d'ingénierie a décidé de réduire l'utilisation de Consul, puis de le réintroduire de manière prudente et systématique. Pour nous assurer d'avoir un point de départ propre, nous avons également bloqué le trafic externe restant. Nous avons dressé une liste exhaustive des services utilisant Consul et déployé des modifications de configuration pour désactiver toute utilisation non essentielle. Ce processus a pris plusieurs heures en raison de la grande diversité des systèmes et des types de modifications de configuration concernés. Les services Roblox qui comptaient habituellement des centaines d’instances en cours d’exécution ont été réduits à quelques unités. La fréquence des contrôles d’intégrité a été réduite de 60 secondes à 10 minutes afin de donner au cluster un peu plus de répit. À 16 h le 29 octobre, plus de 24 heures après le début de la panne, l'équipe a entamé sa deuxième tentative pour remettre Roblox en ligne. Une fois de plus, la phase initiale de cette tentative de redémarrage semblait prometteuse, mais à 2 h du matin le 30 octobre, Consul se trouvait à nouveau dans un état critique, cette fois avec une charge nettement moindre provenant des services Roblox qui en dépendent.

À ce stade, il était clair que l'utilisation globale de Consul n'était pas le seul facteur contribuant à la dégradation des performances que nous avions constatée pour la première fois le 28. Face à ce constat, l'équipe a de nouveau changé d'approche. Au lieu d'examiner Consul du point de vue des services Roblox qui en dépendent, l'équipe a commencé à chercher des indices dans le fonctionnement interne de Consul.

Recherche sur les conflits d'accès (30/10 02h00 – 30/10 12h00)

Au cours des 10 heures suivantes, l'équipe d'ingénieurs a examiné de plus près les journaux de débogage et les métriques au niveau du système d'exploitation. Ces données ont montré que les écritures KV de Consul étaient bloquées pendant de longues périodes. En d'autres termes, il y avait une « contention ». La cause de cette contention n'était pas immédiatement évidente, mais une théorie suggérait que le passage de serveurs à 64 cœurs à des serveurs à 128 cœurs au début de la panne avait peut-être aggravé le problème. Après avoir examiné les données htop et les données de débogage des performances présentées dans les captures d'écran ci-dessous, l'équipe a conclu qu'il valait la peine de revenir à des serveurs à 64 cœurs, similaires à ceux utilisés avant la panne. L'équipe a commencé à préparer le matériel : Consul a été installé, les configurations du système d'exploitation ont été vérifiées à trois reprises et les machines ont été préparées pour le service de la manière la plus détaillée possible. L'équipe a ensuite fait passer le cluster Consul à nouveau à des serveurs à 64 cœurs, mais ce changement n'a pas aidé. Il s'agissait de notre quatrième tentative pour diagnostiquer la cause première de l'incident.

3. Nous avons ensuite affiché ces résultats dans un rapport de performance, comme indiqué ci-dessus. La majeure partie du temps a été consacrée aux verrous de rotation du noyau via le chemin d'exécution du code d'abonnement au streaming.
4. HTOP affichant l'utilisation du processeur sur 128 cœurs.

Causes profondes identifiées (30/10 12h00 – 30/10 20h00)

Il y a plusieurs mois, nous avons activé une nouvelle fonctionnalité de streaming Consul sur une partie de nos services. Cette fonctionnalité, conçue pour réduire l'utilisation du processeur et la bande passante réseau du cluster Consul, a fonctionné comme prévu. Nous l'avons donc progressivement étendue à d'autres services backend au cours des mois suivants. Le 27 octobre à 14 h, la veille de la panne, nous avons activé cette fonctionnalité sur un service backend chargé du routage du trafic. Dans le cadre de ce déploiement, afin de nous préparer à l'augmentation du trafic que nous observons généralement en fin d'année, nous avons également augmenté de 50 % le nombre de nœuds prenant en charge le routage du trafic. Le système avait bien fonctionné avec le streaming à ce niveau pendant une journée avant que l'incident ne commence ; il n'était donc pas clair au départ pourquoi ses performances avaient changé. Cependant, l’analyse des rapports de performances et des graphiques de flammes provenant des serveurs Consul a révélé que les chemins d’exécution du streaming étaient responsables de la contention à l’origine de l’utilisation élevée du CPU. Nous avons désactivé la fonctionnalité de streaming sur tous les systèmes Consul, y compris les nœuds de routage du trafic. La propagation de la modification de configuration s’est achevée à 15 h 51, moment auquel le 50e centile des écritures Consul KV est tombé à 300 ms. Nous avions enfin fait une percée.

Pourquoi le streaming posait-il problème ? HashiCorp a expliqué que, bien que le streaming fût globalement plus efficace, son implémentation utilisait moins d’éléments de contrôle de la concurrence (canaux Go) que le long polling. Sous une charge très élevée – plus précisément, une charge de lecture très élevée et une charge d’écriture très élevée – la conception du streaming exacerbe la contention sur un seul canal Go, ce qui provoque des blocages lors des écritures, le rendant nettement moins efficace. Ce comportement expliquait également l’effet des serveurs à plus de cœurs : ces serveurs étaient des architectures à double socket avec un modèle de mémoire NUMA. La contention supplémentaire sur les ressources partagées s’aggravait donc sous cette architecture. En désactivant le streaming, nous avons considérablement amélioré la santé du cluster Consul.

Malgré cette avancée, nous n'étions pas encore tirés d'affaire. Nous avons constaté que Consul élisait par intermittence de nouveaux leaders de cluster, ce qui était normal, mais nous avons également observé que certains leaders présentaient les mêmes problèmes de latence que ceux constatés avant la désactivation du streaming, ce qui n'était pas normal. En l'absence d'indices évidents permettant d'identifier la cause profonde du problème de lenteur des leaders, et compte tenu des preuves indiquant que le cluster fonctionnait correctement tant que certains serveurs n'étaient pas élus leaders, l'équipe a pris la décision pragmatique de contourner le problème en empêchant les leaders problématiques de rester élus. Cela a permis à l'équipe de se concentrer sur le rétablissement du bon fonctionnement des services Roblox qui dépendent de Consul.

Mais que se passait-il avec ces leaders lents ? Nous n'avons pas pu le déterminer pendant l'incident, mais les ingénieurs de HashiCorp ont identifié la cause profonde dans les jours qui ont suivi la panne. Consul utilise une bibliothèque de persistance open source populaire nommée BoltDB pour stocker les journaux Raft. Elle n’est pas utilisée pour stocker l’état actuel au sein de Consul, mais plutôt un journal glissant des opérations en cours d’application. Pour empêcher BoltDB de grossir indéfiniment, Consul effectue régulièrement des instantanés. L’opération d’instantané écrit l’état actuel de Consul sur le disque, puis supprime les entrées de journal les plus anciennes de BoltDB. 

Cependant, en raison de la conception de BoltDB, même lorsque les entrées de journal les plus anciennes sont supprimées, l'espace utilisé par BoltDB sur le disque ne diminue jamais. Au lieu de cela, toutes les pages (segments de 4 Ko au sein du fichier) qui servaient à stocker les données supprimées sont marquées comme « libres » et réutilisées pour les écritures suivantes. BoltDB suit ces pages libres dans une structure appelée « liste libre ». En général, la latence d'écriture n'est pas significativement affectée par le temps nécessaire à la mise à jour de la liste libre, mais la charge de travail de Roblox a révélé un problème de performance pathologique dans BoltDB qui rendait la maintenance de la liste libre extrêmement coûteuse. 

Restauration du service de mise en cache (30/10 20h00 – 31/10 05h00)

Cela faisait 54 heures que la panne avait commencé. Le streaming étant désactivé et un processus mis en place pour empêcher les leaders lents de rester élus, Consul était désormais stable en permanence. L'équipe était prête à se concentrer sur la reprise du service.

Roblox utilise un modèle de microservices classique pour son backend. Au bas de la « pile » de microservices se trouvent les bases de données et les caches. Ces bases de données n’avaient pas été affectées par la panne, mais le système de mise en cache, qui traite régulièrement 1 milliard de requêtes par seconde à travers ses multiples couches en fonctionnement normal, était en état de dysfonctionnement. Comme nos caches stockent des données transitoires qui peuvent facilement être réinitialisées à partir des bases de données sous-jacentes, le moyen le plus simple de rétablir le bon fonctionnement du système de mise en cache était de le redéployer.

Le processus de redéploiement du cache a rencontré une série de problèmes : 

  1. Probablement en raison de la réinitialisation de l'instantané du cluster Consul effectuée plus tôt, les données de planification internes que le système de cache stocke dans le KV Consul étaient incorrectes. 
  2. Le déploiement des petits caches prenait plus de temps que prévu, et celui des grands caches ne se terminait pas. Il s'est avéré qu'un nœud défaillant était considéré par le planificateur de tâches comme étant complètement ouvert plutôt que défaillant. Cela a conduit le planificateur de tâches à tenter de planifier de manière intensive des tâches de mise en cache sur ce nœud, ce qui a échoué car le nœud était défaillant. 
  3. L'outil de déploiement automatisé du système de mise en cache avait été conçu pour prendre en charge des ajustements incrémentiels sur des déploiements à grande échelle qui géraient déjà un trafic important, et non pour des tentatives itératives de démarrage d'un grand cluster à partir de zéro. 

L'équipe a travaillé toute la nuit pour identifier et résoudre ces problèmes, s'assurer que les systèmes de mise en cache étaient correctement déployés et vérifier leur bon fonctionnement. À 5 h le 31 octobre, 61 heures après le début de la panne, nous disposions d'un cluster Consul opérationnel et d'un système de mise en cache opérationnel. Nous étions prêts à remettre en service le reste de Roblox.

Le retour des joueurs (31/10 05 h 00 – 31/10 16 h 00)

La phase finale de remise en service a officiellement commencé à 5 h le 31. À l'instar du système de mise en cache, une partie importante des services en cours d'exécution avait été arrêtée pendant la panne initiale ou les phases de dépannage. L'équipe devait redémarrer ces services aux niveaux de capacité appropriés et vérifier qu'ils fonctionnaient correctement. Cela s'est déroulé sans encombre, et à 10 h, nous étions prêts à ouvrir l'accès aux joueurs.

Avec des caches vides et un système dont nous n'étions pas encore tout à fait sûrs, nous ne voulions pas d'un afflux de trafic susceptible de replonger le système dans un état instable. Pour éviter un afflux, nous avons utilisé le routage DNS pour gérer le nombre de joueurs pouvant accéder à Roblox. Cela nous a permis de laisser entrer un certain pourcentage de joueurs sélectionnés au hasard tandis que les autres continuaient d'être redirigés vers notre page de maintenance statique. À chaque fois que nous augmentions ce pourcentage, nous vérifiions la charge de la base de données, les performances du cache et la stabilité globale du système. Le travail s’est poursuivi tout au long de la journée, augmentant l’accès par paliers d’environ 10 %. Nous avons apprécié de voir certains de nos joueurs les plus assidus comprendre notre système de redirection DNS et commencer à partager cette information sur Twitter afin de pouvoir bénéficier d’un accès « anticipé » à mesure que nous remettions le service en ligne. À 16 h 45 dimanche, 73 heures après le début de la panne, 100 % des joueurs avaient accès au service et Roblox était pleinement opérationnel.

Analyse approfondie et changements résultant de la panne

Bien que les joueurs aient pu revenir sur Roblox le 31 octobre, Roblox et HashiCorp ont continué à affiner leur compréhension de la panne tout au long de la semaine suivante. Des problèmes de contention spécifiques au nouveau protocole de streaming ont été identifiés et isolés. Bien que HashiCorp ait testé le streaming à une échelle similaire à celle de l’utilisation de Roblox, l’entreprise n’avait jamais observé ce comportement spécifique auparavant, car il résultait d’une combinaison entre un grand nombre de flux et un taux de désabonnement élevé. L'équipe d'ingénieurs de HashiCorp met au point de nouveaux tests de performance en laboratoire pour reproduire ce problème de contention spécifique et effectue des tests d'évolutivité supplémentaires. HashiCorp s'efforce également d'améliorer la conception du système de streaming afin d'éviter les conflits de contention sous une charge extrême et de garantir des performances stables dans de telles conditions. 

Une analyse plus approfondie du problème de « slow leader » a également permis de mettre au jour la cause principale des écritures de données Raft de deux secondes et des problèmes de cohérence du cluster. Les ingénieurs ont examiné des graphiques en flamme comme celui ci-dessous pour mieux comprendre le fonctionnement interne de BoltDB.

5. Analyse des opérations sur la liste libre de BoltDB.
Comme mentionné précédemment, Consul utilise une bibliothèque de persistance appelée BoltDB pour stocker les données du journal Raft. En raison d'un schéma d'utilisation spécifique apparu pendant l'incident, les opérations d'écriture de 16 ko sont devenues beaucoup plus volumineuses. Vous pouvez voir le problème illustré dans ces captures d'écran :
6. Statistiche dettagliate di BoldDB utilizzate nell'analisi.

La sortie de la commande précédente nous apprend plusieurs choses :

  • Ce magasin de journaux de 4,2 Go ne stocke que 489 Mo de données réelles (y compris toutes les données internes de l'index). 3,8 Go sont de l'espace « vide ».
  • La liste des pages libres (freelist) pèse 7,8 Mo, car elle contient près d'un million d'identifiants de pages libres.

Cela signifie que, pour chaque ajout au journal (chaque écriture Raft après un certain regroupement), une nouvelle liste libre de 7,8 Mo était également écrite sur le disque, même si les données brutes réelles ajoutées ne dépassaient pas 16 Ko. 

La contre-pression exercée sur ces opérations a également saturé les tampons TCP et contribué à des temps d'écriture de 2 à 3 secondes sur les leaders défaillants. L'image ci-dessous présente les résultats des recherches sur les fenêtres TCP à zéro menées pendant l'incident.

7. Recherche sur les fenêtres TCP à zéro. Lorsque le tampon d'un récepteur TCP commence à se remplir, il peut réduire sa fenêtre de réception. S'il se remplit complètement, il peut réduire la fenêtre à zéro, ce qui indique à l'expéditeur TCP d'arrêter l'envoi.Légende

HashiCorp et Roblox ont développé et déployé un processus utilisant les outils BoltDB existants pour « compacter » la base de données, ce qui a permis de résoudre les problèmes de performances.

Améliorations récentes et prochaines étapes

Cela fait deux mois et demi que la panne s'est produite. Qu'avons-nous fait depuis ? Nous avons mis ce temps à profit pour tirer le plus d'enseignements possible de cette panne, pour ajuster nos priorités techniques en fonction de ce que nous avons appris et pour renforcer considérablement nos systèmes. L'une des valeurs de Roblox est le respect de la communauté, et même si nous aurions pu publier un message plus tôt pour expliquer ce qui s'était passé, nous estimions qu'il était de notre devoir envers vous, notre communauté, de réaliser des progrès significatifs dans l'amélioration de la fiabilité de nos systèmes avant de publier quoi que ce soit. 

La liste complète des améliorations de fiabilité déjà mises en œuvre ou en cours est trop longue et trop détaillée pour cet article, mais voici les points clés :

Améliorations de la télémétrie

Il existait une dépendance circulaire entre nos systèmes de télémétrie et Consul, ce qui signifiait que lorsque Consul était défaillant, nous ne disposions pas des données de télémétrie qui nous auraient permis de déterminer plus facilement ce qui n’allait pas. Nous avons supprimé cette dépendance circulaire. Nos systèmes de télémétrie ne dépendent plus des systèmes qu’ils sont configurés pour surveiller.

Nous avons étendu nos systèmes de télémétrie pour offrir une meilleure visibilité sur les performances de Consul et de BoltDB. Nous recevons désormais des alertes très ciblées dès les premiers signes indiquant que le système s'approche de l'état ayant causé cette panne. Nous avons également étendu nos systèmes de télémétrie pour offrir une meilleure visibilité sur les schémas de trafic entre les services Roblox et Consul. Cette visibilité supplémentaire sur le comportement et les performances de notre système à plusieurs niveaux nous a déjà aidés lors des mises à niveau du système et des sessions de débogage.

Expansion vers plusieurs zones de disponibilité et centres de données

Le fait d’exécuter tous les services backend de Roblox sur un seul cluster Consul nous a exposés à une panne de cette nature. Nous avons déjà mis en place les serveurs et le réseau pour un centre de données supplémentaire, géographiquement distinct, qui hébergera nos services backend. Nous travaillons actuellement à la migration vers plusieurs zones de disponibilité au sein de ces centres de données ; nous avons apporté des modifications majeures à notre feuille de route technique et à nos plans de dotation en personnel afin d’accélérer ces efforts.

Mises à niveau de Consul et partitionnement

Roblox continue de croître rapidement ; par conséquent, même avec plusieurs clusters Consul, nous souhaitons réduire la charge que nous imposons à Consul. Nous avons examiné la manière dont nos services utilisent le magasin KV et les contrôles de santé de Consul, et avons séparé certains services critiques dans leurs propres clusters dédiés, réduisant ainsi la charge sur notre cluster Consul central à un niveau plus sûr.

Certains services essentiels de Roblox utilisent directement le magasin KV de Consul comme emplacement pratique pour stocker des données, même si nous disposons d’autres systèmes de stockage probablement plus adaptés. Nous sommes en train de migrer ces données vers un système de stockage plus approprié. Une fois cette migration terminée, cela réduira également la charge sur Consul.

Nous avons découvert une grande quantité de données clé-valeur obsolètes. La suppression de ces données obsolètes a amélioré les performances de Consul.

Nous travaillons en étroite collaboration avec HashiCorp pour déployer une nouvelle version de Consul qui remplace BoltDB par un successeur appelé bbolt, qui ne présente pas le même problème de croissance illimitée de la liste libre. Nous avons délibérément reporté cette initiative à la nouvelle année afin d’éviter une mise à niveau complexe pendant notre pic de trafic de fin d’année. La mise à niveau est actuellement en cours de test et s’achèvera au premier trimestre.

Améliorations des procédures de démarrage et de la gestion de la configuration

La reprise du service a été ralentie par un certain nombre de facteurs, notamment le déploiement et la mise en température des caches nécessaires aux services Roblox. Nous développons de nouveaux outils et processus pour automatiser davantage cette procédure et la rendre moins sujette aux erreurs. En particulier, nous avons repensé nos mécanismes de déploiement de cache afin de garantir que nous puissions rapidement mettre en service notre système de cache à partir d’un état de repos. La mise en œuvre de ces mesures est en cours.

Nous avons collaboré avec HashiCorp pour identifier plusieurs améliorations de Nomad qui nous permettront de lancer plus facilement des tâches volumineuses après une longue période d'indisponibilité. Ces améliorations seront déployées dans le cadre de notre prochaine mise à niveau de Nomad, prévue pour la fin du mois.

Nous avons développé et déployé des mécanismes permettant d'accélérer les modifications de configuration des machines.

Réintroduction du streaming

Nous avions initialement déployé le streaming afin de réduire l'utilisation du CPU et la bande passante réseau du cluster Consul. Une fois qu'une nouvelle implémentation aura été testée à notre échelle avec notre charge de travail, nous prévoyons de la réintroduire avec précaution dans nos systèmes.

Remarque sur le cloud public

À la suite d’une panne comme celle-ci, il est naturel de se demander si Roblox envisagerait de migrer vers le cloud public et de confier à un tiers la gestion de nos services de base en matière de calcul, de stockage et de réseau.

Une autre de nos valeurs chez Roblox est « Take The Long View » (Adopter une vision à long terme), et cette valeur influence fortement notre prise de décision. Nous construisons et gérons notre propre infrastructure de base sur site car, à notre échelle actuelle, et surtout à l’échelle que nous savons atteindre à mesure que notre plateforme se développe, nous pensons que c’est la meilleure façon de soutenir notre entreprise et notre communauté. Plus précisément, en construisant et en gérant nos propres centres de données pour les services backend et de périphérie de réseau, nous avons pu contrôler nos coûts de manière significative par rapport au cloud public. Ces économies ont une influence directe sur les montants que nous sommes en mesure de verser aux créateurs sur la plateforme. De plus, le fait de posséder notre propre matériel et de construire notre propre infrastructure de périphérie nous permet de minimiser les variations de performances et de gérer avec soin la latence de nos joueurs à travers le monde. Des performances constantes et une faible latence sont essentielles à l’expérience de nos joueurs, qui ne se trouvent pas nécessairement à proximité des centres de données des fournisseurs de cloud public.

Notez que nous ne sommes pas idéologiquement attachés à une approche particulière : nous utilisons le cloud public pour les cas d'utilisation où cela est le plus judicieux pour nos joueurs et nos développeurs. À titre d'exemple, nous utilisons le cloud public pour la capacité de pointe, une grande partie de nos workflows DevOps et la plupart de nos analyses internes. En général, nous considérons que le cloud public est un bon outil pour les applications où les performances et la latence ne sont pas critiques, et qui fonctionnent à une échelle limitée. Cependant, pour nos charges de travail les plus critiques en termes de performances et de latence, nous avons choisi de construire et de gérer notre propre infrastructure sur site. Nous avons fait ce choix en sachant que cela demande du temps, de l’argent et des compétences, mais aussi en sachant que cela nous permettra de construire une meilleure plateforme. Cela s’inscrit dans notre valeur « Take The Long View ».

Stabilité du système depuis la panne

Roblox enregistre généralement un pic de trafic à la fin du mois de décembre. Nous avons encore beaucoup de travail à accomplir en matière de fiabilité, mais nous sommes heureux d’annoncer que Roblox n’a connu aucun incident de production significatif pendant ce pic de décembre, et que les performances et la stabilité de Consul et de Nomad ont été excellentes pendant cette période. Il semble que nos améliorations immédiates en matière de fiabilité portent déjà leurs fruits, et à mesure que nos projets à plus long terme s’achèvent, nous nous attendons à des résultats encore meilleurs.

Conclusion

Nous tenons à remercier notre communauté Roblox mondiale pour sa compréhension et son soutien. Une autre de nos valeurs chez Roblox est « Assumer ses responsabilités », et nous assumons pleinement la responsabilité de ce qui s’est passé ici. Nous tenons à adresser une nouvelle fois nos sincères remerciements à l’équipe de HashiCorp. Leurs ingénieurs se sont immédiatement mobilisés pour nous aider dès le début de cette panne sans précédent et ne nous ont pas quittés. Même aujourd’hui, deux mois après la panne, les ingénieurs de Roblox et de HashiCorp continuent de collaborer étroitement pour s’assurer que nous faisons collectivement tout notre possible pour empêcher qu’une panne similaire ne se reproduise.

Enfin, nous tenons à remercier nos collègues de Roblox d’avoir confirmé à quel point c’est un lieu de travail extraordinaire. Chez Roblox, nous croyons en la courtoisie et au respect. Il est facile d’être courtois et respectueux quand tout va bien, mais le véritable test réside dans la façon dont nous nous traitons les uns les autres lorsque les choses se compliquent. À un moment donné au cours de cette panne de 73 heures, alors que le temps passait et que le stress montait, il n’aurait pas été surprenant de voir quelqu’un perdre son sang-froid, tenir des propos irrespectueux ou se demander à haute voix à qui incombait la responsabilité de tout cela. Mais ce n’est pas ce qui s’est passé. Nous nous sommes soutenus les uns les autres et avons travaillé ensemble, comme une seule et même équipe, sans relâche jusqu’à ce que le service soit rétabli. Nous ne sommes bien sûr pas fiers de cette panne et de son impact sur notre communauté, mais nous sommes fiers de la façon dont nous nous sommes mobilisés en équipe pour redonner vie à Roblox, et de la manière dont nous nous sommes traités avec courtoisie et respect à chaque étape de ce processus.

Nous avons énormément appris de cette expérience, et nous sommes plus déterminés que jamais à faire de Roblox une plateforme plus solide et plus fiable à l'avenir.

Merci encore. 

¹ Remarque : toutes les dates et heures mentionnées dans cet article sont exprimées en heure normale du Pacifique (PST).