Procedure consigliate per la creazione di modelli di Azure Resource Manager

Le linee guida seguenti consentono di creare modelli di Azure Resource Manager affidabili e facili da usare; sono quindi da considerare solo come suggerimenti e non come requisiti assoluti, salvo diversa indicazione. I diversi scenari potrebbero richiedere una variazione rispetto agli approcci o esempi seguenti.

Nomi di risorse

In genere vengono usati tre tipi di nomi di risorse in Resource Manager:

  • Nomi di risorse che devono essere univoci.
  • Nomi di risorse che non devono necessariamente essere univoci, ma che si desidera rendano possibile l'identificazione di una risorsa in base al contesto.
  • Nomi di risorse che possono essere generici.

Per informazioni sulla creazione di una convenzione di denominazione, vedere le linee guida sulla denominazione di un'infrastruttura di Azure. Per informazioni sulle restrizioni relative ai nomi di risorse, vedere Recommended naming conventions for Azure resources(Convenzioni di denominazione consigliate per le risorse di Azure).

Nomi di risorse univoci

È necessario fornire un nome univoco per qualsiasi tipo di risorsa con un endpoint di accesso ai dati. Alcuni tipi di risorse comuni che richiedono un nome univoco includono:

  • Archiviazione di Azure1
  • Funzionalità app Web del servizio app di Azure
  • SQL Server
  • Insieme di credenziali chiave Azure
  • Cache Redis di Azure
  • Azure Batch
  • Gestione traffico di Azure
  • Ricerca di Azure
  • HDInsight di Azure

1 I nomi di account di archiviazione devono essere formati da lettere minuscole, un massimo di 24 caratteri e non devono includere alcun segno meno.

Se si specifica un parametro per un nome di risorsa, è necessario indicare un nome univoco durante la distribuzione. In alternativa, è possibile creare una variabile che usi la funzione uniqueString() per generare un nome.

È spesso opportuno aggiungere un prefisso o un suffisso al risultato di uniqueString. La modifica del nome univoco consente di identificare più facilmente il tipo di risorsa in base al nome. Ad esempio, è possibile generare un nome univoco per un account di archiviazione usando la variabile seguente:

"variables": {
    "storageAccountName": "[concat(uniqueString(resourceGroup().id),'storage')]"
}

Nomi di risorse per l'identificazione

Si tratta di risorse cui si desidera attribuire un nome, ma di cui non è necessario garantire l'univocità. Per questi tipi di risorse, è sufficiente indicare un nome che identifichi il contesto e il tipo di risorsa. È opportuno attribuire un nome descrittivo che ne faciliti il riconoscimento in un elenco di risorse. Se è necessario modificare il nome della risorsa durante le distribuzioni, usare un parametro per il nome:

"parameters": {
    "vmName": { 
        "type": "string",
        "defaultValue": "demoLinuxVM",
        "metadata": {
            "description": "The name of the VM to create."
        }
    }
}

Se non è necessario modificare il nome durante la distribuzione, usare una variabile:

"variables": {
    "vmName": "demoLinuxVM"
}

In alternativa si può usare un valore hardcoded:

{
  "type": "Microsoft.Compute/virtualMachines",
  "name": "demoLinuxVM",
  ...
}

Nomi di risorse generici

Per i tipi di risorse in gran parte accessibili tramite un'altra risorsa, è possibile usare un nome generico che sia hardcoded nel modello. Ad esempio, è possibile impostare un nome generico e standard per le regole del firewall in SQL server:

{
    "type": "firewallrules",
    "name": "AllowAllWindowsAzureIps",
    ...
}

parameters

