Autoscalez le stockage FSLogix

Un dimanche soir, votre stockage FSLogix sature, et personne ne le voit. Lundi matin, vos 200 utilisateurs AVD n’arrivent plus à se connecter car leur profil ne se charge plus. Que faire en ce moment d’urgence ? Vous découvrez en urgence que provisionner un share Azure avec « 8 To au cas où » , ça vous coûte un bras et demi. Ce mauvais rêve vous parle ou vous empêche de dormir ? Cet article est fait pour vous.

On va très rapidement remonter l’histoire d’Azure Files, comprendre pourquoi Provisioned v2 (GA depuis 2025) change la donne pour les workloads FSLogix, et surtout déployer ensemble, depuis Azure Cloud Shell, en moins de 5 minutes, une solution open-source qui fait grossir automatiquement le quota quand l’usage approche la saturation, avec des notifications mail à la clé.

Pour vous guider plus facilement dans cet article, voici des liens rapides :

1. Petit rappel : Azure Files, d’où on vient

Plusieurs articles ont déjà été écrits sur le sujet du stockage dans Azure :

Mais pour rappel, jusqu’ici Azure Files se déclinait essentiellement en deux familles :

  • Standard (HDD) en pay-as-you-go : pas cher, performances modestes, facturation peu prédictible (capacité utilisée + transactions).
  • Premium (SSD) en provisioned : les IOPS et le throughput étaient dérivés mécaniquement de la capacité provisionnée. Vous vouliez 50 000 IOPS ? Vous provisionniez des To de capacité, que vous les remplissiez ou non.
AttributeSSD approvisionné v1HDD, paiement à l’utilisation
La taille minimale de stockage100 Gio (approvisionné)0 octets
Taille de stockage maximale100 Tio100 Tio
Nombre maximal de fichiersUnlimitedUnlimited
Nombre maximal d’E/S par seconde (données)102 400 IOPS (dépendant de l’approvisionnement)20 000 IOPS
Débit maximal10 340 Mio /s (dépendant de l’approvisionnement)Jusqu’aux limites du compte de stockage
Microsoft Learn

Bursting v1 approvisionné :

Capacité (Gio)IOPS de référenceIOPS en rafaleLister les créditsDébit (Mio/s)
1003 100Jusqu’à 10 00024 840 000110
5003 500Jusqu’à 10 00023 400 000150
1 0244 024Jusqu’à 10 00021 513 600203
5 1208 120Jusqu’à 15 36026 064 000613
10 24013 240Jusqu’à 30 72062 928 0001 125
33 79236 792Jusqu’à 102 400227 548 8003 480
51 20054 200Jusqu’à 102 400164 880 0005 220
102 400102 400Jusqu’à 102 400010 340
Microsoft Learn

Ce dernier point a été le casse-tête FSLogix pendant des années. Sur un share AVD, vous n’avez pas spécialement besoin de 5 To de capacité, mais vous avez besoin de pouvoir encaisser une sign-in storm à 8 h le matin.

Sur du Premium V1, pour atteindre les IOPS nécessaires, vous étiez obligé de surprovisionner la capacité. Vous payiez alors de l’espace que vous n’utilisiez pas, contrairement au HDD pay-as-you-go.

Et si vous étiez tenté par le HDD pay-as-you-go pour dormir tranquille : à la place d’un long discours, voici une image qui a dû faire mal à de nombreux administrateurs d’AVD :

Mon retour terrain : sur la quasi-totalité des projets AVD que j’ai vus, le calcul de sizing FSLogix se faisait « en IOPS » et la capacité était une conséquence. Résultat : des shares à 2-4 To remplis à 30 %, payés plein pot.

2. L’arrivée de Provisioned v2

Provisioned v2 est GA depuis 2025, dans toutes les régions publiques Azure et toutes les régions Azure US Government. La grande nouveauté : on provisionne trois axes indépendants.

Le modèle v2 provisionné pour Azure Files associe la prévisibilité du coût total de possession à la flexibilité, vous permettant ainsi de créer un partage de fichiers qui répond précisément à vos exigences en matière de stockage et de performances.

