DevOps et supervision

Pourquoi un contrôle de santé « 200 OK » peut masquer une panne totale du service

Une requête GET mise en cache a renvoyé un succès alors que le serveur d'origine était hors ligne, entraînant l'échec silencieux de toutes les soumissions des acheteurs pendant plusieurs heures.

Illustration d'un cache frontend sain connecté à un tunnel backend cassé
Illustration créée pour cet article

Traduit automatiquement depuis l’original en anglais.

Un service e-commerce auto-hébergé semblait pleinement opérationnel pour son système de surveillance durant toute une soirée, renvoyant des codes de statut de succès toutes les cinq minutes. En réalité, le tunnel d'origine vers le backend était tombé en panne plusieurs heures plus tôt, provoquant l'échec de chaque soumission d'achat tandis que la page frontend restait accessible via le cache.

Ce qui s'est passé

L'incident a débuté lorsque le tunnel d'origine reliant le bord du réseau de distribution de contenu (CDN) au serveur backend a cessé de répondre. Malgré cette défaillance critique, le contrôle de santé automatisé continuait à signaler que le service était sain. Le contrôle effectuait une simple requête GET vers la page destinée aux acheteurs, servie par le CDN depuis son cache avec la dernière version connue valide du HTML. Cela a abouti à un code de statut 200 OK, indiquant au système de surveillance que tout fonctionnait correctement.

Pendant ce temps, les utilisateurs réels tentant d'effectuer des achats ont subi une panne complète. Leurs navigateurs envoyaient des requêtes POST contenant des données de formulaire pour soumettre les commandes. Contrairement à la page HTML statique, ces appels API dynamiques ne pouvaient pas être servis depuis le cache du CDN. Ils étaient routés directement vers le tunnel d'origine, qui était inactif. Le nœud de bord renvoyait une page d'erreur 1033 pour ces requêtes, mais comme personne ne surveillait activement les journaux d'erreurs côté utilisateur, la défaillance est passée inaperçue auprès de l'équipe d'opérations. Cinq soumissions réelles provenant de trois réseaux différents ont échoué durant cette fenêtre, sans déclencher aucune alerte.

Cette situation résultait d'une correction précédente visant à résoudre un problème différent. Un incident antérieur impliquait un chemin statique auquel le bord répondait indépendamment de l'origine, générant des faux positifs. L'équipe a corrigé cela en dirigeant le contrôle de santé vers la page acheteur, qui dépend effectivement de l'origine. Cependant, ils ont conservé la méthode GET pour le contrôle. Bien que le chemin soit correct, la méthode ne l'était pas, car un GET mis en cache ne vérifie pas la vitalité de la logique de traitement du backend.

Détails clés

  • Le contrôle de santé s'exécutait toutes les cinq minutes et recevait systématiquement une réponse 200 OK du cache du CDN.
  • Le tunnel d'origine était hors ligne pendant plusieurs heures, faisant échouer toutes les requêtes POST des acheteurs avec une erreur 1033.
  • Cinq tentatives d'achat réelles ont échoué sur trois réseaux distincts sans déclencher d'alertes opérationnelles.
  • La correction précédente avait changé la cible du contrôle de santé vers la page acheteur, mais maintenait incorrectement une requête GET.
  • Une requête POST vers un point de terminaison JSON-RPC aurait forcé l'origine à répondre, révélant immédiatement la panne.
  • La résolution finale nécessitait seulement une modification d'une ligne pour changer la méthode du contrôle de santé de GET à POST.

Contexte

Pour comprendre cette défaillance, il est utile de distinguer comment les CDN gèrent différentes méthodes HTTP. Une requête GET récupère des données et est souvent mise en cache. Les CDN stockent des copies de ces réponses dans des emplacements de bord proches des utilisateurs pour réduire la latence et la charge sur le serveur d'origine. Si l'origine tombe en panne, le CDN peut continuer à servir ces copies mises en cache, donnant l'impression que le site est actif même lorsque le backend est inaccessible. Ceci est utile pour la lecture de contenu mais trompeur pour vérifier la santé du système.

En revanche, les requêtes POST sont utilisées pour envoyer des données au serveur, comme la soumission d'un formulaire ou la création d'un enregistrement. Ces requêtes ne sont généralement pas mises en cache car elles modifient l'état de l'application. Lorsqu'une requête POST arrive, le CDN doit la transmettre au serveur d'origine pour traitement. Si l'origine est hors ligne, la requête échoue immédiatement. Par conséquent, un contrôle de santé utilisant GET peut ne vérifier que la disponibilité du cache, tandis qu'un contrôle POST vérifie la disponibilité de la logique applicative réelle et de la connectivité à la base de données.

Pourquoi c'est important

Pour les équipes développant leurs propres logiciels, cet incident met en évidence un piège courant en observabilité : mesurer la mauvaise chose. Un code de statut est une preuve concernant une requête spécifique, pas l'ensemble du service. Si votre contrôle de santé ne reproduit pas le chemin critique de vos utilisateurs, il procure un faux sentiment de sécurité. Dans ce cas, le contrôle mesurait la résilience du cache CDN plutôt que la santé du backend applicatif. Cette distinction est cruciale pour les hébergeurs autonomes qui comptent sur la surveillance automatisée pour détecter les pannes avant les clients.

Le coût de cette mauvaise configuration a été significatif en termes de perte de confiance et de revenus. Comme le système de surveillance signalait un succès, aucun ingénieur n'a été alerté, et le problème a persisté pendant des heures. Le silence des journaux était trompeur ; les journaux CDN montraient des réponses 200 réussies, masquant les erreurs 1033 survenant sur les chemins non mis en cache. Cela démontre que la journalisation et l'alerting complets doivent tenir compte de la différence entre le succès au niveau du bord et la fonctionnalité au niveau de l'origine. Sans aligner les contrôles de santé sur le comportement des utilisateurs, les équipes risquent de manquer des défaillances silencieuses qui ne deviennent apparentes que lorsque les clients se plaignent.

Ce que vous pouvez faire

  • Auditez vos contrôles de santé pour vous assurer qu'ils utilisent la même méthode HTTP et le même chemin que vos actions utilisateurs les plus critiques.
  • Remplacez les simples contrôles GET sur les pages mises en cache par des requêtes POST vers des points de terminaison dynamiques nécessitant un traitement à l'origine.
  • Validez que votre contrôle de santé attend un contenu spécifique dans le corps de la réponse, et pas seulement un code de statut 200.
  • Testez votre surveillance en arrêtant délibérément le serveur d'origine pour voir si le contrôle de santé signale correctement une défaillance.
  • Implémentez des contrôles séparés pour la disponibilité du CDN et la santé de l'origine afin de distinguer les problèmes de cache en bord de ceux du backend.
  • Examinez les journaux pour les types de requêtes réussis et échoués afin de garantir que vos alertes couvrent les interactions dynamiques non mises en cache.

Autres actualités

Toutes les actualités