Hi ha una asimetria incòmoda en el que Contoso Airlines ha construït fins aquí. El codi del web de reserves està versionat, revisat per dues persones, compilat i provat a cada canvi, empaquetat amb versió semàntica i desplegat amb aprovacions i reversió en segons. La plataforma sobre la qual corre aquest codi —vnet-contoso-pro amb les seves cinc subxarxes, app-contoso-reservas-pro amb la seva ranura i el seu pla Premium v3, sql-contoso-reservas-pro amb el seu punt privat, kv-contoso-pro, el WAF, les polítiques de governança— existeix únicament perquè algú va teclejar una vegada les ordres correctes. No hi ha història, no hi ha revisió, no hi ha reversió i no hi ha manera de recrear-la a North Europe si West Europe desapareix.

Aquesta lliçó tanca aquesta bretxa i, amb ella, el mòdul. Bicep és el llenguatge d'infraestructura com a codi natiu d'Azure: descrius l'estat desitjat dels teus recursos en fitxers de text, els versiones al costat de la resta del codi i deixes que Azure Resource Manager —el mateix ARM del mòdul 1— s'encarregui que la realitat coincideixi amb la descripció.

Contingut

  1. Declaratiu davant d'imperatiu, i idempotència
  2. El panorama d'eines i per què Bicep
  3. Sintaxi de Bicep des de zero
  4. La plantilla de Contoso pas a pas
  5. Mòduls i registre privat
  6. Bucles, condicionals i àmbits de desplegament
  7. Desplegar: --what-if, modes i validació
  8. La canalització d'infraestructura
  9. Estat, secrets, desviació i decompilació
  10. Errors Comuns i Consells
  11. Exercicis
  12. Conclusió

  1. Declaratiu davant d'imperatiu, i idempotència

Imperatiu (la CLI dels mòduls 1-4) Declaratiu (Bicep)
Què escrius Els passos: crea, després configura, després connecta El resultat: això és el que ha d'existir
Executar dues vegades Falla, o duplica, llevat que tu ho controlis No passa res: ja està com ha d'estar
Estat desconegut Cal esbrinar-lo amb if i consultes El calcula la plataforma
Llegibilitat Es llegeix la història, no el resultat Es llegeix el resultat

La propietat que fa útil el declaratiu és la idempotència: aplicar la mateixa plantilla una vegada o cent produeix exactament el mateix estat final. Això canvia la naturalesa del desplegament d'infraestructura. Ja no és «una operació arriscada que cal executar en l'ordre correcte i una sola vegada», sinó «una comprovació que la realitat coincideix amb l'escrit», que es pot llançar tantes vegades com calgui. És la mateixa propietat que feia segur aquell script bash idempotent de 01-06, ara garantida per la plataforma en lloc de pel teu compte.

  1. El panorama d'eines i per què Bicep

