1 points par GN⁺ 2025-11-16 | 1 commentaires | Partager sur WhatsApp
  • Cas où un bug de race condition survenu dans AWS Aurora RDS a été reproduit expérimentalement, et dont AWS a confirmé la cause
  • En faisant évoluer son système de traitement d’événements, Hightouch a découvert, pendant le processus de failover (basculement) d’Aurora, un phénomène où le basculement de l’instance d’écriture échouait
  • L’analyse des logs a montré que deux instances effectuaient des écritures simultanément, provoquant des conflits dans la couche de stockage et l’arrêt des processus
  • AWS a officiellement confirmé que la cause était la promotion d’un nouveau writer alors que la rétrogradation de l’ancien writer n’était pas terminée, en raison d’un problème de traitement des signaux internes
  • Ce cas souligne l’importance du contrôle de concurrence dans les systèmes distribués à grande échelle ainsi que la nécessité d’une procédure d’arrêt des écritures lors d’un basculement

Contexte

  • Le 20 octobre 2025, une panne s’est produite dans la région AWS us-east-1 en raison d’un bug de race condition dans le système de gestion DNS
  • À cause de cela, Hightouch a vu son backlog de traitement d’événements fortement augmenter jusqu’à atteindre les limites du système
  • Pour garantir le débit nécessaire, l’entreprise a procédé le 23 octobre à une mise à niveau des instances Aurora RDS, découvrant au passage un nouveau bug de race condition

Architecture du système d’événements de Hightouch

  • Le système chargé de la collecte et de l’envoi des événements repose sur Kubernetes, Kafka et Postgres (Aurora)
  • Postgres est utilisé comme file de métadonnées de batch, avec un traitement de 500 000 événements par seconde en moins d’une seconde
  • Aurora PostgreSQL se compose d’une instance d’écriture uniquement (primary), d’instances en lecture seule (replica), ainsi que d’une couche de stockage partagée

Plan de mise à niveau

  • Ajout d’une instance de lecture → mise à niveau du reader existant et attribution d’une priorité de failover → exécution du failover → mise à niveau du writer existant → suppression du reader temporaire
  • Cette procédure correspond à celle décrite dans la documentation AWS et avait été validée en environnement de staging via des tests de charge

Tentative de mise à niveau et apparition du problème

  • Le 23 octobre à 16:39 EDT, après l’exécution du failover, l’ancien writer est redevenu primary
  • Lors des deux tentatives, le même résultat s’est produit, avec des erreurs d’écriture dans certains services : DatabaseError: cannot execute UPDATE in a read-only transaction
  • L’analyse des logs a confirmé que deux instances effectuaient des écritures en même temps avant de s’arrêter à cause d’un conflit de stockage

Cause de la race condition

  • Pendant le processus de failover d’Aurora, une race condition est survenue entre l’étape 3 (rétrogradation de l’ancien writer) et l’étape 4 (promotion du nouveau writer)
  • Deux instances ont ainsi détenu simultanément les droits d’écriture, provoquant le conflit
  • En réessayant après avoir supprimé le trafic d’écriture, le failover s’est déroulé normalement, ce qui a confirmé l’hypothèse de la race condition

Confirmation et réponse d’AWS

  • Après examen interne, AWS a confirmé que la cause était une erreur dans le traitement du signal de rétrogradation du writer, sans lien avec la configuration de Hightouch ni avec son profil de trafic
  • Le correctif est inscrit à la roadmap, et AWS recommande à titre provisoire d’interrompre les écritures pendant le failover

Mesures finales

  • Hightouch a finalisé la mise à niveau du cluster et a mis en place :
    • une procédure d’arrêt des écritures avant tout failover volontaire
    • un renforcement de la supervision des changements de rôle du writer
    • une mise à jour du manuel opérationnel (playbook)

Principaux enseignements

  1. Il faut préparer des mécanismes de reprise face aux transitions d’état inattendues pendant une migration
  2. La visibilité opérationnelle (observability) est essentielle pour détecter les problèmes
  3. Il est important de concevoir pour minimiser l’impact entre les composants d’un système distribué
  4. Il faut garder à l’esprit la différence entre environnement de test et environnement de production

Aucune information supplémentaire dans l’article original

