Cloud

Azure Managed Redis : contenir une tempête de connexions avant de scaler ou basculer

Un runbook de production pour distinguer reconnexions clientes, pression serveur, DNS/TLS et saturation réseau, puis valider une correction, un scaling ou un rollback.

29 août 2026 azuremanaged-redisredisconnectionsresilienceobservabilitynetworkingtlskqlscalingfailoverrunbookrollbackproduction

Une API commence à accumuler des timeouts Redis juste après le déploiement de nouvelles instances. Le nombre de clients connectés grimpe, la charge serveur suit, puis les retries transforment une interruption courte en incident durable. Scaler Azure Managed Redis ou forcer une bascule peut sembler logique. Ces actions peuvent aussi fermer davantage de connexions et amplifier la tempête si le client recrée trop de sockets, utilise des timeouts trop courts ou ne réutilise pas ses connexions.

Le cas d’usage est un service de production qui utilise Azure Managed Redis pour accélérer des lectures applicatives. Le runbook doit séparer quatre causes avant d’agir : pression Redis légitime, boucle de reconnexion cliente, défaut DNS/TLS/réseau et régression introduite par une release. La sortie attendue est une décision bornée : corriger le client, augmenter la capacité, laisser la haute disponibilité opérer, rollbacker la release ou maintenir le trafic réduit jusqu’à obtenir une preuve.

Figer l’incident avant de créer une nouvelle coupure

Commencez par conserver une fenêtre UTC, la version applicative, le groupe d’instances touché et le endpoint réellement utilisé. Ne déclenchez pas de reboot ou de bascule pour « nettoyer » les connexions tant que l’équipe ne sait pas si ces connexions sont la cause ou la conséquence.

yaml managed-redis-connection-incident.yml
incident:
started_at_utc: 2026-08-29T05:40:00Z
service: catalog-api-prod
cache: redis-catalog-prod
region: westeurope
endpoint: <cache-name>.<region>.redis.azure.net
port: 10000

symptom:
- redis dependency p95 rises after a deployment
- connected clients increase faster than application traffic
- timeouts trigger repeated reconnect attempts
- fallback reads begin loading the system of record

last_changes:
application_release: catalog-api-2026.08.29.3
replica_count: 12-to-30
redis_client_package: <version>
cache_configuration_changed: false

preserve:
- deployment and autoscale events
- cache metrics with dimensions
- client dependency traces by role instance
- DNS, TCP and TLS test results
- Azure Resource Health and Activity Log events

stop_conditions:
- downstream fallback exceeds its accepted load
- reconnect rate keeps rising after mitigation
- server load remains high while useful operations fall
- a canary opens more connections than its envelope

Distinguez un échec continu, où aucun client ne se connecte, d’un échec intermittent. Un problème continu oriente vers endpoint, DNS, Private Endpoint, firewall, port ou TLS. Une dégradation intermittente demande de corréler maintenance, charge serveur, nombre de clients et comportement de reconnexion.

Lire le service et le client sur la même fenêtre

La charge Redis seule ne suffit pas. Une tempête cliente peut faire monter la charge serveur ; un serveur saturé peut aussi provoquer la première vague de timeouts. Comparez au minimum :

  • charge serveur et CPU, avec maximum sur la fenêtre courte et moyenne sur la tendance ;
  • clients connectés, connexions créées ou fermées si la métrique est disponible, opérations et erreurs ;
  • latence et timeouts côté application par version et par instance ;
  • événements de déploiement, autoscaling, maintenance et santé Azure ;
  • charge du système de repli si l’application contourne temporairement le cache.

Commencez par découvrir les définitions réellement exposées sur la ressource au lieu de copier des noms de métriques d’un autre service Redis.

bash 01-managed-redis-service-evidence.sh
RG="rg-catalog-prod"
CACHE="redis-catalog-prod"

CACHE_ID=$(az redisenterprise show \
--resource-group "$RG" \
--name "$CACHE" \
--query id \
--output tsv)

az redisenterprise show \
--resource-group "$RG" \
--name "$CACHE" \
--output json

az monitor metrics list-definitions \
--resource "$CACHE_ID" \
--query "[].{metric:name.value, display:name.localizedValue, unit:unit}" \
--output table

az redisenterprise test-connection \
--resource-group "$RG" \
--name "$CACHE" \
--auth entra

Le test de connexion prouve le chemin utilisé par l’identité Azure CLI ; il ne remplace pas un test depuis le réseau et l’identité runtime de l’application. Conservez aussi la configuration de haute disponibilité, le SKU, le mode de cluster et les changements de ressource observés dans l’Activity Log.

