Martin Rylko
  • Služby
  • Blog
  • O mně
  • Kontakt
  • Spolupráce
Martin Rylko

Senior Cloud Architect & DevOps Engineer. Specializace na Microsoft Azure, IaC, Cloud Security a AI.

Navigace

  • Služby
  • Blog
  • O mně
  • Kontakt

Spolupráce

Hledáte zkušeného architekta pro Váš Azure projekt? Ozvěte se.

rylko@cloudmasters.cz

© 2026 Martin Rylko. Všechna práva vyhrazena.

Buduji v cloudu. Nasazuji přes Azure Static Web Apps.

Domů/Blog/Bicep Deployment Stacks: Lifecycle management bez ručního cleanupu
Všechny článkyRead in English

Bicep Deployment Stacks: Lifecycle management bez ručního cleanupu

28. 4. 2026 4 min
#Bicep#Azure#IaC#DevOps#Deployment Stacks

Bicep Deployment Stacks: Lifecycle management bez ručního cleanupu

Klasický Bicep deployment řeší jeden problém: jak nasadit resources. Neřeší dva další: jak je v čase udržovat jako celek a jak je bezpečně odstranit. Deployment Stacks (GA od konce 2024) tohle dorovnávají a v Christie's i Nespresso jsme je v roce 2026 zavedli jako default pattern pro aplikační deploymenty.

Tenhle článek shrnuje, kdy je použít, jak migrovat existující prostředí a kde jsou pasti.

Problém, který Deployment Stack řeší

Scénář, který každý IaC engineer zná: tým má main.bicep s Function App, Storage Account, Key Vault a třemi role assignmenty. Po půl roce už není v šabloně Storage Account potřeba, někdo ho odstraní z main.bicep, mergne PR, spustí az deployment group create. Co se stane?

Storage Account v Azure zůstane. Klasický deployment je idempotentní pouze pro create/update, ne pro delete. Resource zůstává až do ručního smazání. Po roce máte 50 orphan resources, které někdo musí proklikat.

Deployment Stack řeší tohle:

# Bez stacku – Storage zůstane v Azure i po odebrání z šablony
az deployment group create \
  --resource-group rg-prod \
  --template-file main.bicep
 
# Se stackem – Storage se smaže při dalším update, pokud chybí v šabloně
az stack group create \
  --name "stack-app-prod" \
  --resource-group rg-prod \
  --template-file main.bicep \
  --action-on-unmanage deleteResources \
  --deny-settings-mode denyDelete

Tři klíčové vlastnosti Deployment Stack

VlastnostCo děláDefault value
Managed resources trackingPersistent list všech resources, které stack vytvořilAuto-managed
actionOnUnmanageCo dělat s resources odebranými ze šablonydetachResources (bezpečné)
denySettingsVytvoří denyAssignment, který blokuje manuální změnynone

actionOnUnmanage – tři volby a kdy je použít

# Pro dev/test – mažeme aktivně
--action-on-unmanage deleteResources
 
# Pro produkci – detach (manuální cleanup po review)
--action-on-unmanage detachResources
 
# Pro ephemeral environments – mazat všechno včetně RG
--action-on-unmanage deleteAll

Můj defaultní pattern: dev má deleteResources, produkce má detachResources plus monitoring alert na detached resources, ephemeral environments mají deleteAll.

denySettings – ochrana proti ručním změnám

To nejvíc novátorské. Stack může vytvořit denyAssignment, který blokuje konkrétní operace na resources i pro vlastníka subskripce:

az stack group create \
  --name "stack-prod" \
  --resource-group rg-prod \
  --template-file main.bicep \
  --deny-settings-mode denyDelete \
  --deny-settings-excluded-principals "<oncall-team-objectId>" \
  --deny-settings-excluded-actions "Microsoft.Authorization/roleAssignments/write"

Co tohle vynutí:

  • Nikdo (ani Owner) nemůže přes Portal/CLI smazat resources spravované stackem
  • Výjimka: oncall team může v incident response
  • Výjimka: role assignments lze měnit i mimo stack (např. když Entra ID admin přiřazuje rolu)

Pro regulované workloady (banking, healthcare) je tohle game changer – nahrazuje resource locks s mnohem granulárnější kontrolou.

Reálný stack: aplikační deployment v Christie's

Vzor, který používáme pro každou aplikaci:

// main.bicep
targetScope = 'resourceGroup'
 
param appName string
param environment string
param location string = resourceGroup().location
 
