Melhores práticas de modelo do ARM

Este artigo mostra-lhe como utilizar práticas recomendadas ao construir o modelo do Azure Resource Manager (modelo do ARM). Estas recomendações ajudam-no a evitar problemas comuns ao utilizar um modelo do ARM para implementar uma solução.

Limites de modelo

Limite o tamanho do modelo para 4 MB e cada definição de recurso para 1 MB. Os limites aplicam-se ao estado final do modelo depois de este ter sido expandido com definições de recursos iterativas e valores para variáveis e parâmetros. O ficheiro de parâmetros também está limitado a 4 MB. Poderá ser apresentado um erro com um ficheiro de modelo ou de parâmetros inferior a 4 MB se o tamanho total do pedido for demasiado grande. Para obter mais informações sobre como simplificar o modelo para evitar pedidos grandes, veja Resolver erros de tamanho de trabalhos excedido.

Também está limitado a:

  • 256 parâmetros
  • 256 variáveis
  • 800 recursos (incluindo a contagem de cópias)
  • 64 valores de saída
  • 10 localizações exclusivas por subscrição/inquilino/âmbito do grupo de gestão
  • 24 576 carateres numa expressão de modelo

Poderá exceder alguns limites do modelo se utilizar um modelo aninhado. Para obter mais informações, veja Utilizar modelos associados e aninhados ao implementar recursos do Azure. Para reduzir o número de parâmetros, variáveis ou saídas, pode combinar vários valores num objeto. Para obter mais informações, veja Objetos como parâmetros.

Grupo de recursos

Quando implementa recursos num grupo de recursos, o grupo de recursos armazena metadados sobre os recursos. Os metadados são armazenados na localização do grupo de recursos.

Se a região do grupo de recursos estiver temporariamente indisponível, não poderá atualizar os recursos no grupo de recursos porque os metadados não estão disponíveis. Os recursos noutras regiões continuarão a funcionar como esperado, mas não poderá atualizá-los. Para minimizar o risco, localize o grupo de recursos e os recursos na mesma região.

Parâmetros

As informações nesta secção podem ser úteis quando trabalha com parâmetros.

Recomendações gerais para parâmetros

  • Minimize a utilização de parâmetros. Em vez disso, utilize variáveis ou valores literais para propriedades que não precisam de ser especificadas durante a implementação.

  • Utilize maiúsculas/minúsculas para nomes de parâmetros.

  • Utilize parâmetros para as definições que variam de acordo com o ambiente, como o SKU, o tamanho ou a capacidade.

  • Utilize parâmetros para nomes de recursos que pretende especificar para uma identificação fácil.

  • Forneça uma descrição de cada parâmetro nos metadados.

    "parameters": {
      "storageAccountType": {
        "type": "string",
        "metadata": {
          "description": "The type of the new storage account created to store the VM disks."
        }
      }
    }
    
  • Defina valores predefinidos para parâmetros que não são confidenciais. Ao especificar um valor predefinido, é mais fácil implementar o modelo e os utilizadores do modelo veem um exemplo de um valor adequado. Qualquer valor predefinido para um parâmetro tem de ser válido para todos os utilizadores na configuração de implementação predefinida.

    "parameters": {
      "storageAccountType": {
        "type": "string",
        "defaultValue": "Standard_GRS",
        "metadata": {
          "description": "The type of the new storage account created to store the VM disks."
        }
      }
    }
    
  • Para especificar um parâmetro opcional, não utilize uma cadeia vazia como um valor predefinido. Em vez disso, utilize um valor literal ou uma expressão de linguagem para construir um valor.

    "storageAccountName": {
       "type": "string",
       "defaultValue": "[concat('storage', uniqueString(resourceGroup().id))]",
       "metadata": {
         "description": "Name of the storage account"
       }
    }
    
  • Utilize allowedValues com moderação. Utilize-o apenas quando tiver de se certificar de que alguns valores não estão incluídos nas opções permitidas. Se utilizar allowedValues de forma demasiado abrangente, poderá bloquear implementações válidas ao não manter a sua lista atualizada.

  • Quando um nome de parâmetro no seu modelo corresponde a um parâmetro no comando de implementação do PowerShell, Resource Manager resolve este conflito de nomenclatura ao adicionar o postfixo FromTemplate ao parâmetro de modelo. Por exemplo, se incluir um parâmetro denominado ResourceGroupName no seu modelo, este entra em conflito com o parâmetro ResourceGroupName no cmdlet New-AzResourceGroupDeployment . Durante a implementação, é-lhe pedido que forneça um valor para ResourceGroupNameFromTemplate.

Recomendações de segurança para parâmetros

  • Utilize sempre parâmetros para nomes de utilizador e palavras-passe (ou segredos).

  • Utilize securestring para todas as palavras-passe e segredos. Se transmitir dados confidenciais num objeto JSON, utilize o secureObject tipo. Os parâmetros de modelo com cadeia segura ou tipos de objetos seguros não podem ser lidos após a implementação de recursos.

    "parameters": {
      "secretValue": {
        "type": "securestring",
        "metadata": {
          "description": "The value of the secret to store in the vault."
        }
      }
    }
    
  • Não forneça valores predefinidos para nomes de utilizador, palavras-passe ou qualquer valor que necessite de um secureString tipo.

  • Não forneça valores predefinidos para as propriedades que aumentam a área da superfície de ataque da aplicação.

