Le mercredi 17 juillet 2013 à 0h02 (UTC+2), une corruption de système de fichiers s’est produite sur le serveur mysql1. Toutes les bases de données hébergées sur ce serveur ont été indisponibles durant la nuit, et une faible proportion d’entre elles ont été victimes de corruption de données.
Ce billet revient en détails sur cet incident : ce qu’il s’est passé et les enseignements que nous en tirons. Nous avons essayé d’utiliser des termes compréhensibles par tous, tout en gardant autant de détails techniques que possible.
Vous pouvez également relire le compte-rendu en direct de l’incident.
Ce qu’il s’est passé
Utilisation de bcache
Commençons par préciser que le matériel du serveur mysql1 a été changé le 7 juillet afin de l’équiper à la fois de disques SSD et de disques mécaniques. Le serveur était auparavant uniquement pourvu des disques SSD, mais l’augmentation croissante de l’espace disque a justifié cette évolution.
bcache est une technologie intégrée récemment à Linux et qui permet de combiner des disques SSD et mécaniques afin d’obtenir un espace disque important et des performances proches de celles d’un SSD. Nous reviendrons en détails sur le choix de cette technologie dans la seconde partie du billet.
Défaillance d’un disque
Le 16 juillet à 3h29, un des disques du serveur a connu un problème matériel. Le disque a automatiquement été éjecté du RAID1, et le serveur a continué à fonctionner normalement sur le second disque — c’est le principe même du RAID. Ce genre de problème n’est pas rare. Deux possibilités :
- soit le disque est définitivement hors service, auquel cas il faudra le remplacer ;
- soit le disque a connu un problème temporaire, et il suffit de le « redémarrer » pour qu’il fonctionne à nouveau normalement.
Notre équipe a pris connaissance de l’incident le matin — aucune astreinte n’a été déclenchée, puisque cela n’a aucun impact sur le bon fonctionnement du serveur. Nous avons décidé de programmer une intervention pour le soir même (c’est une opération qui nécessite de mettre le serveur hors service pendant quelques minutes, nous préférons donc le faire à des heures creuses).
Redémarrage du serveur
À 23h52, nous redémarrons le serveur mysql1. Nous constatons que le disque qui était sorti du RAID fonctionne à nouveau normalement. Mais immédiatement, nous observons une corruption du système de fichiers (XFS) sur lequel les bases de données sont stockées. Après une investigation rapide, nous comprenons ce qu’il vient de se passer.
Les bases de données sont stockées sur un pseudo-disque bcache, combinaison virtuelle de nos disques mécaniques et de nos SSD. Lorsque Linux démarre, bcache scanne l’ensemble des disques physiques à la recherche d’une signature. Cette signature, lorsqu’elle est détectée, signifie que ce disque fait partie d’un pseudo-disque bcache. bcache combine ensuite les disques trouvés et crée le pseudo-disque. Ces signatures sont installées une fois pour toutes à l’installation du système.
Nos deux disques mécaniques étaient en RAID1, ce qui veut dire que les deux disques étaient strictement identiques et synchronisés. C’est, bien entendu, le principe du RAID1 : si un disque tombe en panne, l’autre prend la relève puisqu’il est sa copie conforme. Dans le cas de mysql1, à 23h52, nous avions donc :
- le disque défaillant qui était resté dans son état de 3h29 (avec des données « périmées ») ;
- le second disque qui contenait les « vraies » données, à savoir les plus récentes.
Les deux disques avaient donc, du point de vue de bcache, des signatures identiques. Au redémarrage du serveur, bcache a donc assemblé les SSD avec le disque défaillant (le premier trouvé) plutôt que le second disque, à jour. Or les SSD contenaient des données récentes. Nous avions donc un pseudo-disque qui était la combinaison de certaines données de 23h52 (SSD) et de données de 3h29 (disque défaillant).
Évidemment, ce pseudo-disque ne contenait alors pas des données cohérentes, d’où la corruption de fichiers. Nous avons immédiatement démonté le système de fichiers pour recombiner les SSD avec le second disque, avec les données à jour. Mais c’était trop tard : le simple fait d’avoir préalablement monté le pseudo-disque bcache avec le disque défaillant a entrainé des écritures sur les SSD. Les données des SSD n’étaient alors plus cohérentes avec le second disque.
Restauration des données
Malgré les corruptions du système de fichiers, une très grande proportion des données restait lisible. Nous avons donc pris la décision de restaurer autant que possible les données à jour, plutôt que de restaurer les sauvegardes de la veille pour tout le monde.
La première étape a été de copier l’ensemble des données (300 Go) sur un serveur temporaire. Par sécurité, nous avons copié une seconde fois les données, sur un second serveur temporaire. Les données du premier serveur ont été utilisées pour démarrer MySQL (accessible uniquement en interne) et essayer de récupérer le maximum de bases possible, ce qui a entrainé des modifications sur les fichiers. Les données du second serveur n’étaient là que pour nous permettre de recommencer le processus, si besoin.
La restauration des données (qui consistait essentiellement à exécuter “mysqldump” sur chaque base) a pris du temps : la corruption a entraîné de nombreux plantages de MySQL, ralentissant l’opération. Une fois que nous avions un dump SQL pour la grande majorité des bases (96 %), nous avons pu démarrer la restauration finale sur mysql1 (reformaté entre temps). Les 4 % de bases corrompues ont ensuite été restaurées depuis les sauvegardes de la veille.
Dans certains rares cas, les données récupérées que nous pensions saines étaient finalement en partie corrompues. Les clients concernés ont pu nous contacter pour que nous restaurions alors une sauvegarde.
Diminuer les risques à l’avenir
Commençons d’emblée par dire que la perte de données est un risque qu’il est impossible de réduire à zéro. Les causes peuvent être multiples : bug, erreur humaine, problème matériel, accident majeur, etc. C’est la raison pour laquelle les sauvegardes existent. Cela ne veut toutefois pas dire qu’on ne peut pas réduire davantage les risques.
Utilisation de technologies jeunes
L’incident a pour origine un bug dans bcache. Il est donc légitime de se demander si l’utilisation de bcache, une technologie relativement jeune, était judicieux.
En règle générale, plus une technologie est jeune, plus le risque qu’elle présente des dysfonctionnements (mineurs ou majeurs) est élevé. Il faut donc juger si les avantages qu’apportent la technologie justifient la prise de risque. Naturellement, ce jugement évolue au fil du temps : plus la technologie mûrit, plus les risques diminuent.
En ce qui concerne bcache, les avantages sont importants : permettre d’augmenter considérablement les performances sans sacrifier l’espace disque. Rappelons que contrairement à la majorité des hébergeurs, nous n’imposons aucune limite sur la taille des bases de données.
Nous suivons l’évolution des technologies hybrides SSD/disque mécanique depuis déjà longtemps. Il en existe de nombreuses, au-delà de bcache : dm-cache, EnhanceIO, FlashCache, CacheCade, btier pour n’en citer qu’une partie. En début d’année, nous avons testé et comparé « en laboratoire » plusieurs de ces solutions. Au terme de ces tests, nous avons décidé d’utiliser bcache sur un serveur de pseudo-production : http11, sur lequel nous avons migré une poignée de clients volontaires. Pendant 4 mois, ce serveur a tourné avec bcache sans présenter le moindre problème, tout en tenant ses promesses de performances accrues.
Précisons que bcache, développé par un ingénieur de Google, existe depuis 2010, et est considéré comme stable par son auteur depuis 2011 — date de la dernière découverte d’un bug pouvant provoquer des corruptions de données. Utilisé en production par de nombreuses personnes et organisations depuis, il a été intégré à Linux en 2013 au terme d’une longue et sévère revue de code par plusieurs développeurs seniors de Linux.
Notre décision d’utiliser bcache en production est parfaitement assumée et nous n’estimons pas qu’il s’agisse d’une faute. Le bug, que nous avons depuis remonté aux développeurs, a été corrigé moins de 2h après, un dimanche soir. Une telle réactivité n’est qu’un atout supplémentaire pour bcache.
Améliorer la fiabilité de notre matériel
Deux éléments matériels ont, indirectement, conduit au bug :
- le fait que le disque ait rencontré un problème temporaire qui a provoqué son éjection du RAID ;
- le fait que nos châssis ne soient pas équipés de hot swap, nous obligeant à redémarrer le serveur pour relancer le disque (ou à débrancher un serveur pour remplacer un disque).
Nous allons remplacer l’ensemble de nos serveurs au cours des prochains mois. Parmi leurs avantages, ils seront encore plus fiables qu’actuellement. Nous aurons l’occasion de revenir en détails sur cette migration dans quelques semaines.
Ajouter une option de redondance
Plusieurs clients souhaiteraient que nous proposions une option de redondance master/slave qui permettrait de pallier certains types de pannes, dont l’incident que nous avons eu. Cette option a nécessairement un coût non négligeable.
Dites-nous dans les commentaires si vous seriez intéressé par une telle option, qui augmenterait le prix d’un pack d’environ 50 %.
En conclusion
Environ 300 bases de données MySQL ont été corrompues et ont dû être restaurées depuis les sauvegardes de la veille, ce qui représente moins de 4 % des bases stockées sur mysql1, et moins de 1,5 % de l’ensemble des bases MySQL. Chaque client concerné a été contacté par mail, et nous leur réitérons nos excuses.
Nous préparons de gros changements internes destinés à améliorer encore davantage notre fiabilité, déjà très élevée. Vous en saurez plus très bientôt.
N’hésitez pas à nous faire vos retours et suggestions en commentaires. Nous sommes toujours preneurs. Nous remercions au passage tous ceux qui nous ont apporté leur soutien durant cet incident, c’est toujours apprécié.
Nous souhaitons enfin d’excellentes vacances à tous ceux qui s’apprêtent à en prendre — et bon courage à ceux qui en reviennent :)
Thanks for this incident report – I haven’t been impacted, so I wasn’t aware of it. What is crucial in my opinion is that you detect, correct and take measures in order to avoid such problems in the future. Looking at the way you treated this incident, and the transparency of the information, gives me a great confidence in your judgements and actions. I want to thank you a lot for this.
Have a nice summer !
Greg
« Dites-nous dans les commentaires si vous seriez intéressé par une telle option, qui augmenterait le prix d’un pack d’environ 50 %. »
Oui, et non, ça dépend. Ça peut toujours être une option intéressante, mais une option pas nécessairement intéressante pour tout le monde. Ça dépend donc surtout de si l’option est automatique ou optionhnelle.
Par définition, l’option est optionnelle :)
Personnellement je ne serais pas prêt a payer 50% de plus pour une fiabilité un peu meilleure (mais pas parfaite).
Après, mon site est particulier car peu d’interaction « sociale » comme un forum, donc si je perd quelques heures de la base de donnée il n’y a rien de bien dramatique.
C’est forcément plus embêtant pour une boutique en ligne ou la perte de donnée peu être très TRÈS embetante.
Moi je pense que pour certains de mes clients, c’est une option que je prendrai
J’ai en charge certains sites en mode SAAS dont le données sont importantes
Merci pour ce compte rendu. C’est toujours très agréable de voir ce qui s’est passé et comment vous avez réagi – même si je n’ai pas été impacté pour le coup. Vu l’état de mes finances et mon utilisation de l’hébergement, l’option ne me sera probablement pas utile mais on ne sait jamais, dans un lointain futur…
Merci pour les précisions et la transparence.
Je pense qu’en fonction de la fréquence des mises à jour d’un site, cette option serait intéressante.
Une autre possibilité serait de faire des backup plus fréquents, par exemple toutes les 12 heures (ne garder que les 2 derniers puis, garder toutes les 24 heures comme vous le faites déjà). Je ne sais pas si ça couterait beaucoup plus cher de faire cela ?
Avoir plusieurs options de backup, c’est toujours intéressant, en fonction de l’usage.
Sinon, ceux derrière « theoldreader » (http://blog.theoldreader.com/post/56209408824/important-update) ont eut des gros problèmes DB, quelqu’un dans les commentaires leur a écrit ceci :
« Use ZFS on rotating rust with L2ARC and log devices on SSDs, and 16K recordsize. Enjoy reliability and long-lasting storage with SSD performance. You’re welcome. »
Faire des sauvegardes plus fréquemment est difficile : cela induit une surcharge non négligeable. Elles sont actuellement effectuées la nuit.
Quant à ZFS, ce n’est pas disponible nativement sous Linux.
Merci pour ces compte-rendus. Techniques, certes, mais sympas pour savoir ce qu’il se passe au lieu d’un simple « Erreur technique » comme message d’explication.
Une majoration de 50% pour la redondance, c’est pas rien. C’est vrai que ca m’a bien embete cette panne, mais je ne suis pas pret a y mettre autant pour l’assurer.
En tout les cas, alwaysdata reste de toute facon, a mon sens, le meilleur hebergeur qui soit.
Cordialement,
Merci j’adore la totale transparence, ça me donne entièrement confiance !
Quel changement après avoir expérimenté les services techniques d’OVH, Free, Wanadoo et autre France Telecom.
Je rêve d’un compte-rendu comme celui-là chaque fin de mois par nos politiciens :-)
Oui l’option de redondance pourrait peut-être intéresser mes clients !
Merci pour ces explications qui ont le mérite d’être très clair, au passage j’ai appris pas mal de choses sur des parties du système que je ne manipule pas !
merci pour le feedback
oui je suis prête à payer plus pour ne pas perdre de données. En effet avec cette panne on a perdu une journée de données.
De mon côté je prendrai sans hésiter les 50% de plus sur tous les packs, les miens et ceux que j’ai pris pour certains clients.