Networking

Azure App Service VNet Integration : diagnostiquer l’épuisement du subnet avant de relancer le scaling

Un runbook de production pour mesurer la capacité d’un subnet VNet Integration, distinguer manque d’adresses, délégation et panne réseau, puis valider un redimensionnement ou une migration avec rollback.

03 oct. 2026 azureapp-servicevnet-integrationsubnetscalingnetworkingcapacityautomationobservabilityrunbookrollbackproduction

Un plan Azure App Service reste joignable, mais un scale-out ou un scale-up n’aboutit pas. Les métriques applicatives montrent toujours de la charge, les instances existantes répondent et aucune règle NSG n’a changé. Le réflexe est souvent de relancer l’opération, d’augmenter encore la capacité cible ou de chercher une panne dans l’application. Pourtant, le blocage peut se trouver dans le subnet de VNet Integration : il n’offre plus assez d’adresses pour créer la nouvelle cohorte de workers.

Le cas fil rouge est un plan de production à huit instances intégré à un ancien subnet /28. Onze adresses y sont utilisables après les cinq adresses réservées par Azure. Une opération de changement de taille peut devoir maintenir les huit anciennes instances pendant que huit nouvelles démarrent. Le besoin transitoire atteint alors seize adresses, avant même de compter un autre plan ou le cas particulier des Windows Containers. Le runbook doit décider entre quatre actions : libérer une pression temporaire, réduire la cible de scaling, migrer vers un subnet dimensionné, ou rollbacker le changement qui a déclenché l’opération.

Figer le contrat de capacité

Ne commencez pas par détacher l’intégration réseau. Cette action redémarre l’application et détruit une partie de l’état utile au diagnostic. Capturez d’abord le plan, le subnet, l’opération et la capacité attendue.

text contrat-capacite-vnet-integration.txt
Fenetre UTC: 2026-10-03 05:35Z a maintenant
Application / slot: api-orders-prod / production
App Service plan: asp-orders-prod
Instances actives avant incident: 8
Operation demandee: scale-up P1v3 vers P2v3
Subnet VNet Integration: snet-appsvc-integration-prod
Prefixe: 10.42.8.0/28

Symptome
Operation de scaling incomplete ou en echec
Instances existantes toujours joignables
Pas de changement DNS, UDR ou NSG confirme

Decision attendue
Attendre une liberation d'adresses prouvee
Revenir a la taille precedente
Migrer vers un subnet avec marge validee
Escalader un incident plateforme avec preuves

Conservez l’ID de l’opération Azure, les événements Activity Log, l’heure de la dernière modification de l’intégration et la chronologie d’autoscale. Une relance sans ces éléments peut créer une nouvelle tentative qui brouille la cause initiale.

Prouver quel plan consomme quel subnet

VNet Integration est un chemin de sortie. Un Private Endpoint éventuellement présent protège un chemin d’entrée ou l’accès à une dépendance ; il ne fournit aucune capacité au subnet d’intégration. Inventoriez donc les applications et plans réellement reliés au subnet, sans déduire la consommation à partir des Private Endpoints voisins.

bash inventaire-vnet-integration.sh
RG_APP="rg-orders-prod"
APP="api-orders-prod"
PLAN="asp-orders-prod"

az webapp vnet-integration list --resource-group "$RG_APP" --name "$APP" --output json

az appservice plan show --resource-group "$RG_APP" --name "$PLAN" --query '{id:id,sku:sku.name,capacity:sku.capacity,kind:kind,reserved:reserved}' --output json

az monitor autoscale list --resource-group "$RG_APP" --output json

Pour repérer d’autres applications qui déclarent le même subnet, utilisez Azure Resource Graph. La requête donne un inventaire de configuration, pas un compteur d’adresses libres : regroupez ensuite les résultats par App Service plan et vérifiez chaque intégration.

