Aller au contenu

Annulation automatique sur alarme CloudWatch — la câbler une fois et arrêter la boucle nocturne d'annulations

Câbler automaticRollbackConfiguration de CodeDeploy aux alarmes CloudWatch est mécanique. Garder les alarmes assez serrées pour attraper les régressions mais assez lâches pour ne pas annuler tous les mardis à 03:00 — c'est là que les équipes se trompent.

Une équipe câble l’annulation automatique CodeDeploy à une alarme CloudWatch sur le taux de 5xx un vendredi. Le déploiement réussit, les alarmes restent vertes, l’équipe part pour le long week-end. Le mardi matin, la personne d’astreinte voit trois annulations pendant la nuit — dont aucune ne répondait à une vraie régression de déploiement. Une était une défaillance transitoire de cible ALB pendant un rafraîchissement d’instance. Une était un timeout en aval qui s’est propagé en 5xx pendant 90 secondes. Une était un test de charge depuis l’environnement de QA qui a frappé la production par erreur. La fonctionnalité d’annulation est le bon design; le câblage d’alarme a besoin de travail. Voici le runbook pour le faire correctement la première fois et le flux d’investigation post-annulation qui le garde serré.

Ce qui se passe

automaticRollbackConfiguration et alarmConfiguration de CodeDeploy sont deux champs séparés qui doivent tous deux être définis pour que l’annulation automatique fonctionne. Le premier définit quels événements déclenchent l’annulation; le second définit quelles alarmes CloudWatch comptent comme un déclencheur. L’un manquant casse la fonctionnalité.

Le champ events accepte trois valeurs :

  • DEPLOYMENT_FAILURE — un script de hook sort non-zéro ou ValidateService échoue. Toujours inclure.
  • DEPLOYMENT_STOP_ON_ALARM — une alarme CloudWatch configurée entre en état ALARM pendant le déploiement. Inclure si des alarmes sont câblées.
  • DEPLOYMENT_STOP_ON_REQUEST — un aws deploy stop-deployment manuel déclenche l’annulation plutôt que de juste arrêter. Inclure pour un comportement convivial pour l’opérateur.

Les alarmes elles-mêmes sont des alarmes CloudWatch standard. CodeDeploy interroge leur état pendant la fenêtre de déploiement — et pour le bleu/vert, aussi pendant la fenêtre d’attente avant terminaison si terminateBlueInstancesOnDeploymentSuccess est configuré. Une alarme qui se déclenche pendant que le bleu est encore vivant déclenche un retour du listener vers le bleu.

Le piège qui transforme la fonctionnalité en une boucle nocturne d’annulations est la sensibilité des alarmes. Trois motifs causent de fausses annulations positives :

  • Alarmes à évaluation unique. Une alarme qui se déclenche sur un seul datapoint d’une minute dépassant le seuil va se déclencher sur une fluctuation transitoire tous les deux jours. Deux périodes d’évaluation est le plancher; trois est confortable.
  • Alarmes basées sur un pourcentage à faible trafic. Une alarme « taux 5xx > 1 % » se déclenche à une erreur sur cent. Un service qui fait 30 RPS voit 1800 requêtes/minute — correct. Un service qui fait 0,5 RPS voit 30 requêtes/minute, et un seul 5xx est un taux de 3,3 %. Utilisez des comptes absolus à faible trafic.
  • Alarmes partagées avec du bruit en aval. Une alarme sur le taux global de 5xx de l’ALB se déclenchera sur n’importe quel timeout en amont — un hoquet de base de données en aval qui n’a rien à voir avec le nouveau déploiement déclenchera quand même l’annulation. Limitez les alarmes au niveau du groupe cible ou du jeu de tâches spécifiquement nouveau.

Comment vérifier

Trois vérifications avant de déclarer l’automatisation d’annulation prête pour la production : les alarmes existent et sont en état OK, le groupe de déploiement les référence par nom, et un test d’alarme forcée annule réellement.

Pour l’état des alarmes :