Recomendações de localização para parâmetros

  • Utilize um parâmetro para especificar a localização dos recursos e defina o valor predefinido como resourceGroup().location. Fornecer um parâmetro de localização permite que os utilizadores do modelo especifiquem uma localização onde tenham permissão para implementar recursos.

    "parameters": {
       "location": {
         "type": "string",
         "defaultValue": "[resourceGroup().location]",
         "metadata": {
           "description": "The location in which the resources should be deployed."
         }
       }
    }
    
  • Não especifique allowedValues para o parâmetro de localização. As localizações especificadas podem não estar disponíveis em todas as clouds.

  • Utilize o valor do parâmetro de localização para os recursos que estão provavelmente na mesma localização. Esta abordagem minimiza o número de vezes que os utilizadores são convidados a fornecer informações de localização.

  • Para recursos que não estão disponíveis em todas as localizações, utilize um parâmetro separado ou especifique um valor de localização literal.

Variáveis

As seguintes informações podem ser úteis quando trabalha com variáveis:

  • Utilize maiúsculas/minúsculas para nomes de variáveis.

  • Utilize variáveis para valores que precisa de utilizar mais do que uma vez num modelo. Se um valor for utilizado apenas uma vez, um valor hard-coded torna o modelo mais fácil de ler.

  • Utilize variáveis para valores que constrói a partir de uma disposição complexa de funções de modelo. O modelo é mais fácil de ler quando a expressão complexa só aparece em variáveis.

  • Não pode utilizar a função de referência na variables secção do modelo. A reference função obtém o respetivo valor a partir do estado de runtime do recurso. No entanto, as variáveis são resolvidas durante a análise inicial do modelo. Construa valores que necessitem da reference função diretamente na resources secção ou outputs do modelo.

  • Inclua variáveis para nomes de recursos que têm de ser exclusivos.

  • Utilize um ciclo de cópia em variáveis para criar um padrão repetido de objetos JSON.

  • Remover variáveis não utilizadas.

Versão da API

Defina a apiVersion propriedade como uma versão da API codificada para o tipo de recurso. Ao criar um novo modelo, recomendamos que utilize a versão mais recente da API para um tipo de recurso. Para determinar os valores disponíveis, veja referência de modelo.

Quando o modelo funcionar conforme esperado, recomendamos que continue a utilizar a mesma versão da API. Ao utilizar a mesma versão da API, não tem de se preocupar com alterações interruptivas que possam ser introduzidas em versões posteriores.

Não utilize um parâmetro para a versão da API. As propriedades e os valores dos recursos podem variar consoante a versão da API. O IntelliSense num editor de código não consegue determinar o esquema correto quando a versão da API está definida como um parâmetro. Se transmitir uma versão da API que não corresponda às propriedades do modelo, a implementação falhará.

Não utilize variáveis para a versão da API.

Dependências de recursos

Ao decidir quais as dependências a definir, utilize as seguintes diretrizes:

  • Utilize a reference função e transmita o nome do recurso para definir uma dependência implícita entre os recursos que precisam de partilhar uma propriedade. Não adicione um elemento explícito dependsOn quando já tiver definido uma dependência implícita. Esta abordagem reduz o risco de ter dependências desnecessárias. Para obter um exemplo de definição de uma dependência implícita, veja funções de referência e lista.

  • Defina um recurso subordinado como dependente do recurso principal.

  • Os recursos com o elemento de condição definido como false são removidos automaticamente da ordem de dependência. Defina as dependências como se o recurso fosse sempre implementado.

  • Deixe as dependências em cascata sem as definir explicitamente. Por exemplo, a máquina virtual depende de uma interface de rede virtual e a interface de rede virtual depende de uma rede virtual e de endereços IP públicos. Por conseguinte, a máquina virtual é implementada após os três recursos, mas não define explicitamente a máquina virtual como dependente dos três recursos. Esta abordagem esclarece a ordem de dependência e facilita a alteração do modelo mais tarde.

  • Se for possível determinar um valor antes da implementação, tente implementar o recurso sem uma dependência. Por exemplo, se um valor de configuração precisar do nome de outro recurso, poderá não precisar de uma dependência. Esta documentação de orientação nem sempre funciona porque alguns recursos verificam a existência do outro recurso. Se receber um erro, adicione uma dependência.

Recursos

