Modularizar modelos
A modularização de modelos é uma prática recomendada que divide modelos grandes e complexos em componentes menores e reutilizáveis. Essa abordagem melhora a capacidade de manutenção, promove a reutilização e torna os modelos mais fáceis de testar e entender.
Porquê modularizar modelos?
Benefícios da modularização:
- Reutilização: Crie um modelo de rede uma vez e use-o em vários projetos.
- Manutenabilidade: Atualize um módulo em vez de modificar vários modelos grandes.
- Colaboração em equipa: Diferentes equipes podem possuir diferentes módulos (rede, segurança, computação).
- Testes: Teste módulos individuais isoladamente antes de compô-los.
- Separação de preocupações: Cada modelo se concentra em um domínio de infraestrutura específico.
- Controle de versão: Rastreie alterações em componentes individuais de forma independente.
Exemplo do mundo real: Crie modelos separados para:
- Módulo de rede: Redes virtuais, sub-redes, NSGs, tabelas de rotas.
- Módulo de armazenamento: Contas de armazenamento, contêineres de blob, compartilhamentos de arquivos.
- Módulo de computação: Máquinas virtuais, conjuntos de disponibilidade, balanceadores de carga.
- Módulo de segurança: Cofre de chaves, identidades gerenciadas, atribuições RBAC.
Modelos ligados
Os modelos vinculados permitem que você faça referência a arquivos de modelo externos a partir de um modelo principal. Esta é a principal metodologia para criar arquiteturas modulares de modelo ARM.
Como funciona:
- Armazene modelos secundários em locais acessíveis (Armazenamento do Azure, GitHub, etc.).
- O modelo principal faz referência a modelos externos via URI.
- O Resource Manager baixa e executa modelos vinculados durante a implantação.
Sintaxe: Adicione um recurso de implantação ao seu modelo principal:
"resources": [
{
"apiVersion": "2022-09-01",
"name": "linkedTemplate",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://mystorageaccount.blob.core.windows.net/templates/networking.json",
"contentVersion": "1.0.0.0"
},
"parameters": {
"vnetName": {
"value": "[parameters('virtualNetworkName')]"
},
"location": {
"value": "[parameters('location')]"
}
}
}
}
]
Principais propriedades:
-
tipo:
Microsoft.Resources/deploymentsIndica uma implantação aninhada ou vinculada. - Modalidade: Modo de implantação (Incremental ou Concluído).
- templateLink: Aponta para o URI do modelo externo.
- Parâmetros: Valores passados para o modelo vinculado.
Exemplo completo com vários modelos vinculados:
"resources": [
{
"name": "networkingDeployment",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('templateBaseUrl'), '/networking.json')]"
},
"parameters": {
"vnetName": { "value": "[parameters('vnetName')]" }
}
}
},
{
"name": "storageDeployment",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
"dependsOn": [
"[resourceId('Microsoft.Resources/deployments', 'networkingDeployment')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('templateBaseUrl'), '/storage.json')]"
}
}
}
]
Modelos aninhados
Os modelos aninhados permitem incorporar um modelo completo diretamente dentro do modelo principal utilizando a propriedade template em vez de templateLink.
Quando usar modelos aninhados:
- Cenários simples: Componentes pequenos e independentes que não precisam de arquivos externos.
- Lógica privada: Lógica de modelo que você não deseja expor externamente.
- Geração dinâmica: Crie conteúdo de modelo programaticamente durante a implantação.
Desvantagem: Aninhar componentes grandes resulta num ficheiro principal de tamanho considerável, o que dificulta a sua manutenção e leitura.
"resources": [
{
"apiVersion": "2022-09-01",
"name": "nestedStorageTemplate",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-01-01",
"name": "[variables('storageName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"supportsHttpsTrafficOnly": true
}
}
]
}
}
}
]
Limitações importantes:
Observação
Escopo do modelo aninhado: Os modelos aninhados só podem usar parâmetros e variáveis do modelo principal. Não é possível definir novos parâmetros ou variáveis dentro do próprio modelo aninhado.
Modelos vinculados vs. aninhados:
| Característica | Modelos vinculados | Modelos aninhados |
|---|---|---|
| Localização | Arquivo externo (URI) | Inserido dentro do modelo principal |
| Reutilização | Alto - uso em todos os projetos | Baixo - vinculado ao modelo principal |
| Manutenibilidade | Fácil - arquivos separados | Mais difícil - incorporado no arquivo principal |
| Parâmetros | Pode definir parâmetros próprios | Usa apenas parâmetros de modelo principais |
| Variáveis | Pode definir variáveis próprias | Usa apenas variáveis de modelo principais |
| Tamanho | Sem impacto no modelo principal | Aumenta o tamanho do modelo principal |
| Melhor para | Arquiteturas modulares de produção | Componentes simples e únicos |
Recomendação: Use modelos vinculados para cenários de produção e modelos aninhados apenas para componentes simples e não reutilizáveis.
Modos de implementação
Ao implantar modelos, você deve escolher um modo de implantação que determine como o Gerenciador de Recursos lida com os recursos existentes no grupo de recursos de destino.
Três opções de implantação
Modo de validação
Finalidade: Modelo de teste sem fazer alterações.
O que faz:
- Compila o modelo e verifica a sintaxe JSON.
- Valida a lógica de implantação (sem dependências circulares).
- Garante que todos os tipos de recursos e versões de API sejam válidos.
- Não implanta nenhum recurso.
Quando usar: Antes das implantações de produção para detetar erros antecipadamente.
Exemplo de comando:
az deployment group validate \
--resource-group myResourceGroup \
--template-file main.json \
--parameters @parameters.json
Modo incremental (padrão)
Finalidade: Adicione ou atualize recursos sem afetar os existentes.
O que faz:
- Implanta recursos definidos no modelo.
- Deixa os recursos inalterados não definidos no modelo.
- Atualiza os recursos se as configurações forem alteradas.
Exemplo de cenário:
- O modelo define VM1, VM2, Storage1.
- O grupo de recursos tem VM1, VM3, Storage1.
- Após a implantação: VM1 (atualizado), VM2 (adicionado), VM3 (inalterado), Storage1 (atualizado).
Quando usar:
- Adicionar novos recursos aos ambientes existentes.
- Atualizar recursos específicos sem risco para outros.
- Ambientes de desenvolvimento e teste.
Modo completo
Finalidade: Garantir que o grupo de recursos corresponda exatamente ao template (idempotência).
O que faz:
- Implanta recursos definidos no modelo.
- Exclui recursos não definidos no modelo.
- O grupo de recursos contém APENAS o que está no template.
Exemplo de cenário:
- O modelo define VM1, VM2, Storage1.
- O grupo de recursos tem VM1, VM3, Storage1, VM4.
- Após a implantação: VM1 (atualizado), VM2 (adicionado), Storage1 (atualizado), VM3 (excluído), VM4 (excluído).
Quando usar:
- Ambientes de produção que exigem um rigoroso controlo estatal.
- Atingir idempotência (o mesmo resultado em todas as implementações).
- Remoção de recursos indesejados ou manuais.
Advertência
O modo completo pode excluir recursos. Teste cuidadosamente antes de usar na produção!
Definindo o modo de implantação
CLI do Azure:
# Incremental (default)
az deployment group create \
--resource-group myResourceGroup \
--template-file main.json \
--mode Incremental
# Complete
az deployment group create \
--resource-group myResourceGroup \
--template-file main.json \
--mode Complete
PowerShell::
# Incremental
New-AzResourceGroupDeployment `
-ResourceGroupName myResourceGroup `
-TemplateFile main.json `
-Mode Incremental
# Complete
New-AzResourceGroupDeployment `
-ResourceGroupName myResourceGroup `
-TemplateFile main.json `
-Mode Complete
Melhores práticas
Observação
Um grupo de recursos por implantação: Use grupos de recursos dedicados para cada aplicativo lógico ou ambiente para simplificar o gerenciamento e evitar exclusões acidentais.
Observação
Limitação de modelos vinculados/aninhados: Você só pode usar o modo incremental para modelos vinculados e aninhados. O modo completo não é suportado para implementações secundárias.
Recommendations:
- Desenvolvimento: Use o modo incremental para flexibilidade e iteração mais rápida.
- Produção: Utilize o modo Completo com pipelines de CI/CD para assegurar um estado consistente.
- Antes do modo Concluído: Valide sempre primeiro e teste em ambientes que não sejam de produção.
- Bloqueios de recursos: Aplique bloqueios a recursos críticos para evitar a exclusão acidental.
Modelos e parâmetros externos
Os modelos externos fornecem a base para arquiteturas de modelo ARM verdadeiramente modulares. Você armazena modelos filho em locais acessíveis e faz referência a eles via URI.
Requisitos de acessibilidade do modelo
O Resource Manager deve ser capaz de acessar modelos vinculados durante a implantação:
O que funciona:
- Armazenamento de Blobs do Azure: Público ou privado com tokens SAS.
- GitHub: Repositórios públicos ou privados com tokens de acesso.
- Endereços HTTPS: Qualquer URL de HTTPS que seja publicamente acessível.
- Instâncias de contêiner do Azure: Hospedagem de arquivos de modelo em contêineres.
O que não funciona:
- Arquivos locais: Ficheiros no seu computador ou rede local.
- File:// protocolo: Caminhos do sistema de arquivos local.
- HTTP (não seguro): Apenas HTTPS é suportado.
Usando templateLink e parametersLink
templateLink: Faz referência a um arquivo de modelo externo.
parâmetrosLink: Faz referência a um arquivo de parâmetro externo (alternativa aos parâmetros embutidos).
Importante
Não é possível usar parâmetros embutidos e parametersLink simultaneamente. Escolha uma abordagem.
Exemplo completo com templateLink:
"resources": [
{
"name": "linkedStorageDeployment",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://mystorageaccount.blob.core.windows.net/templates/storage.json?sv=2021-06-08&sr=b&sig=ABC123...&se=2025-12-31T23:59:59Z&sp=r",
"contentVersion": "1.0.0.0"
},
"parameters": {
"storageAccountName": {
"value": "[variables('storageAccountName')]"
},
"location": {
"value": "[parameters('location')]"
},
"sku": {
"value": "Standard_GRS"
}
}
}
}
]
Componentes-chave:
- URI: URL HTTPS completo para o modelo vinculado (inclui token SAS se estiver usando armazenamento privado).
- contentVersion: Versão do modelo vinculado (deve corresponder ao que está no arquivo de modelo vinculado).
- Parâmetros: Valores passados para o modelo vinculado (podem fazer referência aos parâmetros/variáveis principais do modelo).
Usando arquivos de parâmetros externos
Alternativa aos parâmetros em linha:
{
"name": "linkedDeployment",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2022-09-01",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://mystorageaccount.blob.core.windows.net/templates/main.json"
},
"parametersLink": {
"uri": "https://mystorageaccount.blob.core.windows.net/parameters/prod.json"
}
}
}
Benefícios:
- Separe arquivos de parâmetros por ambiente (dev.json, staging.json, prod.json).
- Parâmetros sensíveis armazenados de forma segura em arquivos de parâmetros.
- Mais fácil de gerenciar implantações em vários ambientes.
Protegendo modelos externos
Os modelos externos não precisam ser públicos. Você pode armazená-los em contas de armazenamento privado e usar tokens SAS (Assinatura de Acesso Compartilhado) para acesso seguro.
Etapas para proteger modelos
- Armazenar modelos no Armazenamento de Blobs privado do Azure:
# Create storage account and container
az storage account create \
--name mytemplatestorage \
--resource-group myResourceGroup \
--location eastus \
--sku Standard_LRS
az storage container create \
--name templates \
--account-name mytemplatestorage \
--public-access off
- Carregue arquivos de modelo:
az storage blob upload \
--account-name mytemplatestorage \
--container-name templates \
--name networking.json \
--file ./templates/networking.json
- Gerar um token SAS com uma data de expiração:
# Create SAS token valid for 30 days
az storage blob generate-sas \
--account-name mytemplatestorage \
--container-name templates \
--name networking.json \
--permissions r \
--expiry 2025-12-31T23:59:59Z \
--https-only \
--output tsv
- Use o token SAS na URI do templateLink:
"templateLink": {
"uri": "https://mytemplatestorage.blob.core.windows.net/templates/networking.json?sv=2021-06-08&sr=b&sig=ABC123...&se=2025-12-31T23:59:59Z&sp=r"
}
Considerações de segurança
Registro de token SAS:
- Mesmo que o token seja passado com segurança, o URI (incluindo o token SAS) é registrado em operações de implantação.
- Os registos de implementação são visíveis para qualquer pessoa com acesso de leitura ao grupo de recursos.
Práticas recomendadas para segurança:
- Definir datas de validade: Crie tokens SAS por tempo limitado (30-90 dias).
-
Use permissões de leitura apenas: Os tokens SAS devem conceder apenas permissão de leitura (
r). - Rode tokens regularmente: Gere novos tokens e atualize modelos periodicamente.
- Use o Azure Key Vault: Armazene tokens SAS no Cofre de Chaves e faça referência a eles em modelos.
- Identidades gerenciadas: Considere o uso de identidades gerenciadas para acesso ao modelo em vez de tokens SAS.
- Pontos finais privados: Utilize pontos finais privados do Azure Storage para uma segurança de rede adicional.
Exemplo com referência ao Key Vault:
"templateLink": {
"uri": "[concat('https://mytemplatestorage.blob.core.windows.net/templates/networking.json', reference(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), 'storageAccountSasToken')).secretValue)]"
}
Essa abordagem mantém os tokens SAS fora do código do modelo e dos registos de implementação.