aws cloudwatch describe-alarms \
  --alarm-names saas-api-5xx-rate saas-api-p95-latency \
  --query 'MetricAlarms[].{Name:AlarmName,State:StateValue,Reason:StateReason}'

Toutes les alarmes doivent être en OK. Une alarme en INSUFFICIENT_DATA ne bloquera pas un déploiement, mais elle n’attrapera pas non plus les régressions — corrigez la collecte de métriques sous-jacente avant de vous y fier.

Pour la référence du groupe de déploiement :

aws deploy get-deployment-group \
  --application-name saas-api \
  --deployment-group-name saas-api-prod \
  --query 'deploymentGroupInfo.{Alarms:alarmConfiguration,Rollback:autoRollbackConfiguration}'

Le champ alarms doit lister les alarmes par nom. Les événements d’annulation doivent inclure DEPLOYMENT_STOP_ON_ALARM.

Pour le test d’alarme forcée, la seule façon de savoir que l’annulation automatique fonctionne est de la déclencher délibérément. Le test le plus propre est de régler le seuil d’une alarme à un niveau que le service de production traverse déjà, de lancer un déploiement et de le regarder annuler. Sinon, utilisez set-alarm-state :

aws cloudwatch set-alarm-state \
  --alarm-name saas-api-5xx-rate \
  --state-value ALARM \
  --state-reason "rollback test"

Cela force l’alarme en état ALARM pendant quelques secondes. Si un déploiement est en cours pendant l’état forcé, CodeDeploy l’enregistrera et déclenchera l’annulation. Faites cela une fois dans un environnement hors production avant de vous fier à la fonctionnalité.

La correction

La configuration complète pour une mise en place d’annulation au niveau service. Trois alarmes : taux de 5xx en compte absolu, latence p95 en percentile, métrique d’application personnalisée pour un mode de défaillance spécifique au workload.

Les alarmes :

aws cloudwatch put-metric-alarm \
  --alarm-name saas-api-5xx-rate \
  --alarm-description "Target group 5xx > 5 in 2 of last 3 minutes" \
  --metric-name HTTPCode_Target_5XX_Count \
  --namespace AWS/ApplicationELB \
  --statistic Sum \
  --period 60 \
  --evaluation-periods 3 \
  --datapoints-to-alarm 2 \
  --threshold 5 \
  --comparison-operator GreaterThanThreshold \
  --treat-missing-data notBreaching \
  --dimensions Name=TargetGroup,Value=targetgroup/saas-api-prod/abc \
               Name=LoadBalancer,Value=app/saas-alb/abc

aws cloudwatch put-metric-alarm \
  --alarm-name saas-api-p95-latency \
  --alarm-description "Target p95 > 800ms in 2 of last 3 minutes" \
  --metric-name TargetResponseTime \
  --namespace AWS/ApplicationELB \
  --extended-statistic p95 \
  --period 60 \
  --evaluation-periods 3 \
  --datapoints-to-alarm 2 \
  --threshold 0.8 \
  --comparison-operator GreaterThanThreshold \
  --treat-missing-data notBreaching \
  --dimensions Name=TargetGroup,Value=targetgroup/saas-api-prod/abc \
               Name=LoadBalancer,Value=app/saas-alb/abc

aws cloudwatch put-metric-alarm \
  --alarm-name saas-api-webhook-failures \
  --alarm-description "Application webhook failures > 10 in 2 of last 3 minutes" \
  --metric-name WebhookDeliveryFailures \
  --namespace SaasApi \
  --statistic Sum \
  --period 60 \
  --evaluation-periods 3 \
  --datapoints-to-alarm 2 \
  --threshold 10 \
  --comparison-operator GreaterThanThreshold \
  --treat-missing-data notBreaching

Trois alarmes, toutes avec evaluation-periods 3, datapoints-to-alarm 2 — ce qui signifie que l’alarme se déclenche quand 2 des 3 derniers datapoints d’une minute dépassent le seuil. Cela attrape les régressions soutenues tout en filtrant les fluctuations d’une seule minute.

Le groupe de déploiement les câble toutes :