As seguintes informações podem ser úteis quando trabalha com recursos:

  • Para ajudar outros contribuidores a compreender a finalidade do recurso, especifique comments para cada recurso no modelo.

    "resources": [
      {
        "name": "[variables('storageAccountName')]",
        "type": "Microsoft.Storage/storageAccounts",
        "apiVersion": "2019-06-01",
        "location": "[resourceGroup().location]",
        "comments": "This storage account is used to store the VM disks.",
          ...
      }
    ]
    

    Se o modelo do ARM estiver armazenado num .jsonc ficheiro, os comentários que utilizam a // sintaxe são suportados, conforme mostrado aqui.

    "resources": [
      {
        // This storage account is used to store the VM disks.
        "name": "[variables('storageAccountName')]",
        "type": "Microsoft.Storage/storageAccounts",
        "apiVersion": "2019-06-01",
        "location": "[resourceGroup().location]",
          ...
      }
    ]
    

    Para obter mais detalhes sobre comentários e metadados, veja Compreender a estrutura e a sintaxe dos modelos do ARM.

  • Se utilizar um ponto final público no seu modelo (como um ponto final público do Armazenamento de Blobs do Azure), não codize o espaço de nomes. Utilize a reference função para obter dinamicamente o espaço de nomes. Pode utilizar esta abordagem para implementar o modelo em diferentes ambientes de espaço de nomes públicos sem alterar manualmente o ponto final no modelo. Defina a versão da API para a mesma versão que está a utilizar para a conta de armazenamento no seu modelo.

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

    Se a conta de armazenamento estiver implementada no mesmo modelo que está a criar e o nome da conta de armazenamento não for partilhado com outro recurso no modelo, não terá de especificar o espaço de nomes do fornecedor ou quando apiVersion referencia o recurso. O exemplo seguinte mostra a sintaxe simplificada.

    "diagnosticsProfile": {
      "bootDiagnostics": {
        "enabled": "true",
        "storageUri": "[reference(variables('storageAccountName')).primaryEndpoints.blob]"
      }
    }
    

    Também pode referenciar uma conta de armazenamento existente que esteja num grupo de recursos diferente.

    "diagnosticsProfile": {
      "bootDiagnostics": {
        "enabled": "true",
        "storageUri": "[reference(resourceId(parameters('existingResourceGroup'), 'Microsoft.Storage/storageAccounts', parameters('existingStorageAccountName')), '2019-06-01').primaryEndpoints.blob]"
      }
    }
    
  • Atribua endereços IP públicos a uma máquina virtual apenas quando uma aplicação o exigir. Para ligar a uma máquina virtual para fins administrativos, utilize regras NAT de entrada, um gateway de rede virtual ou uma jumpbox.

    Para obter mais informações sobre como ligar a máquinas virtuais, consulte:

  • A domainNameLabel propriedade para endereços IP públicos tem de ser exclusiva. O domainNameLabel valor tem de ter entre 3 e 63 carateres de comprimento e seguir as regras especificadas por esta expressão regular: ^[a-z][a-z0-9-]{1,61}[a-z0-9]$. Uma vez que a uniqueString função gera uma cadeia com 13 carateres de comprimento, o dnsPrefixString parâmetro está limitado a 50 carateres.

    "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 adicionar uma palavra-passe a uma extensão de script personalizado, utilize a commandToExecute propriedade na protectedSettings propriedade .

    "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

    Para garantir que os segredos são encriptados quando são transmitidos como parâmetros para VMs e extensões, utilize a protectedSettings propriedade das extensões relevantes.

  • Especifique valores explícitos para propriedades com valores predefinidos que podem ser alterados ao longo do tempo. Por exemplo, se estiver a implementar um cluster do AKS, pode especificar ou omitir a kubernetesVersion propriedade. Se não o especificar, o cluster é predefinido para a versão secundária N-1 e o patch mais recente. Quando implementa o cluster com um modelo do ARM, este comportamento predefinido poderá não ser o esperado. Reimplementar o modelo pode resultar na atualização inesperada do cluster para uma nova versão do Kubernetes. Em vez disso, considere especificar um número de versão explícito e, em seguida, alterá-lo manualmente quando estiver pronto para atualizar o cluster.

Comentários

Além da comments propriedade, são suportados comentários com a // sintaxe. Para obter mais detalhes sobre comentários e metadados, veja Compreender a estrutura e a sintaxe dos modelos do ARM. Pode optar por guardar ficheiros JSON que contenham // comentários com a extensão de .jsonc ficheiro, para indicar que o ficheiro JSON contém comentários. O serviço ARM também aceitará comentários em qualquer ficheiro JSON, incluindo ficheiros de parâmetros.

Ferramentas arm do Visual Studio Code

Trabalhar com modelos do ARM é muito mais fácil com as Ferramentas do Azure Resource Manager (ARM) para Visual Studio Code. Esta extensão fornece suporte de idiomas, fragmentos de recursos e conclusão automática de recursos para o ajudar a criar e validar modelos de Resource Manager do Azure. Para saber mais e instalar a extensão, veja Ferramentas do Azure Resource Manager (ARM).

Utilizar o toolkit de teste

O toolkit de teste de modelos do ARM é um script que verifica se o modelo utiliza práticas recomendadas. Quando o modelo não está em conformidade com as práticas recomendadas, devolve uma lista de avisos com alterações sugeridas. O toolkit de teste pode ajudá-lo a aprender a implementar as melhores práticas no seu modelo.

Depois de concluir o modelo, execute o toolkit de teste para ver se existem formas de melhorar a implementação. Para obter mais informações, veja Utilizar o toolkit de teste de modelos do ARM.

Passos seguintes