1 commentaires

 
GN⁺ 2025-11-16
Avis Hacker News
  • À la lecture de ce billet, on a l'impression que pendant un failover manuel, si l'application continue à envoyer du trafic d'écriture comme d'habitude, cela échoue systématiquement
    Mais cela soulève plusieurs questions. Pourquoi les autres utilisateurs d'Aurora ne rencontrent-ils pas toujours ce problème, comment AWS pourrait-il ne pas être au courant, et s'ils le savent, pourquoi cela n'est-il pas traité comme un incident critique de niveau P0 ?
    Je me dis qu'il y a peut-être des conditions subtiles en jeu, comme l'état des transactions en cours ou les timeouts

    • D'après mon expérience sur des problèmes similaires avec Azure, beaucoup de gens les rencontrent mais passent à autre chose parce qu'un redémarrage résout le problème. Trouver la cause racine est difficile, et l'analyse avec le fournisseur est tellement pénible que la plupart abandonnent
    • Nous avons confirmé le même problème en travaillant avec AWS. Le profil de trafic n'avait rien de particulier, et le problème n'était pas reproductible dans d'autres régions. Il est fort probable qu'il s'agisse d'un défaut fondamental du mécanisme de failover d'Aurora
    • Il y a longtemps, avec une combinaison Python + MySQL, j'ai déjà subi un bugSELECT ... FOR UPDATE échouait silencieusement et la transaction passait en mode autocommit. Personne n'y prêtait attention, donc j'étais seul à en parler, puis quelques mois plus tard quelqu'un m'a contacté en disant avoir eu le même problème. Cela a fini par être corrigé, mais j'avais déjà cessé de m'y intéresser
      Lien connexe : question Stack Overflow
    • AWS publie très peu d'informations internes. Ils ne donnent pas de détails au-delà du niveau API, donc on a l'impression qu'ils classent ce genre de problème parmi les cas rares et passent à autre chose
    • Une partie du problème peut aussi venir de la manière dont l'application réagit à un failover annulé (reverted failover). Le cache semble avoir été corrompu et l'application a continué à tenter des écritures vers le mauvais primaire. Même si ce type d'échec se produit de temps en temps, comme un retry finit par réussir, il est possible que les utilisateurs ne le signalent pas à AWS et qu'AWS ne s'en rende donc pas compte
  • J'ai vu plusieurs fois des comportements inattendus sur Aurora PostgreSQL
    En particulier, pendant le Zero Downtime Patching (ZDP), l'état de session a été mal conservé, au point que même des requêtes simples étaient annulées bien plus vite que statement_timeout
    Mon hypothèse est que lorsque le client se reconnecte, Aurora réutilise tel quel l'ancien état du timer de la session précédente, ce qui provoque l'annulation immédiate des requêtes

  • Nous effectuons nous aussi régulièrement des failovers dans un environnement avec un trafic d'écriture très élevé, mais nous opérons cela de manière fiable via un processus automatisé en utilisant l'AWS JDBC wrapper

    • En pratique, la couche de stockage d'Aurora a empêché toute violation ACID, autrement dit l'intégrité des données a été préservée
  • On paie justement pour qu'Aurora maintienne ce genre d'invariants fondamentaux, donc voir ce type de problème est surprenant

    • Mais la couche de stockage elle-même a correctement bloqué les écritures concurrentes
  • D'après les logs et l'explication d'AWS, l'hypothèse de l'auteur du billet original semble erronée
    Après l'échec de la promotion, un processus de supervision externe semble avoir détecté l'incohérence de l'état du cluster et l'avoir forcé à s'arrêter avec kill -9. Les messages liés au sous-système de stockage sont apparus après cela

  • J'aimerais avoir un retour sur la comparaison de performances entre Aurora et RDS Postgres.
    Si l'on n'a pas besoin du multi-AZ ni d'un failover rapide, est-ce qu'une configuration gp3 64k IOPS sur RDS peut offrir de meilleures performances ? Aurora semble notamment lent sur les insertions et plus coûteux. Les benchmarks indiquent rarement clairement la configuration RDS, donc il est difficile de leur faire confiance

    • De notre côté, avec Aurora PG 14 en configuration 1 writer + 1~2 readers, nous avons obtenu de meilleures performances et des coûts plus faibles. Aurora est avantageux car la facturation du stockage se fait au niveau du cluster et non par instance.
      Il n'est pas non plus nécessaire de provisionner directement les IOPS, et le service fournit environ 80k IOPS.
      Il existe aussi deux modes de facturation des IO : pay-per-IO pour les charges faibles, et un mode à tarif fixe plus intéressant pour les workloads très consommateurs d'IO.
      À noter que le Serverless a presque toujours été peu économique. Il n'est utile que lorsqu'il y a de courts pics de charge
    • Notre équipe a subi une explosion des coûts I/O sur Aurora Postgres RDS. Quelques requêtes fuzzy ont suffi pour dépasser les 3 000 $ par mois, alors qu'on aurait dû rester sous les 100 $
    • Nous avons été déçus par le coût, les performances et la latence d'Aurora, et nous avons finalement migré vers PostgreSQL on-premise
    • Pour Aurora MySQL, à IOPS équivalents, cela revenait beaucoup plus cher sur RDS
    • Aurora n'utilise pas EBS et il est impossible de choisir le type de stockage ou la latence. On peut seulement choisir le mode de facturation des IO
  • Cela illustre bien le « modèle en briques Lego » dont parlent les ingénieurs AWS
    La couche de stockage a été conçue de manière totalement indépendante, si bien que même lorsque le service de niveau supérieur a échoué, la cohérence des données a été garantie. Je trouve que c'est un bon exemple d'ingénierie AWS

  • AWS aurait recommandé de « stopper les écritures pendant le failover », mais je me demande s'il serait possible de partager le numéro de dossier correspondant

    • Nous utilisons nous aussi Aurora MySQL, donc j'aimerais savoir si cette recommandation s'applique aussi à MySQL
  • Cela me rassure de savoir que je ne suis pas le seul à avoir rencontré ce problème

    • Au début, l'AWS Support a rétorqué que c'était dû au replication lag, mais ils se basaient sur des métriques anciennes de 24 heures. J'aimerais vraiment savoir quel type d'échec s'est produit et pourquoi cela n'était pas reproductible dans d'autres régions
  • L'architecture séparant calcul et stockage d'Aurora est intéressante
    Le Hyperscale de MSSQL repose sur une structure similaire, et c'est presque le seul produit Azure que je considère réellement utilisable