aws deploy update-deployment-group \
  --application-name saas-api \
  --current-deployment-group-name saas-api-prod \
  --auto-rollback-configuration '{
    "enabled": true,
    "events": ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM", "DEPLOYMENT_STOP_ON_REQUEST"]
  }' \
  --alarm-configuration '{
    "enabled": true,
    "ignorePollAlarmFailure": false,
    "alarms": [
      {"name": "saas-api-5xx-rate"},
      {"name": "saas-api-p95-latency"},
      {"name": "saas-api-webhook-failures"}
    ]
  }'

Le ignorePollAlarmFailure: false compte — si CodeDeploy ne peut pas lire l’état de l’alarme (permission IAM manquante, alarme supprimée), le déploiement est marqué comme ayant échoué. Avec true, l’agent hausse les épaules et continue — annulant le filet de sécurité.

Runbook d’investigation post-annulation. Une annulation est une donnée. Le runbook démarre dans l’heure qui suit l’annulation pour garder le contexte frais :

  1. Tirez la chronologie des événements d’annulation. aws deploy get-deployment --deployment-id d-XXX retourne les événements de cycle de vie et quelle alarme a basculé.
  2. Pour l’alarme déclenchée, interrogez CloudWatch pour les datapoints minute par minute pendant la fenêtre de déploiement. L’alarme était-elle une régression soutenue ou une seule pointe ? Si une seule pointe, l’alarme a besoin de plus de périodes d’évaluation.
  3. Vérifiez les logs d’application sur les instances vertes pendant la fenêtre d’annulation. Le journal de l’agent CodeDeploy sur chaque instance est à /var/log/aws/codedeploy-agent/codedeploy-agent.log; les logs d’application sont là où le service écrit. Le signal est : les instances vertes servaient-elles réellement mal, ou l’alarme s’est-elle déclenchée sur du bruit non lié au déploiement ?
  4. Si l’annulation était un vrai positif (le nouveau code a régressé), le diff entre la révision annulée et la précédente est la cause racine. La correction est un changement de code avant le redéploiement, pas une alarme plus serrée.
  5. Si l’annulation était un faux positif (l’alarme s’est déclenchée sur du bruit), l’alarme est le problème. Ajustez les périodes d’évaluation, passez aux comptes absolus, ou limitez l’alarme à une dimension plus étroite.

Trois règles que nous tenons pour l’automatisation d’annulation :

Ajustez les alarmes sur une semaine de trafic normal avant de les câbler à l’annulation. Un seuil d’alarme raisonnable est la valeur en régime permanent plus une marge — choisissez la marge à partir du trafic observé, pas d’une estimation. Une alarme qui se déclenche une fois par semaine sur du vrai bruit fera basculer ~14 % des déploiements; une alarme qui se déclenche une fois par mois fera basculer ~3 %.

Distinguez les alarmes au niveau service des alarmes d’infrastructure. Une pointe dans NetworkOut EC2 est du bruit d’infrastructure; une pointe dans HTTPCode_Target_5XX_Count du groupe cible est un signal de service. Seules les alarmes au niveau service appartiennent à la configuration d’annulation.

Une annulation répétée sur la même alarme sans régression dans le diff est la faute de l’alarme, pas du déploiement. Trois annulations en un mois sans cause racine de changement de code signifie que l’alarme est trop serrée. Desserrez, ne désactivez pas.

L’annulation automatique est la différence entre une récupération de 90 secondes et une de 25 minutes — mais seulement si les alarmes sont câblées pour se déclencher sur de vraies régressions, pas sur le bruit qui vit dans chaque service de production. Référez-vous au tutoriel bleu/vert pour la fenêtre d’attente avant terminaison où les alarmes ont leur chance de se déclencher.


Stack Harbor opère CodeDeploy + CodePipeline sur les flottes EC2 / ECS / Lambda de production dans le cadre de Gestion AWS et des Environnements infogérés en continu. Si vos déploiements demandent encore une fenêtre de maintenance, commencez par une consultation d’infrastructure.