kusto 01-apps-par-subnet-integration.kql
let subnet = tolower('/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-net-prod/providers/Microsoft.Network/virtualNetworks/vnet-prod/subnets/snet-appsvc-integration-prod');
resources
| where type =~ 'microsoft.web/sites'
| extend integrationSubnet = tolower(tostring(properties.virtualNetworkSubnetId))
| where integrationSubnet == subnet
| project subscriptionId, resourceGroup, app=name,
        appServicePlan=tostring(properties.serverFarmId), integrationSubnet

Complétez l’inventaire par les slots, les intégrations configurées via les propriétés réseau du site et les plans joints au même subnet. Avec Multi Plan Subnet Join, la marge est commune : additionnez les instances de tous les plans, pas seulement celles de l’application en incident.

Calculer l’enveloppe, y compris le pic transitoire

Azure réserve cinq adresses dans chaque subnet. Pour App Service multitenant, une instance de plan consomme normalement une adresse dans chaque subnet d’intégration utilisé. Lors d’un scale-up ou d’un scale-down en taille, les anciennes et nouvelles instances peuvent coexister : la consommation du plan est alors temporairement doublée. Une mise à niveau de plateforme a elle aussi besoin de marge. Les adresses libérées après une opération peuvent rester occupées pendant un délai court et, dans de rares cas, jusqu’à douze heures.

Écrivez le calcul au lieu de conclure à partir du seul CIDR.

text enveloppe-adresses.txt
Subnet /28
Adresses totales                           16
Adresses reservees par Azure                5
Adresses utilisables                       11

Plan asp-orders-prod
Instances actuelles                         8
Nouvelle cohorte pendant scale-up            8
Pic transitoire du plan                     16

Marge au pic: 11 - 16 = -5
Decision: le subnet ne peut pas porter cette operation de facon sure

Pour un subnet partagé, calculez au minimum :

adresses nécessaires au pic = somme des instances stables des autres plans + 2 × instances du plan en opération + réserve d’exploitation.

Adaptez la formule si plusieurs plans scalent simultanément. Pour des Windows Containers, ajoutez l’adresse supplémentaire consommée par application et par instance de plan. Ne transformez pas la recommandation “deux fois le maximum prévu” en simple règle documentaire : utilisez-la pour couvrir le chevauchement de scaling et les opérations de plateforme. Pour un environnement de production, un /26 constitue le point de départ recommandé par Microsoft, mais le bon préfixe dépend toujours du nombre de plans, d’applications conteneurisées et d’intégrations.

Distinguer épuisement, délégation et panne de chemin

Un subnet presque plein n’explique pas tous les échecs. Vérifiez sa délégation, ses associations et son préfixe avant d’annoncer une saturation.

bash controle-subnet-integration.sh
RG_NET="rg-net-prod"
VNET="vnet-prod"
SUBNET="snet-appsvc-integration-prod"

az network vnet subnet show --resource-group "$RG_NET" --vnet-name "$VNET" --name "$SUBNET" --query '{prefixes:addressPrefixes,delegations:delegations[].serviceName,nsg:networkSecurityGroup.id,routeTable:routeTable.id,serviceAssociationLinks:serviceAssociationLinks[].id}' --output json

Séparez les branches du diagnostic :

  • une création de worker échoue pendant que les instances présentes restent saines : capacité ou opération de plateforme probable ;
  • aucune instance ne reçoit d’adresse privée : intégration, délégation ou Service Association Link à contrôler ;
  • les instances ont une adresse mais une dépendance devient inaccessible : DNS, UDR, NSG, firewall ou retour réseau ;
  • seule une application Windows Container échoue après ajout d’apps : recalculer le multiplicateur propre aux conteneurs ;
  • le compteur semble suffisant juste après un scale-in : rechercher une libération différée avant toute nouvelle relance.

WEBSITE_PRIVATE_IP permet de confirmer qu’une instance a reçu une adresse du subnet. Cette valeur peut changer : ne l’ajoutez pas individuellement à une allowlist. Les destinations doivent autoriser le préfixe d’intégration prévu, sous réserve des contrôles de sécurité définis pour le flux.