Lorsque vous créez un partage de fichiers v2 approvisionné, vous spécifiez la quantité de stockage, d’IOPS et de débit dont votre partage de fichiers a besoin.

Source : Understand Azure Files billing — Microsoft Learn

Concrètement, vous payez trois choses séparément, même si certaines limites existent :

  • La capacité provisionnée (GiB)
  • Les IOPS provisionnés
  • Le throughput provisionné (MiB/s)

Et deux SKUs sont disponibles en v2 avec des redondances spécifiques :

  • Premium V2 (SSD) : LRS ou ZRS
  • Standard V2 (HDD) : LRS, ZRS, GRS ou GZRS

Voici d’ailleurs les limites officielles à connaître :

DimensionPremium V2 (SSD)Standard V2 (HDD)
Capacité min32 GiB32 GiB
Capacité max256 TiB256 TiB
IOPS min3 000500
IOPS max102 40050 000
Throughput min100 MiB/s60 MiB/s
Throughput max10 340 MiB/s5 120 MiB/s
Unité de provisioning1 GiB1 GiB
Microsoft Learn

Deux subtilités utiles à connaître :

  • Cooldown 24 h sur la descente : on peut augmenter le quota n’importe quand, mais on ne peut le diminuer qu’après 24 h sans changement.
  • Burst IOPS credit-based : sur SSD, le burst max est MIN(MAX(3 × ProvisionedIOPS, 10 000), 102 400). Pratique pour absorber les pics ponctuels sans surprovisionner.

Bursting v2 approvisionné :

IOPS provisionnéesLimite d’IOPS en rafale SSDCrédits de rafale SSDLimite de l’IOPS en mode bursting de disque de l’HDDCrédits de bursting de disque de l’HDD
500Jusqu’à 5 00016 200 000
1 000Jusqu’à 5 00014,400,000
3 000Jusqu’à 10 00025,200,000Jusqu’à 9 00021 600 000
5 000Jusqu’à 15 00036 000 000Jusqu’à 15 00036 000 000
10 000Jusqu’à 30 00072 000 000Jusqu’à 30 00072 000 000
25 000Jusqu’à 75 000180,000,000Jusqu’à 50 00090 000 000
50 000Jusqu’à 102 400188,640,000Jusqu’à 50 0000
75 000Jusqu’à 102 40098,640,000
102 400Jusqu’à 102 4000
Microsoft Learn

3. FSLogix : ce que Microsoft recommande vraiment

Côté FSLogix, la doc Microsoft Learn pose deux chiffres très concrets, par utilisateur :

Profil de chargeIOPS par utilisateur
Steady state (utilisation normale en cours de journée)10
Sign-in / Sign-out (ouverture ou fermeture de session)50

L’exemple de ce tableau est celui d’un utilisateur unique, mais il peut être utilisé pour estimer les besoins relatifs au nombre total d’utilisateurs dans votre environnement. Par exemple, vous avez besoin d’environ 1 000 IOPS pour 100 utilisateurs et environ 5 000 IOPS lors de la connexion et de la déconnexion.

Source : Container storage options — FSLogix — Microsoft Learn

Projetons ça sur quelques tailles d’environnement classiques :

UsersIOPS steady (×10)IOPS pic sign-in (×50)
505002 500
2002 00010 000
5005 00025 000
1 00010 00050 000

Côté capacité, Microsoft ne fixe pas de chiffre dur officiel par utilisateur, ça dépend des applis, d’Outlook (qui crée souvent les plus gros .OST), de OneDrive Known Folder Move, etc.

Sur la majorité des environnements AVD que j’ai croisés, on tourne entre 5 et 30 GiB par profil, avec une grosse variance. C’est exactement le genre de variable difficile à prévoir à l’avance, et c’est pour ça que l’auto-grow prend tout son sens.

Attention : les 10 / 50 IOPS sont des moyennes Microsoft. Sur une population à fort usage Office + Teams + OneDrive sync, on monte assez vite. Mesurez sur votre prod plutôt que de partir tête baissée sur la table.