Le informazioni seguenti possono essere utili quando si usano parametri:

  • Ridurre al minimo l'uso di parametri. Se possibile, usare una variabile o un valore letterale. Specificare parametri solo per questi scenari:

    • Impostazioni da variare in base all'ambiente (ad esempio SKU, dimensioni o capacità).
    • Nomi di risorse da specificare per facilitare l'identificazione.
    • Valori usati spesso per completare altre attività (ad esempio nome utente amministratore).
    • Segreti (ad esempio password).
    • Il numero o la matrice di valori da usare durante la creazione di più istanze di un tipo di risorsa.
  • Usare la notazione Camel per i nomi dei parametri.
  • Indicare una descrizione nei metadati per ogni parametro:

    "parameters": {
        "storageAccountType": {
            "type": "string",
            "metadata": {
                "description": "The type of the new storage account created to store the VM disks."
            }
        }
    }
    
  • Definire i valori predefiniti per i parametri (ad eccezione delle password e delle chiavi SSH):

    "parameters": {
         "storageAccountType": {
             "type": "string",
             "defaultValue": "Standard_GRS",
             "metadata": {
                 "description": "The type of the new storage account created to store the VM disks."
             }
         }
    }
    
  • Usare SecureString per tutte le password e i segreti:

    "parameters": {
        "secretValue": {
            "type": "securestring",
            "metadata": {
                "description": "The value of the secret to store in the vault."
            }
        }
    }
    
  • Quando possibile, evitare di usare un parametro per specificare la posizione. Usare invece la proprietà location del gruppo di risorse. Usando l'espressione resourceGroup().location per tutte le risorse, le risorse nel modello verranno distribuite nella stessa posizione del gruppo di risorse:

    "resources": [
      {
          "name": "[variables('storageAccountName')]",
          "type": "Microsoft.Storage/storageAccounts",
          "apiVersion": "2016-01-01",
          "location": "[resourceGroup().location]",
          ...
      }
    ]
    

    Se un tipo di risorsa è supportato solo in un numero limitato di posizioni, provare a specificare una posizione valida direttamente nel modello. Se è necessario usare un parametro location, condividere per quanto possibile il relativo valore con le risorse che potrebbero essere nella stessa posizione. Questo approccio permette di ridurre al minimo il numero di volte in cui gli utenti devono dare informazioni sulla posizione.

  • Evitare di usare un parametro o una variabile per la versione dell'API per un tipo di risorsa. I valori e le proprietà delle risorse possono variare in base al numero di versione. Quando la versione dell'API è impostata su un parametro o una variabile, IntelliSense negli editor di codice non può determinare lo schema corretto. Impostare invece la versione dell'API come hardcoded nel modello.

variables

Le informazioni seguenti possono essere utili quando si usano variabili:

  • Usare le variabili per i valori da usare più volte in un modello. Se un valore viene usato una sola volta, un valore hardcoded facilita la lettura del modello.
  • Non è possibile usare la funzione reference nella sezione variables del modello. La funzione reference deriva il proprio valore dallo stato di runtime della risorsa, ma le variabili vengono risolte durante l'analisi iniziale del modello. Costruire invece valori che richiedono la funzione reference direttamente nella sezione resources o outputs del modello.
  • Includere le variabili per i nomi di risorse che devono essere univoci, come illustrato in Nomi di risorse.
  • È possibile raggruppare le variabili in oggetti complessi. È possibile fare riferimento a un valore da un oggetto complesso nel formato variable.subentry. Il raggruppamento delle variabili consente di tenere traccia delle variabili correlate e migliora la leggibilità del modello. Ad esempio:

    "variables": {
        "storage": {
            "name": "[concat(uniqueString(resourceGroup().id),'storage')]",
            "type": "Standard_LRS"
        }
    },
    "resources": [
      {
          "type": "Microsoft.Storage/storageAccounts",
          "name": "[variables('storage').name]",
          "apiVersion": "2016-01-01",
          "location": "[resourceGroup().location]",
          "sku": {
              "name": "[variables('storage').type]"
          },
          ...
      }
    ]
    
    Nota

    Un oggetto complesso non può contenere un'espressione che fa riferimento a un valore da un oggetto complesso. A questo scopo, definire una variabile separata.

    Per esempi avanzati di uso di oggetti complessi come variabili, vedere Condividere lo stato tra modelli di Azure Resource Manager.

Risorse