ARM (JSON) Bicep Terraform Pulumi
Llenguatge JSON verbós DSL propi, concís HCL Llenguatges generals (C#, Python, TS)
Abast Només Azure Només Azure Multinúvol Multinúvol
Estat El guarda Azure El guarda Azure Fitxer d'estat propi que cal custodiar Servei propi o autogestionat
Serveis d'Azure el dia 1 Sí Sí Amb retard del proveïdor Amb retard
Corba d'aprenentatge Alta Baixa Mitjana Baixa si ja programes
Suport de Microsoft Sí Sí, és la recomanació No és de Microsoft No és de Microsoft

Bicep no és un producte diferent d'ARM: compila a ARM en JSON. És una capa de sintaxi, cosa que vol dir que no afegeix cap capa de traducció amb retard i que qualsevol recurs d'Azure està disponible el dia que es publica.

L'elecció honesta: si la teva organització fa servir diversos núvols, Terraform és la resposta raonable i el seu ecosistema és enorme. Si estàs només a Azure, Bicep guanya en tres coses concretes —no hi ha fitxer d'estat per custodiar, bloquejar ni corrompre; els serveis nous estan disponibles immediatament; i el suport de Microsoft és de primera part—. Contoso està només a Azure i tria Bicep. Les plantilles ARM en JSON continuen existint com a format intermedi, però ja ningú no les escriu a mà.

  1. Sintaxi de Bicep des de zero

// PARAMETRES: el que canvia entre entorns, amb tipus, decoradors i valor per defecte
@description('Entorn de desti, que governa noms i mides')
@allowed(['dev', 'pro'])
param entorn string
param ubicacio string = resourceGroup().location   // Hereta la del grup de recursos
@secure()                                          // No es registra a l historial
param contrasenyaAdministrador string

// VARIABLES: valors calculats, no parametritzables des de fora
var etiquetesComunes = {
  entorno: entorn
  proyecto: 'contoso-reservas'
  'centro-coste': 'CC-1042'
  propietario: '[email protected]'
}
// Interpolacio i uniqueString, per a un nom global unic i DETERMINISTA
var nomMagatzem = 'stcontoso${entorn}${uniqueString(resourceGroup().id)}'

// RECURS: tipus@versio-d-api, nom simbolic local, i les seves propietats
resource magatzem 'Microsoft.Storage/storageAccounts@2023-05-01' = {
  name: nomMagatzem
  location: ubicacio
  tags: etiquetesComunes
  sku: { name: entorn == 'pro' ? 'Standard_ZRS' : 'Standard_LRS' }
  kind: 'StorageV2'
  properties: {
    minimumTlsVersion: 'TLS1_2'
    allowBlobPublicAccess: false      // Politica sin-blobs-publicos (04-06)
    supportsHttpsTrafficOnly: true    // Politica solo-https
    allowSharedKeyAccess: false       // Decisio de Contoso: nomes identitat administrada
  }
}

output puntConnexioBlob string = magatzem.properties.primaryEndpoints.blob

Els quatre decoradors que més es fan servir: @description documenta el paràmetre i apareix a l'ajuda; @allowed restringeix els valors admesos i falla en validació, abans de tocar res; @secure() marca un paràmetre com a secret perquè no es registri a l'historial de desplegaments; i @minValue/@maxValue acoten els numèrics. Les funcions habituals són resourceGroup() i subscription() per llegir el context, uniqueString() per generar sufixos deterministes —el mateix grup de recursos produeix sempre el mateix sufix, cosa que preserva la idempotència— i la interpolació ${} per compondre noms.

  1. La plantilla de Contoso pas a pas

Ampliem el fitxer anterior amb el pla i l'aplicació. L'important és la dependència implícita:

var sufix = entorn == 'pro' ? 'pro' : 'dev'

resource pla 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: 'plan-contoso-reservas-${sufix}'
  location: ubicacio
  tags: etiquetesComunes
  sku: {
    name: entorn == 'pro' ? 'P1v3' : 'B1'       // Premium v3 nomes en produccio
    capacity: entorn == 'pro' ? 3 : 1
  }
  properties: {
    reserved: true                              // Linux
    zoneRedundant: entorn == 'pro'              // Redundancia de zona en produccio
  }
}

resource app 'Microsoft.Web/sites@2023-12-01' = {
  name: 'app-contoso-reservas-${sufix}'
  location: ubicacio
  tags: etiquetesComunes
  identity: { type: 'SystemAssigned' }          // Identitat administrada (04-02)
  properties: {
    // En referenciar pla.id, Bicep DEDUEIX que el pla s ha de crear abans:
    // aquesta es la dependencia implicita, i fa innecessari qualsevol dependsOn.
    serverFarmId: pla.id
    httpsOnly: true
    siteConfig: {
      linuxFxVersion: 'DOTNETCORE|8.0'
      healthCheckPath: '/salud'                 // El punt de salut de 05-04
      appSettings: [
        // El VALOR del secret no es aqui: nomes una referencia al magatzem
        { name: 'PasarelaPagoClave', value: '@Microsoft.KeyVault(SecretUri=${uriSecretPassarela})' }
      ]
    }
  }
}

// La ranura de preproduccio que 05-04 intercanvia: nomes existeix en produccio
resource ranura 'Microsoft.Web/sites/slots@2023-12-01' = if (entorn == 'pro') {
  parent: app                                   // Relacio pare-fill explicita
  name: 'preproduccion'
  location: ubicacio
  properties: { serverFarmId: pla.id }
}