4. Le piège du « pay-per-provisioned »

C’est le point qui change avec le Provisioned v2, qu’il soit SSD ou HDD. Microsoft le dit noir sur blanc :

Vous payez en fonction de ce que vous approvisionnez, quel que soit le montant que vous utilisez réellement.

Source : Understand Azure Files billing — Microsoft Learn

Concrètement : vous provisionnez 8 To « au cas où » → vous payez 8 To, qu’ils soient remplis à 5 % ou à 95 %. Plus du tout le modèle Standard pay-as-you-go d’antan où vous ne payiez que le stockage consommé.

Deux stratégies s’offrent à vous :

  1. Surprovisionner dès le départ pour ne jamais être surpris → vous payez de la capacité dormante pendant des mois.
  2. Provisionner serré (avec un peu de marge) puis grossir à la demande, dès que l’usage s’approche d’un seuil → vous payez ce dont vous avez besoin au moment où vous en avez besoin.

L’option 2 demande de l’automatisation. C’est exactement ce que fait la solution qui suit.

5. La solution : auto-grow runbook open-source

J’ai packagé tout ça sur GitHub : jlou07/azure-files-autogrow. Le repo contient trois fichiers :

  • main.bicep : déploie un Automation Account avec Managed Identity, les modules PowerShell 7.2 (Az.Accounts + Az.Storage), un runbook vide, une schedule, et toute la stack Azure Communication Services pour les emails.
  • Grow-FslogixShare.ps1 : le runbook qui lit la capacité utilisée du share, compare au seuil, agrandit le quota, et envoie un email récapitulatif.
  • deploy-cloudshell.sh : script interactif qui vous pose les questions et orchestre tout depuis Azure Cloud Shell.

Le runbook est grow-only par design : il ne diminue jamais le quota et c’est volontaire : un utilisateur qui charge un gros profil un jour et le supprime le lendemain ne doit pas déclencher une décroissance.

Et de toute façon, Azure impose 24 h de cooldown avant toute baisse, donc autant ne pas s’embêter.

Pré-requis

SubscriptionVous devez être Contributor sur un Resource Group de la sub.
Storage accountKind FileStorage avec SKU PremiumV2_* ou StandardV2_* déjà existant, avec un file share déjà créé.
Email de notifN’importe quelle adresse (interne, externe, gmail, …). Optionnelle : si vous la laissez vide, les notifs sont désactivées et la stack ACS n’est pas déployée.
OutilsAzure Cloud Shell (Bash).
Mon retour terrain : j’ai fait le choix d’Azure Communication Services pour les emails, plutôt que Microsoft Graph. Avantage énorme : un simple rôle Contributor scopé sur la ressource ACS suffit. Pas de consentement admin tenant, pas de Mail.Send au niveau du tenant, pas de mailbox à provisionner. La solution est déployable par n’importe quel admin Azure qui a un Resource Group à sa main.

6. Déploiement pas-à-pas depuis Cloud Shell

Étape 0 — Ouvrir Cloud Shell et récupérer les fichiers

Mais juste avant, j’ai déployé un Azure File Share de 50 Go sur mon environnement de test :

Allez sur shell.azure.com ou cliquez ici :

Choisissez Bash, puis :

curl -O https://raw.githubusercontent.com/jlou07/azure-files-autogrow/main/main.bicep
curl -O https://raw.githubusercontent.com/jlou07/azure-files-autogrow/main/Grow-FslogixShare.ps1
curl -O https://raw.githubusercontent.com/jlou07/azure-files-autogrow/main/deploy-cloudshell.sh
chmod +x deploy-cloudshell.sh

Étape 1 — Lancer le script

./deploy-cloudshell.sh

Le script vous pose une série de questions, dans l’ordre :

  • La subscription cible (par défaut celle qui est active dans Cloud Shell)
  • Le Resource Group où déployer l’Automation Account (créé s’il n’existe pas)
  • La région (ex. francecentral, westeurope)
  • Le RG, le nom et le nom du share du storage cible (celui qui contient le file share v2 à monitorer)
  • Le seuil de déclenchement en % (défaut 80)
  • Le growth factor (défaut 1.25, soit +25 % à chaque grossissement)
  • Le quota max en GiB (défaut 4 096)
  • La fréquence de check (PT15M, PT30M, PT1H (défaut 30 min))
  • L’email de notification (vide = pas d’emails, et la stack ACS n’est pas déployée)
  • La data location ACS (défaut Europe)