Le informazioni seguenti possono essere utili quando si usano le risorse:

  • Specificare comments per ogni risorsa nel modello per consentire ad altri collaboratori di comprendere lo scopo della risorsa:

    "resources": [
      {
          "name": "[variables('storageAccountName')]",
          "type": "Microsoft.Storage/storageAccounts",
          "apiVersion": "2016-01-01",
          "location": "[resourceGroup().location]",
          "comments": "This storage account is used to store the VM disks.",
          ...
      }
    ]
    
  • È possibile usare i tag per aggiungere metadati alle risorse. Usare i metadati per aumentare le informazioni sulle risorse. Ad esempio, è possibile aggiungere metadati per registrare i dettagli di fatturazione di una risorsa. Per altre informazioni, vedere Uso dei tag per organizzare le risorse di Azure.

  • Se si usa un endpoint pubblico nel modello, come ad esempio un endpoint pubblico di archiviazione BLOB di Azure, non impostare come hardcoded lo spazio dei nomi. Usare la funzione reference per recuperare lo spazio dei nomi in modo dinamico. Questo approccio consente di distribuire il modello in ambienti diversi dello spazio dei nomi pubblico senza dover modificare manualmente l'endpoint nel modello. Impostare la versione dell'API sulla stessa versione in uso per l'account di archiviazione nel modello:

    "osDisk": {
        "name": "osdisk",
        "vhd": {
            "uri": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')), '2016-01-01').primaryEndpoints.blob, variables('vmStorageAccountContainerName'), '/',variables('OSDiskName'),'.vhd')]"
        }
    }
    

    Se l'account di archiviazione viene distribuito nello stesso modello creato, non è necessario specificare lo spazio dei nomi del provider quando si fa riferimento alla risorsa. La sintassi semplificata è:

    "osDisk": {
        "name": "osdisk",
        "vhd": {
            "uri": "[concat(reference(variables('storageAccountName'), '2016-01-01').primaryEndpoints.blob, variables('vmStorageAccountContainerName'), '/',variables('OSDiskName'),'.vhd')]"
        }
    }
    

    Se nel modello sono presenti altri valori configurati per usare uno spazio dei nomi pubblico, modificarli in modo da riflettere la stessa funzione reference. Ad esempio, è possibile impostare la proprietà storageUri del profilo di diagnostica della macchina virtuale:

    "diagnosticsProfile": {
        "bootDiagnostics": {
            "enabled": "true",
            "storageUri": "[reference(concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName')), '2016-01-01').primaryEndpoints.blob]"
        }
    }
    

    È anche possibile fare riferimento a un account di archiviazione in un gruppo di risorse diverso:

    "osDisk": {
        "name": "osdisk", 
        "vhd": {
            "uri":"[concat(reference(resourceId(parameters('existingResourceGroup'), 'Microsoft.Storage/storageAccounts/', parameters('existingStorageAccountName')), '2016-01-01').primaryEndpoints.blob,  variables('vmStorageAccountContainerName'), '/', variables('OSDiskName'),'.vhd')]"
        }
    }
    
  • Assegnare indirizzi IP pubblici a una macchina virtuale solo se richiesto per un'applicazione. Per connettersi a una macchina virtuale (VM) per il debug o per la gestione o a scopi amministrativi, usare le regole NAT in ingresso, un gateway di rete virtuale o un jumpbox.

    Per altre informazioni sulla connessione alle macchine virtuali, vedere:

  • La proprietà domainNameLabel deve essere univoca per gli indirizzi IP pubblici. Il valore domainNameLabel deve avere una lunghezza compresa tra 3 e 63 caratteri e seguire le regole specificate dall'espressione regolare seguente: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$. Dato che la funzione uniqueString genera una stringa lunga 13 caratteri, il parametro dnsPrefixString non deve superare 50 caratteri:

    "parameters": {
        "dnsPrefixString": {
            "type": "string",
            "maxLength": 50,
            "metadata": {
                "description": "The DNS label for the public IP address. It must be lowercase. It should match the following regular expression, or it will raise an error: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$"
            }
        }
    },
    "variables": {
        "dnsPrefix": "[concat(parameters('dnsPrefixString'),uniquestring(resourceGroup().id))]"
    }
    
  • Quando si aggiunge una password a un'estensione di script personalizzato, usare la proprietà commandToExecute nella proprietà protectedSettings:

    "properties": {
        "publisher": "Microsoft.Azure.Extensions",
        "type": "CustomScript",
        "typeHandlerVersion": "2.0",
        "autoUpgradeMinorVersion": true,
        "settings": {
            "fileUris": [
                "[concat(variables('template').assets, '/lamp-app/install_lamp.sh')]"
            ]
        },
        "protectedSettings": {
            "commandToExecute": "[concat('sh install_lamp.sh ', parameters('mySqlPassword'))]"
        }
    }
    
    Nota

    Per garantire che i segreti passati come parametri a macchine virtuali ed estensioni siano crittografati, usare la proprietà protectedSettings delle estensioni pertinenti.

