image

Bootcamps ilimitados + curso de inglês para sempre

80
%OFF
Article image
EVERTON LUCAS
EVERTON LUCAS14/06/2025 10:57
Compartilhe

Simplificando a Implantação de Projetos no Azure com JSON e ARM Templates

    A administração de ambientes Azure envolve frequentemente a criação e configuração de recursos. Para otimizar e padronizar essas operações, os Azure Resource Manager (ARM) templates, escritos em JSON, são ferramentas indispensáveis. Eles permitem que você defina a infraestrutura como código, garantindo consistência, repetibilidade e minimizando erros manuais.

    Neste artigo, exploraremos um JSON modelo que simplifica a implantação de um novo projeto no Azure, criando um Grupo de Recursos, uma Rede Virtual (VNet) e uma Máquina Virtual (VM) Linux básica. O objetivo é fornecer um template flexível que possa ser facilmente adaptado por outros administradores, alterando apenas alguns parâmetros-chave.



    JSON 1: Implantação de um Novo Projeto no Azure (Grupo de Recursos, VNet e VM)

    Este template é projetado para criar o ambiente básico para um novo projeto no Azure. Ele engloba a criação de um grupo de recursos para organizar seus recursos, uma rede virtual para isolamento de rede e uma máquina virtual Linux para hospedar suas aplicações.

    Objetivo: Automatizar a criação de um ambiente de projeto inicial no Azure, incluindo:

    • Um novo Grupo de Recursos.
    • Uma Rede Virtual (VNet) com uma sub-rede.
    • Uma Máquina Virtual (VM) Linux com IP público e regras de NSG para SSH.

    Serviços do Azure Envolvidos: Azure Resource Manager, Azure Virtual Networks, Azure Virtual Machines, Azure Network Security Groups.

    O JSON Modelo:

    JSON

    {

       "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",

       "contentVersion": "1.0.0.0",

       "parameters": {

           "resourceGroupName": {

               "type": "string",

               "metadata": {

                   "description": "Nome do novo Grupo de Recursos para o projeto."

               }

           },

           "location": {

               "type": "string",

               "defaultValue": "[resourceGroup().location]",

               "metadata": {

                   "description": "Localização (região do Azure) para os recursos."

               }

           },

           "vnetName": {

               "type": "string",

               "defaultValue": "[concat('vnet-', parameters('resourceGroupName'))]",

               "metadata": {

                   "description": "Nome da Rede Virtual."

               }

           },

           "subnetName": {

               "type": "string",

               "defaultValue": "default",

               "metadata": {

                   "description": "Nome da Sub-rede dentro da Rede Virtual."

               }

           },

           "vnetAddressPrefix": {

               "type": "string",

               "defaultValue": "10.0.0.0/16",

               "metadata": {

                   "description": "Prefixo de endereço para a VNet."

               }

           },

           "subnetAddressPrefix": {

               "type": "string",

               "defaultValue": "10.0.0.0/24",

               "metadata": {

                   "description": "Prefixo de endereço para a Sub-rede."

               }

           },

           "vmName": {

               "type": "string",

               "defaultValue": "[concat('vm-', parameters('resourceGroupName'))]",

               "metadata": {

                   "description": "Nome da Máquina Virtual."

               }

           },

           "vmSize": {

               "type": "string",

               "defaultValue": "Standard_DS1_v2",

               "metadata": {

                   "description": "Tamanho da Máquina Virtual (ex: Standard_DS1_v2, Standard_B2s)."

               }

           },

           "adminUsername": {

               "type": "string",

               "metadata": {

                   "description": "Nome de usuário administrador para a VM Linux."

               }

           },

           "adminPassword": {

               "type": "securestring",

               "metadata": {

                   "description": "Senha administrador para a VM Linux. Use senhas fortes!"

               }

           },

           "ubuntuOSVersion": {

               "type": "string",

               "defaultValue": "latest",

               "allowedValues": [

                   "18.04-LTS",

                   "20.04-LTS",

                   "22.04-LTS",

                   "latest"

               ],

               "metadata": {

                   "description": "Versão do Ubuntu Server para a VM."

               }

           },

           "sshPortNumber": {

               "type": "int",

               "defaultValue": 22,

               "metadata": {

                   "description": "Número da porta para SSH. Mude se não for 22."

               }

           }

       },

       "variables": {

           "publicIpAddressName": "[concat(parameters('vmName'), '-ip')]",

           "networkSecurityGroupName": "[concat(parameters('vmName'), '-nsg')]",

           "networkInterfaceName": "[concat(parameters('vmName'), '-nic')]"

       },

       "resources": [

           {

               "type": "Microsoft.Resources/resourceGroups",

               "apiVersion": "2021-04-01",

               "name": "[parameters('resourceGroupName')]",

               "location": "[parameters('location')]",

               "properties": {}

           },

           {

               "type": "Microsoft.Network/virtualNetworks",

               "apiVersion": "2023-09-01",

               "name": "[parameters('vnetName')]",

               "location": "[parameters('location')]",

               "dependsOn": [

                   "[resourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroupName'))]"

               ],

               "properties": {

                   "addressSpace": {

                       "addressPrefixes": [

                           "[parameters('vnetAddressPrefix')]"

                       ]

                   },

                   "subnets": [

                       {

                           "name": "[parameters('subnetName')]",

                           "properties": {

                               "addressPrefix": "[parameters('subnetAddressPrefix')]"

                           }

                       }

                   ]

               }

           },

           {

               "type": "Microsoft.Network/networkSecurityGroups",

               "apiVersion": "2023-09-01",

               "name": "[variables('networkSecurityGroupName')]",

               "location": "[parameters('location')]",

               "dependsOn": [

                   "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"

               ],

               "properties": {

                   "securityRules": [

                       {

                           "name": "AllowSSH",

                           "properties": {

                               "description": "Allow SSH access",

                               "protocol": "Tcp",

                               "sourcePortRange": "*",

                               "destinationPortRange": "[parameters('sshPortNumber')]",

                               "sourceAddressPrefix": "Internet",

                               "destinationAddressPrefix": "*",

                               "access": "Allow",

                               "priority": 100,

                               "direction": "Inbound"

                           }

                       }

                   ]

               }

           },

           {

               "type": "Microsoft.Network/publicIPAddresses",

               "apiVersion": "2023-09-01",

               "name": "[variables('publicIpAddressName')]",

               "location": "[parameters('location')]",

               "dependsOn": [

                   "[resourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroupName'))]"

               ],

               "properties": {

                   "publicIPAllocationMethod": "Dynamic",

                   "dnsSettings": {

                       "domainNameLabel": "[concat(parameters('vmName'), '-', uniqueString(resourceGroup().id))]"

                   }

               }

           },

           {

               "type": "Microsoft.Network/networkInterfaces",

               "apiVersion": "2023-09-01",

               "name": "[variables('networkInterfaceName')]",

               "location": "[parameters('location')]",

               "dependsOn": [

                   "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))]",

                   "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]",

                   "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"

               ],

               "properties": {

                   "ipConfigurations": [

                       {

                           "name": "ipconfig1",

                           "properties": {

                               "privateIPAllocationMethod": "Dynamic",

                               "publicIPAddress": {

                                   "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))]"

                               },

                               "subnet": {

                                   "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName'))]"

                               }

                           }

                       }

                   ],

                   "networkSecurityGroup": {

                       "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"

                   }

               }

           },

           {

               "type": "Microsoft.Compute/virtualMachines",

               "apiVersion": "2023-09-01",

               "name": "[parameters('vmName')]",

               "location": "[parameters('location')]",

               "dependsOn": [

                   "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]"

               ],

               "properties": {

                   "hardwareProfile": {

                       "vmSize": "[parameters('vmSize')]"

                   },

                   "osProfile": {

                       "computerName": "[parameters('vmName')]",

                       "adminUsername": "[parameters('adminUsername')]",

                       "adminPassword": "[parameters('adminPassword')]"

                   },

                   "storageProfile": {

                       "imageReference": {

                           "publisher": "Canonical",

                           "offer": "0001-com-ubuntu-server-jammy",

                           "sku": "[parameters('ubuntuOSVersion') == '18.04-LTS' ? '18_04-lts-gen2' : parameters('ubuntuOSVersion') == '20.04-LTS' ? '20_04-lts-gen2' : '22_04-lts-gen2']",

                           "version": "latest"

                       },

                       "osDisk": {

                           "createOption": "FromImage",

                           "managedDisk": {

                               "storageAccountType": "Standard_LRS"

                           }

                       }

                   },

                   "networkProfile": {

                       "networkInterfaces": [

                           {

                               "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]"

                           }

                       ]

                   }

               }

           }

       ],

       "outputs": {

           "resourceGroupNameOutput": {

               "type": "string",

               "value": "[parameters('resourceGroupName')]",

               "metadata": {

                   "description": "Nome do Grupo de Recursos criado."

               }

           },

           "publicIpAddress": {

               "type": "string",

               "value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))).ipAddress]",

               "metadata": {

                   "description": "Endereço IP público da VM."

               }

           },

           "sshCommand": {

               "type": "string",

               "value": "[concat('ssh ', parameters('adminUsername'), '@', reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))).ipAddress)]",

               "metadata": {

                   "description": "Comando SSH para conectar à VM."

               }

           }

       }

    }

    Explicação Detalhada do JSON:

    • $schema e contentVersion: Define o tipo de documento e a versão do template ARM.
    • parameters: Seção crucial para a flexibilidade. Aqui você define as entradas que os administradores podem personalizar.
    • resourceGroupName, location, vnetName, vmName, adminUsername, adminPassword, vmSize: Parâmetros essenciais que garantem a unicidade e configurabilidade do projeto.
    • defaultValue: Muitos parâmetros têm valores padrão, facilitando o uso rápido sem necessidade de especificar todos eles.
    • allowedValues: Restringe as opções para alguns parâmetros (ex: ubuntuOSVersion), evitando erros de digitação.
    • securestring: Para senhas, garante que o valor não seja logado abertamente.
    • variables: Define valores que são computados durante a implantação, geralmente para construir nomes de recursos derivados dos parâmetros. Isso mantém os nomes consistentes.
    • resources: A parte principal onde cada recurso do Azure é definido. Cada recurso tem:
    • type: O tipo de recurso (ex: Microsoft.Network/virtualNetworks).
    • apiVersion: A versão da API do Azure Resource Provider para o recurso.
    • name: O nome do recurso.
    • location: A região do Azure onde o recurso será implantado.
    • dependsOn: Garante a ordem correta de implantação. Por exemplo, a VM depende da NIC, que depende da Public IP e da NSG, que dependem da VNet.
    • properties: As configurações específicas do recurso (endereços IP, tamanho da VM, nome de usuário, etc.).
    • outputs: Retorna informações úteis após a implantação, como o nome do Grupo de Recursos, o IP público da VM e até mesmo um comando SSH formatado para acesso rápido.

    Demonstração com Azure CLI:

    Para usar este template, salve-o em um arquivo chamado deploy_project.json.

    1. Prepare o arquivo de parâmetros (opcional, mas recomendado para reutilização): Crie um arquivo chamado parameters.json para definir os valores dos parâmetros. Isso é ideal para que outros administradores apenas alterem este arquivo.

    JSON

    {

       "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",

       "contentVersion": "1.0.0.0",

       "parameters": {

           "resourceGroupName": {

               "value": "meuNovoProjetoRG" // Substitua pelo nome do seu Grupo de Recursos

           },

           "location": {

               "value": "eastus" // Substitua pela região desejada

           },

           "vmName": {

               "value": "meuServidorWeb" // Substitua pelo nome da sua VM

           },

           "vmSize": {

               "value": "Standard_B2s" // Opcional: mude o tamanho da VM

           },

           "adminUsername": {

               "value": "azureuser" // Seu nome de usuário admin

           },

           "adminPassword": {

               "value": "SuaSenhaMuitoSegura123!" // Sua senha forte

           },

           "sshPortNumber": {

               "value": 22 // Opcional: Mude a porta SSH se necessário

           }

       }

    }

    Importante: Nunca armazene senhas em texto puro em arquivos de controle de versão. Para ambientes de produção, use o Azure Key Vault para armazenar segredos e referencie-os nos templates.

    1. Execute a implantação via Azure CLI:

    Abra seu terminal ou Azure Cloud Shell e execute o seguinte comando:

    Bash

    az deployment group create \

     --name "ProjetoNovoDeploy" \

     --template-file deploy_project.json \

     --parameters @parameters.json

    • --name "ProjetoNovoDeploy": Um nome para sua implantação.
    • --template-file deploy_project.json: O caminho para o arquivo JSON do seu template.
    • --parameters @parameters.json: O caminho para o arquivo JSON com os valores dos parâmetros. O @ indica que é um arquivo.

    Alternativamente, você pode passar os parâmetros diretamente na linha de comando, sem um arquivo de parâmetros:

    Bash

    az deployment group create \

     --name "ProjetoNovoDeploy" \

     --template-file deploy_project.json \

     --parameters resourceGroupName=meuNovoProjetoRG location=eastus vmName=meuServidorWeb adminUsername=azureuser adminPassword="SuaSenhaMuitoSegura123!"

    Cuidado: Ao passar senhas diretamente na linha de comando, elas podem aparecer no histórico do seu shell. O uso de um arquivo de parâmetros ou Key Vault é mais seguro.

    Particularidades e Dicas Importantes:

    • Reutilização: Este template é um ponto de partida excelente. Você pode estendê-lo para incluir outros recursos como contas de armazenamento, bancos de dados, App Services, etc.
    • Parâmetros: Utilize os parâmetros para tornar seu template dinâmico e reutilizável. Evite "hard-coding" valores dentro da seção resources.
    • dependsOn: Essencial para garantir que os recursos sejam criados na ordem correta. O Azure não tentará criar uma NIC antes que a VNet exista, por exemplo.
    • Versões da API (apiVersion): Sempre use as versões mais recentes das APIs para os tipos de recurso que você está implantando. Consulte a documentação do Azure para as versões mais atuais.
    • Saídas (outputs): Use as saídas para recuperar informações importantes sobre os recursos implantados, como IPs públicos ou URLs, que podem ser úteis para scripts subsequentes ou para o usuário final.
    • Validação: Antes de implantar, você pode validar o template usando az deployment group validate --resource-group <nome-do-grupo> --template-file deploy_project.json --parameters @parameters.json. Isso verifica a sintaxe e a lógica sem realmente criar recursos.
    • What-if: Use az deployment group what-if --resource-group <nome-do-grupo> --template-file deploy_project.json --parameters @parameters.json para ver as mudanças que a implantação faria no seu ambiente sem aplicá-las.



    Integrando o Azure Key Vault para Segurança de Credenciais

    Conforme mencionado, armazenar senhas diretamente nos arquivos de parâmetros não é uma prática segura. O Azure Key Vault é o serviço ideal para gerenciar e proteger chaves criptográficas, certificados e, crucialmente, segredos (como senhas).

    Para utilizar senhas armazenadas no Key Vault em seu ARM template, você precisará de algumas etapas:

    1. Criar e configurar um Azure Key Vault: O Key Vault deve existir antes da implantação do template. Você pode criá-lo via portal, CLI ou até mesmo outro ARM template. Certifique-se de que a identidade que realiza a implantação (usuário, Service Principal ou Managed Identity) tenha permissões de Get para os segredos no Key Vault.

    Exemplo de criação de Key Vault via CLI:

    Bash

    # Crie um grupo de recursos para o Key Vault (se ainda não tiver um)

    az group create --name "myKeyVaultRG" --location "eastus"

    # Crie o Key Vault

    az keyvault create \

     --name "mySecureKeyVault123" \

     --resource-group "myKeyVaultRG" \

     --location "eastus" \

     --sku "Standard"

    # Adicione um segredo (a senha da VM)

    az keyvault secret set \

     --vault-name "mySecureKeyVault123" \

     --name "vmAdminPassword" \

     --value "SuaSenhaUltraSecretaParaVM!"

    Importante: Conceda permissões de acesso ao Key Vault para a entidade que fará a implantação. Por exemplo, se for você com sua conta de usuário:

    Bash

    az keyvault set-policy \

     --name "mySecureKeyVault123" \

     --resource-group "myKeyVaultRG" \

     --object-id $(az ad signed-in-user show --query id -o tsv) \

     --secret-permissions get list

    (Substitua $(az ad signed-in-user show --query id -o tsv) pelo Object ID da Service Principal ou Managed Identity, se aplicável).

    1. Modificar o parâmetro da senha no ARM Template: No seu arquivo deploy_project.json, você manterá o parâmetro adminPassword como securestring. Não há alteração neste arquivo.
    2. Modificar o arquivo de parâmetros para referenciar o Key Vault: Esta é a mudança chave. Em vez de fornecer a senha diretamente, você referencia o segredo no Key Vault. Crie ou modifique seu parameters.json da seguinte forma:

    JSON

    {

       "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",

       "contentVersion": "1.0.0.0",

       "parameters": {

           "resourceGroupName": {

               "value": "meuNovoProjetoRG"

           },

           "location": {

               "value": "eastus"

           },

           "vmName": {

               "value": "meuServidorWeb"

           },

           "vmSize": {

               "value": "Standard_B2s"

           },

           "adminUsername": {

               "value": "azureuser"

           },

           "adminPassword": {

               "reference": {

                   "keyVault": {

                       "id": "/subscriptions/<SUA_SUBSCRIPTION_ID>/resourceGroups/myKeyVaultRG/providers/Microsoft.KeyVault/vaults/mySecureKeyVault123"

                   },

                   "secretName": "vmAdminPassword"

                   // "secretVersion": "OptionalVersion" // Opcional: use uma versão específica do segredo

               }

           },

           "sshPortNumber": {

               "value": 22

           }

       }

    }

    Lembre-se de substituir <SUA_SUBSCRIPTION_ID> pelo ID da sua assinatura do Azure. Você pode obter seu ID de assinatura com az account show --query id -o tsv.

    Como Funciona:

    Quando você executa a implantação do ARM template com este arquivo de parâmetros, o Azure Resource Manager faz uma chamada segura ao Key Vault para recuperar o segredo (vmAdminPassword) antes de provisionar a VM. Dessa forma, a senha nunca é exposta em texto simples no template, nos arquivos de parâmetros ou nos logs de implantação.

    Demonstração de Implantação com Key Vault:

    A execução do comando no Azure CLI permanece a mesma:

    Bash

    az deployment group create \

     --name "ProjetoNovoDeployComKV" \

     --template-file deploy_project.json \

     --parameters @parameters.json

    Com esta abordagem, você eleva significativamente a segurança de suas implantações no Azure, gerenciando credenciais de forma centralizada e segura com o Key Vault.



    Este template oferece uma base sólida para a automação de novas implantações de projetos no Azure. Ao dominá-lo, os administradores podem garantir que os ambientes sejam configurados de forma padronizada e eficiente, liberando tempo para tarefas mais estratégicas.

    Compartilhe
    Recomendados para você
    Deal Group - AI Centric .NET
    Randstad - Análise de Dados
    BairesDev - Machine Learning Training
    Comentários (1)
    DIO Community
    DIO Community - 16/06/2025 14:06

    Everton, esse artigo está simplesmente sensacional! Você entregou um verdadeiro guia prático, didático e extremamente aplicável sobre como utilizar ARM Templates no Azure com JSON, mostrando não só o passo a passo, mas também as boas práticas que garantem segurança, eficiência e escalabilidade no deployment.

    O cuidado em abordar desde conceitos básicos até tópicos mais avançados, como a integração com o Azure Key Vault, realmente agrega muito valor e, na prática, eleva o nível de qualquer profissional que esteja gerenciando infraestrutura no Azure.

    Seu conteúdo conecta diretamente quem está começando com quem já atua em ambientes mais robustos. Você já pensou em complementar essa abordagem com Bicep, a linguagem declarativa que a própria Microsoft lançou como evolução dos ARM Templates?