Étape 2 — Le script déroule

Une fois que vous confirmez, le script enchaîne :

  1. Crée le RG si besoin.
  2. Déploie le Bicep (Automation Account + modules + runbook vide + schedule + ACS + Email Service + Managed Domain + role assignment Contributor sur ACS).
  3. Grant Storage Account Contributor sur le storage cible à l’identité managée de l’Automation Account.
  4. Upload le contenu du Grow-FslogixShare.ps1 dans le runbook.
  5. Publie le runbook.
  6. Lie la schedule au runbook avec les bons paramètres (jobSchedule).

Voici toutes les ressources Azure présentes dans mon environnement :

Étape 3 — Vérifier dans le portail Azure

  • Automation Account → Modules : Az.Accounts et Az.Storage en statut Available (~10-15 min après le déploiement, c’est de l’import asynchrone) :
  • Runbooks → Grow-FslogixShare : statut Published :
  • Schedules → AutoGrowSchedule : enabled, avec un lien vers le job Grow-FslogixShare :
  • Storage account cible → IAM : l’identité managée de l’AA a bien le rôle Storage Account Contributor :
  • Ressource ACS → IAM : l’identité managée a Contributor :

Nous allons maintenant tester l’action d’agrandissement, le blocage au cap, et le système de notifications par email.

7. Le moment de vérité : on déclenche un grow

Dès la mise en place de la solution, un premier job doit se lancer :

Le détail de toutes les actions est visible dans le log du job :

Pour forcer un run immédiat sans attendre la prochaine occurrence dans Azure Cloud Shell :

az automation runbook start \
  -g <aa-rg> \
  --automation-account-name <aa-name> \
  --name Grow-FslogixShare \
  --parameters \
      SubscriptionId=<sub-id> \
      ResourceGroupName=<storage-rg> \
      StorageAccountName=<storage-name> \
      FileShareName=<share-name> \
      ThresholdPercent=80 \
      GrowthFactor=1.25 \
      MaxQuotaGiB=4096 \
      NotificationEmail=alerts@mondomaine.com \
      AcsEndpoint=https://<acs-name>.europe.communication.azure.com \
      AcsSenderAddress=DoNotReply@<guid>.azurecomm.net

Les jobs manuels ou automatiques sont visibles ici :

Si vous voulez juste tester l’envoi d’email sans toucher au quota, le runbook supporte un switch -WhatIf qui simule la décision sans appliquer.

Au besoin, vous pouvez modifier la configuration planifiée en en créant une nouvelle ici :

Quand l’usage du share franchit le seuil (par défaut 80 %), comme ici :

Le runbook calcule le nouveau quota (ceil(quota_actuel × 1.25), capé à MaxQuotaGiB), appelle Update-AzRmStorageShare :

La taille du partage de fichier augmente bien de 25 % :

Et enfin il envoie un email récap :

Mais, si le share atteint le cap dur (MaxQuotaGiB), le runbook arrête de le faire grossir :

Et il envoie aussi un email d’alerte en importance haute :

Attention : le premier email envoyé depuis le domaine ACS managé (DoNotReply@<guid>.azurecomm.net) peut tomber en spam. Whitelistez *.azurecomm.net côté destinataire, ou mieux branchez un custom domain vérifié dans le portail ACS (10 minutes d’enregistrements DNS).

Et comme attendu, le service veille en continu :

8. Estimation de coûts (ordres de grandeur)

Les prix Azure Files V2 varient selon la région et la redondance, et Microsoft les ajuste régulièrement.

Les chiffres qui suivent sont des ordres de grandeur pour un déploiement de 256 Go en Europe de l’Ouest, sur un workload FSLogix sur les quatre types de stockage :