// Storage pro app data
module storage 'br:cmnregistry.azurecr.io/bicep/cmn-storage:1.4.3' = {
  name: 'storage-${appName}'
  params: {
    storageAccountName: 'st${appName}${environment}'
    location: location
    sku: 'Standard_LRS'
  }
}
 
// Function App s VNet integration
module funcApp 'br:cmnregistry.azurecr.io/bicep/cmn-funcapp:2.1.0' = {
  name: 'func-${appName}'
  params: {
    appName: 'func-${appName}-${environment}'
    location: location
    subnetId: subnetId
    storageAccountId: storage.outputs.id
  }
}
 
// Key Vault
module kv 'br:cmnregistry.azurecr.io/bicep/cmn-keyvault:1.2.0' = {
  name: 'kv-${appName}'
  params: {
    name: 'kv-${appName}-${environment}'
    location: location
    enableRbacAuthorization: true
  }
}
 
// Role assignment – Function MI -> KV Secrets User
module kvRole 'br:cmnregistry.azurecr.io/bicep/cmn-roleassignment:1.0.0' = {
  name: 'role-${appName}-kv'
  params: {
    principalId: funcApp.outputs.identityPrincipalId
    roleDefinitionId: '4633458b-17de-408a-b874-0445c86b69e6'  // KV Secrets User
    scope: kv.outputs.id
  }
}

Deploy přes stack:

az stack group create \
  --name "stack-${APP_NAME}-${ENV}" \
  --resource-group "rg-${APP_NAME}-${ENV}" \
  --template-file main.bicep \
  --parameters appName=${APP_NAME} environment=${ENV} \
  --action-on-unmanage detachResources \
  --deny-settings-mode denyDelete \
  --deny-settings-excluded-principals "${ONCALL_TEAM_OID}"

Pokud někdo později z main.bicep odebere module storage, příští az stack group create storage detachne (s logem). Operations team uvidí v az stack group show listu detached resources a může je manuálně smazat.

Migrace existujícího prostředí na stack: adoption

Pokud máte už deployed resources přes klasický deployment, nemusíte je recreate. Stack umí "adoption":

# Krok 1: dry-run, ověřte si, co se stane
az stack group validate \
  --name "stack-app-prod" \
  --resource-group rg-app-prod \
  --template-file main.bicep
 
# Krok 2: vytvořte stack se stejnými parametry jako original deployment
az stack group create \
  --name "stack-app-prod" \
  --resource-group rg-app-prod \
  --template-file main.bicep \
  --parameters @prod.parameters.json \
  --action-on-unmanage detachResources \
  --deny-settings-mode none  # poprvé bez deny – nejdřív ověřit

Po prvním create Azure zaregistruje existující resources jako managed by stack. Při druhém update s --deny-settings-mode denyDelete přidáte deny assignments.

Pozor: adoption neignoruje drift. Pokud má existující Storage Account jiný SKU než šablona, stack udělá update na deklarovaný SKU. Vždy nejdřív what-if:

az stack group create \
  --name "stack-app-prod" \
  --resource-group rg-app-prod \
  --template-file main.bicep \
  --parameters @prod.parameters.json \
  --what-if \
  --action-on-unmanage detachResources

CI/CD integrace: stack v GitHub Actions

# .github/workflows/deploy.yml
name: Deploy app stack
on:
  push:
    branches: [main]
    paths: ['infra/**']
 
permissions:
  id-token: write
  contents: read
 
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
 
      - uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
 
      - name: Deploy stack
        run: |
          az stack group create \
            --name "stack-${{ vars.APP_NAME }}-prod" \
            --resource-group "rg-${{ vars.APP_NAME }}-prod" \
            --template-file infra/main.bicep \
            --parameters @infra/prod.parameters.json \
            --action-on-unmanage detachResources \
            --deny-settings-mode denyDelete \
            --deny-settings-excluded-principals "${{ vars.ONCALL_OID }}" \
            --yes

--yes přeskočí interactive prompt o destruktivních změnách. V produkci: vždy mít předchozí krok s --what-if a manual approval gate v Environments.

Tři pasti, které stojí za zmínku

  1. DenyAssignments brání i schválené operace – pokud Bicep šablona obsahuje roleAssignment, který existuje, deploy padne s RoleAssignmentExists. Musíte buď přidat principal do excluded list, nebo použít --deny-settings-excluded-actions
  2. Stack name max 90 znaků – pro convention stack-${appname}-${env}-${region} musíte hlídat. V Christie's jsme se na to spálili u dlouhých feature branch deploymentů
  3. detachResources bez monitoringu = orphan farm – pokud nemáte alert na detached resources, akumulují se. V Christie's máme weekly KQL query, který detected resources reportuje na Teams channel platform týmu