Els valors per entorn se separen en fitxers .bicepparam, que substitueixen els antics fitxers de paràmetres JSON:

// pro.bicepparam
using './main.bicep'          // Vinculat a la plantilla: els errors es detecten en validar

param entorn = 'pro'
param ubicacio = 'westeurope'

Una plantilla, tants fitxers de paràmetres com entorns. Aquesta és la resposta a «recrear la plataforma en una altra regió»: canviar una línia del fitxer de paràmetres.

  1. Mòduls i registre privat

Un fitxer únic amb tota la plataforma seria ingovernable. Un mòdul és simplement un altre fitxer .bicep invocat des del principal:

// 'name' identifica el desplegament niat a l historial del grup de recursos
module xarxa 'modulos/modulo-red.bicep' = {
  name: 'desplegament-xarxa'
  params: { entorn: entorn, ubicacio: ubicacio, espaiAdreces: '10.20.0.0/16' }
}

module aplicacio 'modulos/modulo-app.bicep' = {
  name: 'desplegament-app'
  params: {
    entorn: entorn
    // Consumir una sortida de l altre modul crea la dependencia implicita
    idSubxarxaIntegracio: xarxa.outputs.idSubxarxaIntegracioApp
  }
}

Quan els mòduls es comparteixen entre equips, deixen de viure al repositori i passen a un registre privat, que a Azure és l'Azure Container Registry —el mateix servei que allotja imatges de contenidor, tema de 06-01—:

az bicep publish --file modulos/modulo-red.bicep \
  --target br:acrcontosopro.azurecr.io/bicep/modulo-red:v1.2.0
// Consumir-lo per la seva versio exacta, igual que un paquet de 05-05
module xarxa 'br:acrcontosopro.azurecr.io/bicep/modulo-red:v1.2.0' = {
  name: 'desplegament-xarxa'
  params: { entorn: entorn, ubicacio: ubicacio }
}

És la mateixa idea que les plantilles de canalització ancorades a etiqueta (05-03) i que els paquets versionats (05-05): la peça compartida té versió i qui la consumeix decideix quan actualitzar.

  1. Bucles, condicionals i àmbits de desplegament

// BUCLE: les cinc subxarxes de vnet-contoso-pro, generades des d una llista
var subxarxes = [
  { nom: 'snet-web',             prefix: '10.20.1.0/24' }
  { nom: 'snet-app',             prefix: '10.20.2.0/24' }
  { nom: 'snet-datos',           prefix: '10.20.3.0/24' }
  { nom: 'snet-gestion',         prefix: '10.20.4.0/24' }
  { nom: 'snet-integracion-app', prefix: '10.20.5.0/24' }
]

resource xarxa 'Microsoft.Network/virtualNetworks@2023-11-01' = {
  name: 'vnet-contoso-${sufix}'
  location: ubicacio
  properties: {
    addressSpace: { addressPrefixes: ['10.20.0.0/16'] }
    subnets: [for s in subxarxes: {
      name: s.nom
      properties: { addressPrefix: s.prefix }
    }]
  }
}

// CONDICIONAL: el punt privat de SQL nomes existeix en produccio
resource puntPrivat 'Microsoft.Network/privateEndpoints@2023-11-01' = if (entorn == 'pro') {
  name: 'pe-sql-reservas'
  location: ubicacio
  properties: { /* subxarxa snet-datos i connexio al servidor */ }
}

No tot es desplega en un grup de recursos. L'àmbit es declara al principi del fitxer, i això és el que permet portar a codi les polítiques del mòdul 4:

targetScope = 'subscription'    // Permet crear grups de recursos i assignar politiques

resource grupXarxa 'Microsoft.Resources/resourceGroups@2023-07-01' = {
  name: 'rg-contoso-red-pro'
  location: 'westeurope'
  tags: etiquetesComunes
}

// La iniciativa de governanca de 04-06, ara com a codi revisable
resource assignacio 'Microsoft.Authorization/policyAssignments@2024-04-01' = {
  name: 'base-gobernanza-contoso'
  properties: {
    displayName: 'Base de gobernanza de Contoso'
    policyDefinitionId: idIniciativaGovernanca
    enforcementMode: 'Default'
  }
}