Choisir une correction qui ne déplace pas l’incident

Si le déficit est transitoire et qu’aucune montée en charge n’est nécessaire, attendez la libération observée et bloquez les relances automatiques concurrentes. Si l’autoscale demande une cible supérieure à l’enveloppe, réduisez temporairement son maximum avec un ticket, une durée et un seuil de sortie. Ce confinement ne remplace pas un subnet correctement dimensionné.

Un subnet déjà affecté à VNet Integration ne se redimensionne pas sur place. La correction durable consiste généralement à préparer un nouveau subnet, dédié, délégué à Microsoft.Web/serverFarms, avec les NSG, UDR et dépendances DNS nécessaires. Validez également l’espace d’adressage amont : créer un /26 qui chevauche une route on-premises produit un second incident plus difficile à lire.

bash creer-subnet-integration-cible.sh
az network vnet subnet create --resource-group "rg-net-prod" --vnet-name "vnet-prod" --name "snet-appsvc-integration-prod-v2" --address-prefixes "10.42.9.0/26" --delegations "Microsoft.Web/serverFarms"

az network vnet subnet show --resource-group "rg-net-prod" --vnet-name "vnet-prod" --name "snet-appsvc-integration-prod-v2" --output json

Ne recopiez pas mécaniquement toutes les règles du subnet historique. Reconstituez le contrat de sortie attendu : serveurs DNS, préfixes privés, appliance éventuelle, NAT Gateway, destinations autorisées et chemin de retour. Une règle devenue inutile ne doit pas survivre uniquement parce qu’elle existait sur v1.

Canaryer la migration et garder un rollback

Quand le plan dispose encore d’une seconde intégration possible, utilisez une application canari représentative sur le même plan pour qualifier le nouveau subnet. Sinon, utilisez un plan de validation équivalent et documentez la différence. Le canari doit tester plus que /health : résolution DNS depuis l’application, connexion TCP aux dépendances privées, identité managée, sortie Internet si Route All est actif, adresse vue par une dépendance externe et télémétrie.

text decision-migration-subnet.txt
PROMOUVOIR
Inventaire des plans et slots complet
Enveloppe au pic compatible avec le nouveau prefixe
Delegation Microsoft.Web/serverFarms validee
DNS, UDR, NSG, NAT et retour reseau testes depuis le canari
Identite et dependances applicatives validees
Autoscale canari termine avec marge positive

ARRETER
Une application ou un plan partage reste inconnu
Le canari utilise un chemin DNS ou route different de production
Le scale cree des erreurs 5xx, timeouts ou refus d'identite
La marge n'inclut pas le chevauchement des instances

ROLLBACK
Reconnecter l'application au subnet precedent pendant la fenetre
Revenir a la capacite et au maximum autoscale valides
Annuler UDR, NSG ou NAT ajoutes uniquement pour la migration
Confirmer sante, chemin sortant et absence de nouvelle tentative de scale

La bascule de l’intégration redémarre l’application. Traitez-la comme un changement de production avec fenêtre, sondes synthétiques et critère d’arrêt. Gardez l’ancien subnet intact jusqu’à validation de la nouvelle cohorte et de la première opération de scaling. Un rollback réseau sans retour à la capacité précédente peut relancer exactement le même échec.

Conclusion

Un scaling App Service bloqué n’est pas nécessairement un problème de quota compute ou de code. Avec VNet Integration, le subnet fait partie de l’enveloppe de capacité du plan : il doit absorber les instances stables, le chevauchement d’un changement de taille, les opérations de plateforme et les autres plans qui le partagent.

La décision de production doit donc être mesurable. Relancez uniquement si une adresse a réellement été libérée et si le pic calculé tient. Sinon, réduisez temporairement la cible ou migrez vers un subnet dimensionné, testé depuis une application représentative. Le rollback reste symétrique : ancienne intégration, ancienne capacité, règles réseau précédentes et validation applicative avant de rendre l’autoscale à nouveau autonome.