Corréler timeouts et instances applicatives

Si Application Insights reçoit les dépendances Redis, utilisez-les pour identifier la release et les instances qui déclenchent la pente. Adaptez les champs au schéma réellement émis par le client ; certains clients Redis demandent une instrumentation explicite.

kusto 02-managed-redis-client-dependencies.kql
let StartTime = datetime(2026-08-29T05:30:00Z);
let EndTime = datetime(2026-08-29T06:30:00Z);
dependencies
| where timestamp between (StartTime .. EndTime)
| where type =~ "Redis" or target contains ".redis.azure.net"
| summarize
  Calls=count(),
  Failures=countif(success == false),
  P50=percentile(duration, 50),
  P95=percentile(duration, 95),
  P99=percentile(duration, 99),
  ResultCodes=make_set(resultCode, 10)
by cloud_RoleName, cloud_RoleInstance, operation_Name, bin(timestamp, 2m)
| extend FailureRate = todouble(Failures) / Calls
| order by timestamp asc, FailureRate desc

Une ou deux instances très bruyantes orientent vers un défaut local : CPU, thread pool, sockets, résolution DNS ou cycle de vie du client. Une hausse simultanée sur toutes les instances, avec charge Redis déjà élevée avant les erreurs, renforce l’hypothèse de capacité. Si les erreurs commencent exactement avec une montée de replicas alors que le trafic utile reste stable, traitez d’abord l’amplification cliente.

Ajoutez dans les logs applicatifs la version du client, l’identifiant d’instance, la raison de reconnexion, le nombre de tentatives et un compteur de connexions actives. N’enregistrez ni token Entra, ni clé d’accès, ni contenu de cache.

Calculer l’enveloppe de connexions

Le nombre de pods ou de VM n’est pas le nombre de connexions Redis. Chaque processus peut créer plusieurs clients, et le mode cluster peut utiliser plusieurs connexions physiques. Mesurez le comportement réel d’une instance saine, puis calculez l’enveloppe au niveau du service.

yaml redis-connection-envelope.yml
runtime:
replicas: 30
processes_per_replica: 2
client_objects_per_process: 1
measured_physical_connections_per_client: <measure-on-healthy-instance>
expected_headroom: <capacity-plan>

verify:
- the client object is long-lived and shared
- dependency injection does not create one client per request
- old clients are disposed after a controlled replacement
- cluster topology refresh does not multiply clients without bound
- autoscaling accounts for the connection envelope
- reconnects use backoff and jitter

hard_stop:
- connection count grows while replica count is stable
- one request creates a new connection
- failed connects immediately restart without delay
- a rollout would exceed the tested connection envelope

La création et la fermeture de connexions coûtent au serveur. Réutilisez des connexions longues plutôt que de recréer un client par opération. Des timeouts de connexion trop courts peuvent accélérer la boucle échec-retry ; pour Azure Managed Redis, un point de départ de cinq secondes pour le connect timeout est plus défendable qu’une valeur agressive, à ajuster avec les mesures du parcours. Les reconnexions de nombreuses instances doivent être étalées.

Prouver DNS, TCP et TLS depuis le runtime

Le réseau reste une branche du diagnostic, pas le prisme unique. Testez depuis le même subnet, le même conteneur ou un runner représentatif. Utilisez le hostname du service, pas une IP publique mémorisée. Pour Azure Managed Redis, le client vise le hostname de l’instance sur le port 10000 ; avec un Private Endpoint, la résolution doit conduire au chemin privé attendu sans configurer directement un nom privatelink.

bash 03-managed-redis-runtime-path.sh
CACHE_HOST="<cache-name>.<region>.redis.azure.net"
CACHE_PORT="10000"

getent ahosts "$CACHE_HOST"
nslookup "$CACHE_HOST"

timeout 5 bash -c "exec 3<>/dev/tcp/$CACHE_HOST/$CACHE_PORT"
openssl s_client \
-connect "$CACHE_HOST:$CACHE_PORT" \
-servername "$CACHE_HOST" \
-brief </dev/null

Interprétez les couches séparément. Une résolution incorrecte n’est pas un défaut Redis. Un TCP qui échoue avec une résolution correcte demande de lire NSG, UDR, firewall, proxy ou Private Endpoint. Un handshake TLS qui échoue demande de vérifier SNI, chaîne de certificats, horloge et interception. Un TLS sain suivi de timeouts intermittents ramène vers le client, la charge ou le service.

