Infrastructure
Azure Storage : valider l'impact d'une lifecycle policy avant suppression
Un runbook de production pour qualifier une lifecycle policy Azure Storage avec inventaire Blob, versions, snapshots, règles de suppression ou tiering, preuves, validation et rollback avant d'effacer des données.
Une lifecycle policy Azure Storage paraît souvent simple : déplacer les blobs anciens vers Cool ou Archive, supprimer les snapshots obsolètes, nettoyer des exports temporaires. En production, c’est plus risqué. Une règle trop large peut toucher un préfixe partagé, supprimer une version encore utile, archiver un objet que l’application relit chaque nuit, ou rendre un rollback beaucoup plus lent que prévu.
Le cas d’usage est un compte Storage qui reçoit des exports applicatifs, des pièces jointes et des fichiers de diagnostic. L’équipe veut activer une règle de nettoyage pour réduire le bruit et les coûts. Le problème n’est pas d’écrire la policy. Le problème est de prouver ce qu’elle toucherait, quels chemins doivent être exclus, comment valider après activation, et quoi faire si une suppression utile est détectée.
Le but du runbook est de décider : activer la policy, la limiter, la reporter, ou rollbacker avant perte de preuve.
Définir le périmètre de données
Commence par nommer les conteneurs, préfixes et types d’objets concernés. Une lifecycle policy agit sur des blobs, versions et snapshots selon l’âge, le préfixe, le type et parfois les tags d’index. Elle ne comprend pas l’intention métier derrière un dossier.
storage_account: stprodappdata
subscription: production
resource_group: rg-data-prod
containers:
exports:
intended_action: delete_after_45_days
owners: product-operations
restore_need: last_successful_export_for_replay
attachments:
intended_action: no_delete_without_business_owner
owners: application-team
restore_need: user_visible_content
diagnostics:
intended_action: move_to_cool_after_30_days_delete_after_180_days
owners: platform-operations
restore_need: incident_evidence
policy_change:
decision_needed: enable_limit_or_postpone
rollback_owner: platform-operations
validation_window: 48h
excluded_prefixes:
- attachments/
- exports/manual-replay/ Si ce contrat n’existe pas, la policy sera lue comme une optimisation de stockage alors qu’elle change la capacité de restauration, de preuve et parfois de conformité.
Lire la policy existante et l’historique
Avant de créer une règle, capture l’état actuel. Il faut savoir si une policy existe déjà, qui l’a modifiée récemment, et si le compte utilise soft delete, versioning, snapshots ou immutability.
RG="rg-data-prod"
ACCOUNT="stprodappdata"
az storage account management-policy show --resource-group "$RG" --account-name "$ACCOUNT" --output json
az storage account blob-service-properties show --resource-group "$RG" --account-name "$ACCOUNT" --query "{deleteRetention:deleteRetentionPolicy,containerDeleteRetention:containerDeleteRetentionPolicy,versioning:isVersioningEnabled,changeFeed:changeFeed.enabled,restorePolicy:restorePolicy}" --output json
az monitor activity-log list --resource-group "$RG" --offset 14d --query "[?contains(operationName.value, 'managementPolicies') || contains(operationName.value, 'blobServices')].{time:eventTimestamp,operation:operationName.value,caller:caller,status:status.value}" --output table Cette lecture évite deux erreurs fréquentes : activer une suppression sans fenêtre de récupération adaptée, ou modifier une policy déjà utilisée par une autre équipe.
Reconstituer l’impact avant activation
Azure Storage Lifecycle Management ne doit pas être traité comme un bouton avec dry-run magique. Avant activation, construis un inventaire des blobs qui seraient candidats selon les critères de la règle. L’objectif est d’obtenir une liste de chemins, d’âges, de tailles et de propriétaires probables.
ACCOUNT="stprodappdata"
CONTAINER="exports"
CUTOFF="2026-06-10T00:00:00Z"
az storage blob list --account-name "$ACCOUNT" --container-name "$CONTAINER" --auth-mode login --include m t v --query "[?properties.lastModified < '$CUTOFF'].{name:name,lastModified:properties.lastModified,accessTier:properties.blobTier,size:properties.contentLength,versionId:versionId,tags:tags}" --output json Pour les gros volumes, préfère Blob Inventory ou un export contrôlé plutôt qu’une boucle CLI fragile. Le point important reste le même : produire un échantillon vérifiable et une estimation par préfixe avant d’écrire la règle.
Classer suppression, tiering et restauration
Toutes les actions n’ont pas le même risque. Déplacer vers Cool n’a pas le même impact qu’archiver, supprimer une version ou effacer un snapshot.
Move to Cool
Risque principal: coût et latence de lecture différents
Validation: application relit-elle ces objets dans la fenêtre normale ?
Move to Archive
Risque principal: restauration lente et parcours applicatif cassé si lecture directe attendue
Validation: aucun job de production ne dépend d'une lecture immédiate
Delete base blob
Risque principal: disparition de l'objet visible par l'application
Validation: propriétaire métier, rétention, soft delete, preuve de non-usage
Delete version or snapshot
Risque principal: perte du chemin de rollback ou de preuve incident
Validation: versioning, snapshots utiles, restauration testée, fenêtre de conservation acceptée
Filter by prefix only
Risque principal: préfixe partagé ou convention non stable
Validation: inventaire par préfixe et exclusions explicites Cette classification aide à limiter la première policy. Un bon premier changement peut tierer un préfixe de diagnostic bien compris, pas supprimer tout ce qui dépasse un âge global.
Vérifier les accès réels avant de conclure
Un blob ancien peut encore être utile. Avant de supprimer, cherche les lectures récentes, les erreurs applicatives et les dépendances batch. Les Storage logs ne remplacent pas la connaissance métier, mais ils évitent de décider uniquement à partir de la date de modification.
let Window = 30d;
StorageBlobLogs
| where TimeGenerated > ago(Window)
| where AccountName == "stprodappdata"
| where ContainerName in ("exports", "diagnostics")
| summarize reads=countif(OperationName in ("GetBlob", "GetBlobProperties")),
writes=countif(OperationName in ("PutBlob", "PutBlockList")),
deletes=countif(OperationName has "Delete"),
failures=countif(StatusCode >= 400),
callers=make_set(AuthenticationType, 5),
sampleUris=make_set(Uri, 5)
by ContainerName, bin(TimeGenerated, 1d)
| order by TimeGenerated desc Si les logs ne sont pas disponibles, c’est une donnée de décision. On peut activer d’abord les diagnostics, réduire le périmètre, ou demander une validation propriétaire avant toute suppression.
Écrire une policy bornée
La policy doit être relisible. Nomme les règles, limite les préfixes, sépare suppression et tiering, et évite de mélanger des objets métier avec des objets techniques.
{
"rules": [
{
"enabled": true,
"name": "diagnostics-cool-after-30-days",
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["diagnostics/platform/"]
},
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"delete": { "daysAfterModificationGreaterThan": 180 }
},
"snapshot": {
"delete": { "daysAfterCreationGreaterThan": 90 }
},
"version": {
"delete": { "daysAfterCreationGreaterThan": 90 }
}
}
}
}
]
} Ne commence pas par un préfixe trop haut comme exports/ si ce répertoire contient à la fois des exports rejouables, des fichiers utilisateur et des artefacts temporaires. Crée des préfixes d’exploitation stables avant d’automatiser la suppression.
Activer avec validation courte
Une fois la policy appliquée, la validation doit chercher trois choses : la policy est bien en place, les opérations attendues apparaissent, et aucun chemin exclu n’est touché.
RG="rg-data-prod"
ACCOUNT="stprodappdata"
az storage account management-policy create --resource-group "$RG" --account-name "$ACCOUNT" --policy @04-bounded-lifecycle-policy.json
az storage account management-policy show --resource-group "$RG" --account-name "$ACCOUNT" --query "policy.rules[].{name:name,enabled:enabled,filters:definition.filters,actions:definition.actions}" --output json Complète avec une surveillance des suppressions et changements de tier.
let Window = 48h;
StorageBlobLogs
| where TimeGenerated > ago(Window)
| where AccountName == "stprodappdata"
| where OperationName has_any ("Delete", "SetBlobTier")
| summarize operations=count(), statuses=make_set(StatusText, 10), sampleUris=make_set(Uri, 10)
by OperationName, ContainerName, bin(TimeGenerated, 1h)
| order by TimeGenerated desc Si des suppressions apparaissent dans un conteneur ou un préfixe non prévu, coupe la règle immédiatement et conserve les logs avant toute correction.
Préparer le rollback
Le rollback d’une lifecycle policy ne restaure pas automatiquement les objets. Il arrête les prochaines actions. La restauration dépend ensuite de soft delete, versions, snapshots, sauvegardes ou réhydratation depuis Archive.
rollback:
stop_policy:
action: disable_or_remove_rule
validation: management_policy_read_back_without_rule
restore_deleted_blob:
prerequisites:
- soft_delete_enabled
- retention_window_not_expired
- exact_container_and_blob_name_known
validation: blob_readable_from_application_path
restore_version_or_snapshot:
prerequisites:
- version_id_or_snapshot_timestamp_known
- owner_approval_for_restore
validation: restored_object_hash_or_size_matches_evidence
rehydrate_archive:
prerequisites:
- archive_tier_was_action_taken
- business_accepts_rehydration_delay
validation: object_available_before_batch_resume
evidence_to_keep:
- policy_before_after
- impacted_prefix_inventory
- StorageBlobLogs_extract
- business_owner_decision La décision de rollback doit donc arriver vite. Plus la fenêtre de rétention est courte, plus la validation initiale doit être stricte.
Décider sans ambiguïté
La décision finale doit tenir sur une fiche d’exploitation.
Activer
Inventaire candidat relu par propriétaire
Préfixes bornés et exclusions explicites
Soft delete, versioning ou autre restauration adaptés au risque
Logs disponibles pour surveiller Delete et SetBlobTier
Rollback testé ou documenté
Limiter
Préfixe trop large
Incertitude sur lectures batch ou exports rejouables
Versions ou snapshots encore utiles
Restauration non testée
Reporter
Aucun propriétaire clair
Logs insuffisants
Rétention métier ou conformité non confirmée
Policy existante mal comprise
Rollbacker
Suppression ou tiering hors périmètre
Erreurs applicatives corrélées aux objets touchés
Objet utile restaurable uniquement pendant une fenêtre courte Conclusion
Une lifecycle policy Azure Storage n’est pas seulement une règle de coût. C’est une action de production sur la disponibilité, la preuve et la restauration des données. Le runbook doit donc partir de l’inventaire, pas de la syntaxe JSON.
La bonne décision consiste à borner les préfixes, distinguer tiering et suppression, vérifier les accès réels, activer avec surveillance courte, puis garder un rollback qui arrête la policy et restaure les objets touchés quand c’est encore possible. Une suppression automatique fiable est une suppression prouvée avant d’être automatisée.