Els quatre àmbits possibles són resourceGroup (el predeterminat), subscription, managementGroup —per governar mg-contoso i els seus fills— i tenant. Amb això, la iniciativa «Base de gobernanza de Contoso» amb les seves assignacions regiones-permitidas, requiere-etiqueta-*, hereda-centro-coste, sin-blobs-publicos, solo-https, tamanos-vm-dev i diagnostico-app-service deixa de ser una cosa que algú va configurar un dia i passa a ser codi revisable.

  1. Desplegar: --what-if, modes i validació

COMU="--resource-group rg-contoso-reservas-pro --template-file main.bicep \
      --parameters pro.bicepparam"

# 1. Validar: comprova sintaxi, tipus i permisos SENSE canviar res
az deployment group validate $COMU

# 2. Vista previa: QUE canviaria exactament. El pas que evita destrosses.
az deployment group create $COMU --what-if

# 3. Desplegar de debo, en mode incremental (el predeterminat)
az deployment group create $COMU --mode Incremental \
  --name desplegament-$(date +%Y%m%d-%H%M)

La sortida de --what-if marca cada recurs amb + Create, ~ Modify, - Delete, = NoChange o ! Deploy. Llegir-la és obligatori: és la diferència entre saber què passarà i esperar que surti bé.

I ara l'advertiment més seriós de la lliçó. Els dos modes de desplegament no són equivalents:

Mode Què fa amb el que és al grup però no a la plantilla
Incremental (predeterminat) Ho deixa intacte. Només crea o modifica el que està declarat
Complete HO ESBORRA. El grup de recursos queda exactament com diu la plantilla

Advertència: un desplegament en mode Complete sobre rg-contoso-reservas-pro amb una plantilla que es va oblidar de declarar la base de dades elimina la base de dades, amb les seves còpies de seguretat dependents. És la manera més ràpida de provocar un desastre irreversible a Azure. Fes servir Incremental llevat que sàpigues exactament què fas, executa sempre --what-if abans, i protegeix els recursos crítics amb bloquejos CanNotDelete (01-05), que impedeixen l'esborrat fins i tot en mode complet.

A això s'hi afegeix el linter integrat, que avisa de males pràctiques —paràmetres sense fer servir, versions d'API antigues, secrets a sortides— i que es pot configurar a bicepconfig.json perquè certs avisos siguin errors:

az bicep lint --file main.bicep    # Hauria d executar-se a la canalitzacio i bloquejar

  1. La canalització d'infraestructura

Aquí convergeix tot el mòdul: el repositori contoso-infra té la seva pròpia canalització, amb les mateixes garanties que la del codi.

name: infra-$(Date:yyyyMMdd)$(Rev:.r)

trigger:
  branches: { include: [ main ] }
  paths:   { include: [ 'infra/*' ] }
pr:
  branches: { include: [ main ] }

pool: { vmImage: ubuntu-latest }

variables:
  - name: comu
    value: '-g rg-contoso-reservas-pro -f infra/main.bicep -p infra/pro.bicepparam'

stages:
  # ETAPA 1: s executa tambe a les sol.licituds de canvi
  - stage: validar
    jobs:
      - job: analitzar
        steps:
          - script: az bicep lint --file infra/main.bicep
            displayName: Linting de Bicep
          - task: AzureCLI@2
            displayName: Validar i publicar el what-if
            inputs:
              azureSubscription: sc-contoso-infra-pro   # Connexio amb MES permisos
              scriptType: bash
              scriptLocation: inlineScript
              inlineScript: |
                az deployment group validate $(comu)
                # El what-if es guarda com a artefacte perque qui revisi el LLEGEIXI
                az deployment group create --what-if --no-pretty-print $(comu) \
                  > $(Build.ArtifactStagingDirectory)/whatif.txt
          - publish: $(Build.ArtifactStagingDirectory)
            artifact: whatif

  # ETAPA 2: nomes des de main, i despres de l aprovacio configurada a l entorn
  - stage: desplegar
    dependsOn: validar
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - deployment: aplicar
        environment: produccion-infra    # Aqui espera l aprovacio de la Marta Rios
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                - task: AzureCLI@2
                  inputs:
                    azureSubscription: sc-contoso-infra-pro
                    scriptType: bash
                    scriptLocation: inlineScript
                    inlineScript: az deployment group create $(comu) --mode Incremental