Cena: nula, ale watch out na quota

Deployment Stacks samy o sobě nic nestojí – jsou součástí ARM service. Ale: každý stack zabírá quota subscription deployments (default 800 per RG). Pro prostředí s 50+ aplikacemi v jedné RG (což byste neměli mít, ale...) se to může vyčerpat. Solution: jedna RG per app, ne jedna RG per environment.

Závěr

Deployment Stacks jsou v dubnu 2026 zralá technologie, která řeší tři dlouhodobé bolesti: orphan resources, drift z manuálních změn a destruktivní cleanup chyby. Cena migrace je nízká (adoption pattern), benefit vysoký (denyAssignments + automatic lifecycle).

V Christie's i Nespresso jsme všechny nové aplikační deploymenty od ledna 2026 dělá přes stacks. Migration legacy deploymentů běží rolling, aniž bychom recreate produkční resources.

Pokud zvažujete migration na Deployment Stacks ve vlastním prostředí, podívejte se na naše služby cloudové architektury nebo se ozvěte pro IaC review.

Tagy:#Bicep#Azure#IaC#DevOps#Deployment Stacks
LinkedInX / Twitter

O autorovi

Martin Rylko

Martin Rylko

Senior Cloud Architect & DevOps Engineer

Více než 14 let v IT – od on-premises datacenter a Hyper-V clusteringu po cloudovou infrastrukturu v Microsoft Azure. Specializuji se na Landing Zones, IaC automatizaci, Kubernetes a bezpečnostní compliance.

Email LinkedInCelý profil

Nejcastejsi dotazy

Co je Deployment Stack a v čem se liší od klasického ARM/Bicep deploymentu?▾
Klasický deployment je jednorázová operace – nasadí resources a pak Azure "zapomene", které deployment je vytvořil. Deployment Stack udržuje persistent state s referencí na všechny resources, které byly nasazené – takže když resource ze šablony odeberete, stack ho při dalším update smaže (nebo detachne podle action). Plus volitelně přidává denyAssignments, které brání manuální změně mimo IaC.
Kdy zvolit Deployment Stack místo klasického deploymentu?▾
Vždy, když resources tvoří logický celek se sdíleným lifecycle – například celá Landing Zone, celý microservice (Function App + Storage + KV + role assignments) nebo celý ephemeral test environment. Pro one-off operace (vytvoření jedné resource group, single resource update) je stack overhead. V Christie's jsme všechny aplikační deploymenty převedli na stacks; sdílené platform moduly zůstaly na klasickém deploymentu.
Co znamená actionOnUnmanage a jak ho správně nastavit?▾
actionOnUnmanage určuje, co se stane s resources, které jsou ve stacku, ale už nejsou v šabloně. Tři možnosti: deleteResources (smazat resources), detachResources (ponechat resources, jen je odebrat ze stacku), deleteAll (smazat resources včetně RG). Pro produkční stacks doporučuji deleteResources s manuální review – nikdy deleteAll, protože jeden chybný PR může smazat celou RG.
Lze migrovat existující resources do Deployment Stacku bez recreate?▾
Ano, od září 2024 Azure podporuje "adoption" – existing resources se přidají do stacku přes redeploy se stejnými parametry. Stack si je zaregistruje jako managed bez recreate. Pozor: pokud máte na resources lock nebo manuálně přidaný tag, který šablona neobsahuje, adoption to neuvidí. Nejdřív vždy spusťte what-if a verifikujte výstup.

Mohlo by vás zajímat

Bicep shared moduly: Skip-if-exists pattern místo --force

Jak v enterprise prostředí publikovat Bicep moduly do ACR bez rizika přepisu existujících verzí. Skip-if-exists pattern, PR validace a semver hygiena.

Číst

Bicep CI/CD: GitHub Actions pipeline pro Azure

Produkční deployment pipeline pro Bicep v GitHub Actions. What-if náhledy, schvalování prostředí, OIDC autentizace a rollback strategie.

Číst

Terraform Azure moduly: Privátní registr a testování

Znovupoužitelné Terraform moduly pro Azure s publikací do privátního registru, automatizované testování Terratest a verzovaná spotřeba modulů v produkci.

Číst