Voici d’ailleurs plusieurs hypothèses de sizing FSLogix :

  • ~ 15 GiB par profil utilisateur (mid-range, typique AVD avec Office + OneDrive sync léger)
  • IOPS pic sign-in : 50 IOPS / user (recommandation Microsoft)
  • Throughput : ce que recommande Azure par défaut pour la capacité provisionnée
UsersCapacité viséeIOPS visés (pic)Stratégie « provisioned sec » à la mainStratégie « auto-grow »
50~ 750 GiB2 500Surprovisionner à 1 TiB pour avoir de la margeDémarrer à 256 GiB, grossir au fil de l’eau jusqu’à ~ 800 GiB
200~ 3 TiB10 000Provisionner d’office 4 TiBDémarrer à 1 TiB, monter par paliers de +25 %
500~ 7,5 TiB25 000Provisionner d’office 8 TiBDémarrer à 2 TiB, monter au besoin
1 000~ 15 TiB50 000Provisionner d’office 16 TiBDémarrer à 4 TiB, monter au besoin

Sur les ratios de remplissage que je vois en prod (souvent 40-60 % sur les premiers 6 mois), la stratégie auto-grow économise typiquement 30 à 50 % sur la ligne « capacité provisionnée » du share, le temps que la base utilisateurs se stabilise. L’IOPS reste à provisionner pour le pic, ou à profiter des bursts :

Coût ajouté par la solution elle-même :

  • Automation Account : les 500 premières minutes de runtime par mois sont incluses. Un check toutes les 30 minutes consomme quelques secondes par run, soit largement sous le seuil gratuit.
  • Azure Communication Services Email : facturation à l’email envoyé. Sur le volume d’un déploiement comme le nôtre (typiquement quelques dizaines d’emails par mois), c’est négligeable.

Bref : le coût de l’orchestration est ridicule face à ce que la stratégie permet d’économiser sur la capacité du share.

9. Pièges & vigilance

Attention : les modules PowerShell sont importés en asynchrone. Pendant les 10-15 minutes qui suivent le déploiement, un job qui se déclenche peut échouer avec « Could not find module Az.Accounts ». C’est normal, ça se résout tout seul. Évitez juste de tester immédiatement après le déploiement.
Attention : le Managed Domain ACS a besoin d’une à deux minutes pour être complètement provisionné après le déploiement. Le tout premier envoi d’email peut échouer ; il suffit de relancer.
Attention : le sender par défaut est DoNotReply@<guid>.azurecomm.net. Pour un envoi propre depuis alerts@mondomaine.com, il faut ajouter un custom domain vérifié dans le portail ACS (quelques enregistrements DNS, 10 minutes) puis mettre à jour AcsSenderAddress sur le jobSchedule.
Mon retour terrain : le runbook est grow-only, ne descend jamais le quota. Et tant mieux : Azure impose 24 h de cooldown avant toute baisse, et refuse toute baisse sous l’usage courant. Si vous voulez vraiment réduire, faites-le à la main après avoir mesuré sur un mois entier.

Conclusion

Voilà, en quelques minutes de Cloud Shell, vous avez :

  • Un Automation Account avec identité managée
  • Un runbook qui surveille votre share FSLogix v2 et adapte le quota automatiquement.
  • Une stack Azure Communication Services dédiée qui envoie les emails

Concrètement, ça donne quoi ? Vous ne surprovisionnez plus à l’aveugle. Vous démarrez serré, et la capacité suit l’usage réel, avec un email récap à chaque changement, et un garde-fou final si jamais ça part en vrille.

Foncez tester, le repo est en MIT, vous pouvez le forker, l’adapter à vos seuils, brancher Logic Apps ou un Teams Webhook à la place de l’email si c’est votre flow. github.com/jlou07/azure-files-autogrow.

Encore hésitant à passer votre stockage FSLogix en v2 ? Regardez cette vidéo :

Et si vous voulez creuser le calcul de sizing FSLogix plus en détail, dites-le moi en commentaire, il y a matière à un article dédié sur la mesure d’IOPS réelle vs la table Microsoft.