Fixa't en el que ha passat. La infraestructura ha adquirit exactament les mateixes garanties que el codi:

graph LR
    A["Canvi a<br/>infra/main.bicep"] --> B["Sol.licitud de canvis"]
    B --> C["Lint + validate<br/>+ what-if publicat"]
    C --> D{"Revisio de<br/>Contoso-Infraestructura<br/>llegint el what-if"}
    D -->|aprovada| E["Squash sobre main"]
    E --> F{"Aprovacio de la Marta<br/>a produccion-infra"}
    F -->|aprovada| G["az deployment group create<br/>--mode Incremental"]

Fixa't també que la connexió de servei és diferent i amb més permisos (sc-contoso-infra-pro), en lloc d'haver ampliat els de sc-contoso-pro: la que desplega l'aplicació continua sense poder crear xarxes.

  1. Estat, secrets, desviació i decompilació

Gestió de l'estat. Terraform manté un fitxer d'estat que registra quins recursos gestiona, i aquest fitxer s'ha d'emmagatzemar, bloquejar per evitar escriptures simultànies i protegir, perquè conté dades sensibles; si es corromp o es perd, recuperar-lo és dolorós. Bicep no té estat propi: l'estat és Azure mateix, consultat a través d'ARM a cada desplegament. És l'avantatge operatiu més pràctic de Bicep, i la contrapartida és que Bicep només sap d'Azure.

Què no posar a Bicep. Secrets, mai. Ni tan sols amb @secure(), que només evita que el valor es registri però exigeix que algú el passi. La manera correcta és que la plantilla llegeixi el secret del magatzem en temps de desplegament:

// Referencia a un Key Vault EXISTENT, sense crear-lo
resource magatzemClaus 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
  name: 'kv-contoso-pro'
  scope: resourceGroup('rg-contoso-seguridad-pro')
}

module baseDades 'modulos/modulo-sql.bicep' = {
  name: 'desplegament-sql'
  params: {
    // getSecret nomes es pot fer servir en passar un parametre @secure() a un modul:
    // el valor no apareix mai a l historial de desplegaments ni als registres
    contrasenyaAdministrador: magatzemClaus.getSecret('sql-admin-clave')
  }
}

Encara que, com saps des del mòdul 4, la millor contrasenya és la que no existeix: l'aplicació s'autentica amb identitat administrada i el magatzem només custodia l'irreductible.

Desviació de la configuració. És el que passa quan algú canvia alguna cosa des del portal per resoldre una urgència i no ho porta a la plantilla: la realitat i el codi deixen de coincidir, i el desplegament següent revertirà aquest canvi sense avisar —o pitjor, no el revertirà i ningú no sabrà quina és la veritat—. Es detecta executant --what-if de manera programada contra producció: si la vista prèvia mostra modificacions sense que ningú hagi tocat el repositori, hi ha desviació. Afegir aquesta execució nocturna a la canalització és l'equivalent d'infraestructura a la compilació nocturna de 05-03. La prevenció és la de sempre: bloquejos de recursos, permisos de només lectura en producció i la disciplina que tot canvi passi pel repositori.

Decompilar l'existent. Tota la plataforma de Contoso ja està creada a mà. El punt de partida es genera automàticament:

# Exportar la plantilla ARM del grup de recursos i convertir-la a Bicep
az group export --name rg-contoso-reservas-pro > exportat.json
az bicep decompile --file exportat.json

El resultat sempre s'ha de netejar, i convé saber per què: l'exportació produeix noms simbòlics il·legibles (resource resource0 ...), incrusta valors literals on haurien d'anar paràmetres, arrossega propietats de només lectura que ARM rebutja en desplegar, fixa versions d'API antigues i conté identificadors complets codificats a mà. Serveix com a esborrany per no partir de zero, mai com a resultat final. El criteri pràctic: decompila, neteja, executa --what-if i no donis la plantilla per bona fins que el what-if retorni = NoChange a tot. Aquest és el moment en què la plantilla descriu fidelment el que existeix.