outputs

Se viene usato un modello per creare indirizzi IP pubblici, deve includere una sezione outputs che restituisca i dettagli dell'indirizzo IP e del nome di dominio completo (FQDN). Questi valori di output consentiranno di recuperare facilmente i dettagli sugli indirizzi IP pubblici e sugli FQDN dopo la distribuzione. Quando si fa riferimento alla risorsa, usare la versione dell'API impiegata per crearla:

"outputs": {
    "fqdn": {
        "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses',parameters('publicIPAddressName')), '2016-07-01').dnsSettings.fqdn]",
        "type": "string"
    },
    "ipaddress": {
        "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses',parameters('publicIPAddressName')), '2016-07-01').ipAddress]",
        "type": "string"
    }
}

Modello singolo o modelli annidati

Per distribuire la soluzione, è possibile usare un modello singolo o un modello principale con più modelli annidati. I modelli annidati sono comuni per scenari più avanzati. L'uso di un modello annidato presenta i vantaggi seguenti:

  • È possibile scomporre la soluzione in componenti di destinazione.
  • È possibile riusare i modelli annidati con modelli principali diversi.

Quando si decide di scomporre la progettazione del modello in più modelli annidati, le linee guida seguenti ne consentono la standardizzazione. Queste linee guida si basano sui criteri di progettazione per modelli di Azure Resource Manager. La progettazione consigliata include i modelli seguenti:

  • Modello principale (azuredeploy.json). Da usare per i parametri di input.
  • Modello di risorse condivise. Da usare per distribuire le risorse condivise da tutte le altre risorse (ad esempio, rete virtuale e set di disponibilità). L'espressione dependsOn deve essere usata per assicurarsi che questo modello venga distribuito prima degli altri.
  • Modello di risorse facoltative. Da usare per distribuire risorse in modo condizionale in base a un parametro, ad esempio un jumpbox.
  • Modello di risorse membro. Ogni tipo di istanza all'interno di un livello di applicazione prevede una propria configurazione. All'interno di un livello, è possibile definire diversi tipi di istanza. Ad esempio, la prima istanza crea un cluster mentre le altre vengono aggiunte al cluster esistente. Ogni tipo di istanza avrà un proprio modello di distribuzione.
  • Script. Per ogni tipo di istanza sono applicabili script ampiamente riutilizzabili, come ad esempio quelli di inizializzazione e formattazione di dischi aggiuntivi. Gli script personalizzati vengono creati per scopi di personalizzazione specifici e variano in base al tipo di istanza.

Modello annidato

Per altre informazioni, vedere Uso di modelli collegati con Azure Resource Manager.

È possibile collegarsi in modo condizionale ai modelli annidati usando un parametro che diventa parte dell'URI per il modello:

"parameters": {
    "newOrExisting": {
        "type": "String",
        "allowedValues": [
            "new",
            "existing"
        ]
    }
},
"variables": {
    "templatelink": "[concat('https://raw.githubusercontent.com/Contoso/Templates/master/',parameters('newOrExisting'),'StorageAccount.json')]"
},
"resources": [
    {
        "apiVersion": "2015-01-01",
        "name": "nestedTemplate",
        "type": "Microsoft.Resources/deployments",
        "properties": {
            "mode": "incremental",
            "templateLink": {
                "uri": "[variables('templatelink')]",
                "contentVersion": "1.0.0.0"
            },
            "parameters": {
            }
        }
    }
]

Formato del modello

È consigliabile passare il modello tramite un validator JSON. Un validator può aiutare a rimuovere virgole, parentesi e parentesi quadre estranee che potrebbero causare un errore durante la distribuzione. Provare JSONlint o un pacchetto linter per l'ambiente di modifica preferito (Visual Studio Code, Atom, Sublime Text, Visual Studio).

È anche consigliabile formattare il codice JSON per una migliore leggibilità. È possibile usare un pacchetto formattatore JSON per l'editor locale. In Visual Studio formattare il documento con Ctrl+K, Ctrl+D. In Visual Studio Code, usare Alt+Shift+F. Se l'editor locale non formatta il documento, è possibile usare un formattatore online.

Passaggi successivi