Contenir la tempête sans déplacer l’incident

La première mitigation doit réduire les nouvelles connexions et protéger les dépendances :

  • geler le rollout ou l’autoscaling qui ajoute des processus plus vite qu’ils ne se stabilisent ;
  • réutiliser le client partagé et désactiver toute création par requête ;
  • introduire backoff exponentiel et jitter sur les reconnexions ;
  • limiter les retries concurrents et conserver un budget de temps de bout en bout ;
  • délester uniquement les usages facultatifs du cache si le fallback a été conçu et testé ;
  • protéger la base ou l’API de repli avec ses propres limites et circuit breakers.

Ne forcez pas toutes les instances à se reconnecter en même temps. Un redémarrage global, une bascule manuelle ou un timeout encore plus court peut produire exactement cette synchronisation. Sur un client .NET utilisant StackExchange.Redis, laissez le multiplexer gérer la reconnexion et vérifiez le pattern de reconnexion forcée avant d’ajouter votre propre boucle.

Décider correction, scaling, bascule ou rollback

text managed-redis-decision-matrix.txt
Corriger ou rollbacker le client
La pente commence avec une release, un rollout ou un autoscaling
Les connexions augmentent plus vite que replicas et trafic utile
Quelques instances concentrent timeouts ou reconnexions
Le serveur monte en charge apres la vague de connexions
La version precedente a une enveloppe connue

Scaler Azure Managed Redis
Les connexions sont legitimes, stables et proches de la limite testee
Operations, debit et charge serveur augmentent avec le trafic utile
Aucun leak, retry storm ou goulot client n'explique le symptome
Le changement de capacite a une fenetre de validation et un owner

Laisser la haute disponibilite operer ou suivre la procedure de bascule
Resource Health ou maintenance explique une interruption de nœud
Le client a prouve sa capacite a se reconnecter progressivement
Le nœud restant peut porter la charge attendue
La bascule n'est pas utilisee comme un reset generique

Corriger le chemin reseau
DNS, TCP ou TLS echoue de facon continue depuis le runtime
Les metriques Redis restent calmes pendant les echecs
Le test distingue endpoint, routage, filtrage et certificat

Maintenir le trafic reduit et collecter
Les preuves client ou service manquent
Le fallback approche sa propre limite
Aucun canari ne reproduit encore le comportement

Une bascule ferme des connexions en cours. Elle est adaptée à un événement de disponibilité qualifié, pas à une fuite de connexions applicative. Le scaling est justifié par une charge utile soutenue, pas par des connexions créées par erreur.

Canary, valider et garder le rollback ouvert

Déployez d’abord le correctif sur une instance ou une faible part du trafic. Comparez-la à une instance témoin avec la même charge. La validation doit couvrir la pente de clients connectés, le taux de reconnexion, les timeouts, la latence p95/p99, la charge serveur, les opérations utiles et la charge du fallback.

yaml managed-redis-change-gate.yml
candidate:
application_release: catalog-api-2026.08.29.4
change:
  - reuse one long-lived client per process
  - add bounded reconnect backoff with jitter
canary_replicas: 1
observation_window: <derived-from-traffic-cycle>

promote_when:
- physical connections stay inside the measured envelope
- reconnect rate returns to baseline
- redis dependency p95 and failures recover
- server load does not rise without useful operations
- fallback load remains inside its guardrail

rollback_when:
- connections keep growing on the canary
- recovery requires repeated forced reconnects
- request success falls despite lower connection count
- downstream load becomes unsafe

rollback:
application_release: catalog-api-2026.08.29.2
keep_capacity_change: false-unless-legitimate-load-was-proven
preserve_evidence: true

Si un scaling temporaire a acheté du temps, ne le réduisez qu’après stabilisation du client et observation sur un cycle de trafic représentatif. Si le client est corrigé mais que la charge utile reste supérieure au dimensionnement, gardez la capacité et documentez la nouvelle baseline.

Conclusion

Une tempête de connexions Azure Managed Redis est un incident de chaîne : cycle de vie client, rollout, DNS/TLS, capacité Redis, haute disponibilité et fallback se répondent. Regarder uniquement la charge serveur mène facilement au mauvais changement.

La décision exploitable vient d’une chronologie partagée, d’une enveloppe de connexions mesurée et d’un canari. Corrigez ou rollbackez la release quand elle amplifie les connexions, scalez quand la charge utile le justifie, et n’utilisez la bascule que pour un événement de disponibilité qualifié. Dans chaque cas, validez la récupération sans fermer le chemin de retour.