Errors Comuns i Consells

  • Desplegar en mode Complete sense llegir el what-if. Esborra tot el que no sigui a la plantilla. És l'error més car d'aquesta lliçó.
  • Posar secrets a la plantilla o al .bicepparam. Tots dos són al repositori. getSecret des de kv-contoso-pro, o millor, identitat administrada i cap secret.
  • Un únic fitxer gegant, o el seu contrari, dependsOn explícits per tot arreu. Mòduls per domini —xarxa, aplicació, dades, seguretat— i deixa que Bicep dedueixi les dependències de les referències: els dependsOn manuals solen sobrar i amaguen errors reals de disseny.
  • Acceptar la sortida de decompile tal qual. És un esborrany. Sense netejar-la, és menys mantenible que el JSON original.
  • Conviure amb la desviació. Tan bon punt un canvi urgent del portal no torna al repositori, la plantilla deixa de ser la veritat i tot l'edifici perd sentit.
  • Noms no deterministes. Un uniqueString(utcNow()) genera un nom diferent a cada execució i trenca la idempotència: crea recursos nous en lloc d'actualitzar els existents.
  • Consell: executa --what-if de manera programada contra producció; és el teu detector de desviació i costa uns minuts d'agent.
  • Consell: protegeix els recursos amb dades —bases de dades, magatzems de claus, comptes d'emmagatzematge— amb bloquejos CanNotDelete. És la xarxa de seguretat davant d'un error de plantilla.

Exercicis

Exercici 1: parametritzar per a dos entorns

Escriu l'esquelet d'una plantilla per al projecte d'exercicis Contoso Millas (centro-coste=CC-2077) que desplegui un pla d'App Service i una aplicació, sabent que: a dev el pla és B1 amb una instància i a pro és P1v3 amb dues i redundància de zona; les etiquetes obligatòries són les quatre del mòdul 1; només s'admeten westeurope i northeurope; i a pro hi ha d'haver una ranura preproduccion que a dev no hi és.

  1. Indica quins paràmetres, decoradors, variables i condicionals faries servir.
  2. Què va a la plantilla i què als fitxers .bicepparam?
  3. Com garanteixes que ningú no desplegui en una regió no permesa, i quin mecanisme del mòdul 4 ho reforça?

Exercici 2: llegir un what-if i decidir

La canalització d'infraestructura mostra aquesta vista prèvia abans de desplegar a rg-contoso-reservas-pro:

~ Microsoft.Web/serverfarms/plan-contoso-reservas-pro
    ~ sku.capacity: 3 => 1
= Microsoft.Web/sites/app-contoso-reservas-pro
- Microsoft.Sql/servers/sql-contoso-reservas-pro/databases/db-reservas
+ Microsoft.Storage/storageAccounts/stcontosopro7f2a
  1. Interpreta cadascuna de les quatre línies.
  2. Quina et faria rebutjar la sol·licitud de canvis immediatament, i què l'ha provocada probablement?
  3. Quins dos mecanismes haurien impedit que aquest canvi arribés a executar-se?

Exercici 3: portar a codi el que s'ha creat a mà

Contoso vol convertir en Bicep el grup rg-contoso-seguridad-pro, creat a mà al mòdul 4 i que conté kv-contoso-pro i log-contoso-pro.

  1. Descriu el procediment complet, de la primera ordre a la plantilla aprovada.
  2. Com saps que la plantilla descriu fidelment el que ja existeix?
  3. Esmenta tres defectes concrets que esperes trobar a la sortida de decompile.

Solucions

Solució 1:

  1. Paràmetres: entorn amb @allowed(['dev','pro']), ubicacio amb @allowed(['westeurope','northeurope']) i valor per defecte resourceGroup().location, i propietari com a cadena amb @description. Variables: etiquetesComunes amb entorno, proyecto: 'contoso-millas', centro-coste: 'CC-2077' i propietario; i sufix derivat d'entorn. Condicionals: l'operador ternari per a sku.name (entorn == 'pro' ? 'P1v3' : 'B1'), per a capacity (2 o 1) i per a zoneRedundant (entorn == 'pro'); i if (entorn == 'pro') al recurs de la ranura, que així no existeix en desenvolupament.
  2. A la plantilla hi va tot l'estructural: quins recursos hi ha, com es relacionen i la lògica que tradueix l'entorn en mides. Als .bicepparam hi van només els valors que distingeixen un entorn d'un altre: entorn, ubicacio i propietari. La prova que la separació és correcta és que desplegar en una altra regió només exigeix canviar una línia del fitxer de paràmetres.
  3. A la plantilla, amb @allowed, que falla a la fase de validació abans de tocar res. Però això només protegeix qui fa servir la plantilla: el reforç real és la política regiones-permitidas de la iniciativa «Base de gobernanza de Contoso» (04-06), amb efecte Deny, que rebutja la creació vingui d'on vingui, inclòs el portal o un az solt. És el principi de les dues capes: la plantilla fa fàcil el correcte, la política fa impossible l'incorrecte.

Solució 2:

  1. ~ al pla: es modifica, baixant la capacitat de 3 instàncies a 1. = a l'aplicació: sense canvis. - a db-reservas: la base de dades s'elimina. +: es crea un compte d'emmagatzematge nou.
  2. La línia - de db-reservas, sense cap dubte: és la base de dades de reserves de producció. La causa més probable és un desplegament en mode Complete amb una plantilla que no declara la base de dades, o que algú l'ha eliminada del fitxer en refactoritzar els mòduls. La baixada de capacitat de 3 a 1 instàncies en producció també mereix una pregunta, perquè compromet la redundància de zona i la capacitat en hora punta.
  3. Primer, un bloqueig CanNotDelete sobre la base de dades, que impedeix l'esborrat encara que el desplegament ho intenti. Segon, la combinació de revisió obligatòria de Contoso-Infraestructura per la directiva de ruta de 05-02 i la publicació del what-if a la sol·licitud de canvis, que és precisament perquè un humà llegeixi aquesta sortida abans d'aprovar. Com a reforç, fixar el mode a Incremental explícitament a la canalització.

Solució 3:

  1. (a) az group export --name rg-contoso-seguridad-pro > exportat.json i az bicep decompile --file exportat.json. (b) Netejar: reanomenar els símbols, extreure els valors repetits a paràmetres i variables, eliminar propietats de només lectura, actualitzar versions d'API i separar en mòduls. (c) az bicep lint i az deployment group validate. (d) --what-if fins que no proposi cap canvi. (e) Confirmar a contoso-infra amb una sol·licitud de canvis revisada per Contoso-Infraestructura. (f) Executar la canalització d'infraestructura amb la seva aprovació.
  2. Perquè el --what-if retorna = NoChange a tots els recursos. Mentre aparegui qualsevol ~ o - que ningú no ha demanat, la plantilla no coincideix amb la realitat. Aquest és el criteri objectiu que l'adopció és completa, i és la mateixa ordre que després detectarà la desviació.
  3. (a) Noms simbòlics il·legibles del tipus resource0, resource1. (b) Identificadors de recurs complets codificats literalment en lloc de referències i funcions, cosa que impedeix reutilitzar la plantilla en un altre entorn o regió. (c) Propietats de només lectura exportades que ARM rebutja en desplegar, juntament amb versions d'API antigues i valors que haurien de ser paràmetres —la ubicació, els noms— incrustats com a literals.

Conclusió

Amb aquesta lliçó es tanca el mòdul, i convé veure quant ha canviat. Entens la diferència entre l'imperatiu i el declaratiu, i per què la idempotència converteix el desplegament d'infraestructura en una comprovació repetible en lloc d'una operació de risc. Has situat Bicep al panorama amb honestedat —Terraform si hi ha diversos núvols, Bicep si estàs només a Azure, pel fitxer d'estat que no cal custodiar, els serveis disponibles el dia u i el suport de primera part— sabent que Bicep compila a ARM i que per això no arriba tard a res. Domines la seva sintaxi: param amb @allowed, @secure i @description, var, resource, output, resourceGroup(), uniqueString() i interpolació; i has construït la plantilla de Contoso pas a pas, des del compte d'emmagatzematge sol fins al pla, l'aplicació i la seva ranura, recolzant-te en les dependències implícites que Bicep dedueix sol i separant els valors per entorn en fitxers .bicepparam —la resposta concreta a «recrear-ho tot a North Europe»—.

Saps compondre amb mòduls i publicar-los versionats en un registre privat d'Azure Container Registry, recórrer llistes amb for, condicionar recursos amb if i desplegar en àmbits de subscripció i grup d'administració per portar a codi les polítiques del mòdul 4. Saps desplegar amb xarxa: validate, el --what-if que s'ha de llegir sempre, el linter, i l'advertiment que no has d'oblidar —el mode Complete esborra tot el que no sigui a la plantilla, i contra això hi ha els bloquejos CanNotDelete—. Has muntat la canalització d'infraestructura que valida, publica el what-if a la sol·licitud de canvis perquè la revisió sigui informada, demana aprovació i aplica, amb una connexió de servei pròpia i separada de la que desplega l'aplicació. I has tancat els flancs: Bicep no necessita fitxer d'estat perquè l'estat és Azure; els secrets no van a la plantilla sinó a kv-contoso-pro llegits amb getSecret, o millor encara no existeixen perquè hi ha identitat administrada; la desviació de la configuració es caça amb un --what-if programat; i el que s'ha creat a mà es decompila amb az bicep decompile sabent que el resultat és un esborrany que només està acabat quan el what-if diu NoChange a tot.

Recapitulant el mòdul sencer: Contoso Airlines hi va entrar amb en Diego enviant un ZIP per correu i la Marta enganxant ordres un divendres a la nit, i en surt amb un cicle complet i automatitzat. La feina es planifica i es rastreja a Boards, amb cada confirmació lligada al seu element de treball. El codi viu a Repos amb branques curtes, revisió obligatòria i directives que ningú —tampoc un administrador— no es pot saltar. Cada canvi es compila, es prova i s'analitza a Pipelines, produint un artefacte únic que es construeix una vegada i es desplega moltes. Aquest artefacte recorre els entorns desarrollo, preproduccion i produccion amb aprovacions, finestres de desplegament i un intercanvi de ranura que fa la reversió qüestió de segons. Les peces compartides es distribueixen versionades des d'Artifacts, amb la cadena de subministrament protegida. I la plataforma sencera —xarxes, aplicacions, bases de dades, polítiques incloses— és ara codi revisable, versionat i repetible. Les mètriques DORA amb què va començar el mòdul tenen per fi un camí real de millora.

El que ve ara ja no és sobre com es lliura el programari, sinó sobre què es lliura. La plataforma de Contoso està ben construïda, però continua recolzada en les peces del mòdul 2, i una d'elles destaca: el motor de disponibilitat viu encara a vm-motor-disponibilidad-dev, una màquina virtual que algú ha de pedaçar, dimensionar i vigilar, i que en producció es va resoldre multiplicant instàncies en un conjunt d'escalat. Al mòdul 6, Serveis avançats d'Azure, començaràs precisament per aquí: empaquetaràs aquest motor heretat en un contenidor, el publicaràs a l'Azure Container Registry i el portaràs a Container Apps, i des d'aquest punt de partida la plataforma farà un salt —orquestració amb Azure Kubernetes Service, funcions sense servidor amb Azure Functions, automatització d'integracions amb Logic Apps, arquitectures basades en missatges i esdeveniments amb Service Bus, Event Grid i Event Hubs, i finalment els serveis d'Azure AI que permetran a Contoso oferir coses que avui no pot—. El lliurament ja està resolt; ara toca modernitzar el que es lliura.

Curs d'Azure

Mòdul 1: Introducció a Azure

Mòdul 2: Serveis principals d'Azure

Mòdul 3: Bases de dades d'Azure

Mòdul 4: Seguretat a Azure

Mòdul 5: Azure DevOps

Mòdul 6: Serveis avançats d'Azure

Mòdul 7: Monitoratge i gestió

Mòdul 8: Gestió i optimització de costos

Mòdul 9: Estudis de cas i millors pràctiques

© Copyright 2026. Tots els drets reservats