Tutorial – Como utilizar o cloud-init para personalizar uma máquina virtual do Linux no Azure no primeiro arranque

Aplica-se a: ✔️ Conjuntos de dimensionamento flexíveis de VMs ✔️ do Linux

Num tutorial anterior, aprendeu a realizar SSH para uma máquina virtual (VM) e instalar manualmente o NGINX. Para criar VMs de forma rápida e consistente, normalmente pretende-se alguma forma de automatização. Uma abordagem comum para personalizar uma VM no primeiro arranque é utilizar o cloud-init. Neste tutorial, ficará a saber como:

  • Criar um ficheiro de configuração do cloud-init
  • Criar uma VM que utiliza um ficheiro cloud-init
  • Ver uma aplicação Node.js em execução depois de a VM ser criada
  • Utilizar o Key Vault para armazenar certificados
  • Automatizar implementações seguras do NGINX com o cloud-init

Se optar por instalar e utilizar a CLI localmente, este tutorial requer que execute uma versão da CLI do Azure que seja a 2.0.30 ou posterior. Executar az --version para localizar a versão. Se precisar de instalar ou atualizar, veja Install Azure CLI (Instalar o Azure CLI).

Descrição geral da inicialização de cloud

Cloud-init é uma abordagem amplamente utilizada para personalizar uma VM com Linux quando arranca pela primeira vez. Pode utilizar o cloud-init para instalar pacotes e escrever ficheiros ou para configurar utilizadores e segurança. Como o cloud-init é executado durante o processo de arranque inicial, não existem passos adicionais ou agentes necessários a aplicar à configuração.

O cloud-init também funciona em distribuições. Por exemplo, não utiliza apt-get install nem yum install para instalar um pacote. Em vez disso, pode definir uma lista dos pacotes a instalar. O cloud-init utiliza automaticamente a ferramenta de gestão de pacotes nativa para a distribuição que selecionar.

Estamos a trabalhar com os nossos parceiros para que o cloud-init seja incluído e fique operacional nas imagens que fornecem ao Azure. Para obter informações detalhadas sobre o suporte cloud-init para cada distribuição, veja Suporte cloud-init para VMs no Azure.

Criar ficheiro de configuração do cloud-init

Para ver o cloud-init em ação, crie uma VM que instala o NGINX e executa uma aplicação Node.js “Hello World” simples. A seguinte configuração do cloud-init instala os pacotes necessários, cria uma aplicação Node.js e, em seguida, inicializa e lança a aplicação.

Na linha de comandos do bash ou no Cloud Shell, crie um ficheiro com o nome cloud-init.txt e cole a seguinte configuração. Por exemplo, escreva sensible-editor cloud-init.txt para criar o ficheiro e ver uma lista de editores disponíveis. Certifique-se de que o ficheiro de inicialização da cloud é copiado corretamente, especialmente a primeira linha:

#cloud-config
package_upgrade: true
packages:
  - nginx
  - nodejs
  - npm
write_files:
  - owner: www-data:www-data
    path: /etc/nginx/sites-available/default
    defer: true
    content: |
      server {
        listen 80;
        location / {
          proxy_pass http://localhost:3000;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection keep-alive;
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
        }
      }
  - owner: azureuser:azureuser
    path: /home/azureuser/myapp/index.js
    defer: true
    content: |
      var express = require('express')
      var app = express()
      var os = require('os');
      app.get('/', function (req, res) {
        res.send('Hello World from host ' + os.hostname() + '!')
      })
      app.listen(3000, function () {
        console.log('Hello world app listening on port 3000!')
      })
runcmd:
  - service nginx restart
  - cd "/home/azureuser/myapp"
  - npm init
  - npm install express -y
  - nodejs index.js

Para obter mais informações sobre as opções de configuração do cloud-init, veja exemplos de configuração do cloud-init.

Criar a máquina virtual

Antes de poder criar uma VM, tem de criar um grupo de recursos com az group create. O exemplo seguinte cria um grupo de recursos com o nome myResourceGroupAutomate na localização eualeste:

az group create --name myResourceGroupAutomate --location eastus

Agora, crie uma VM com az vm create. Utilize o parâmetro --custom-data para passar o ficheiro de configuração de inicialização da cloud. Forneça o caminho completo para a configuração do cloud-init.txt, se tiver guardado o ficheiro fora do diretório de trabalho atual. O exemplo seguinte cria uma VM com o nome myVM:

az vm create \
    --resource-group myResourceGroupAutomate \
    --name myAutomatedVM \
    --image Ubuntu2204 \
    --admin-username azureuser \
    --generate-ssh-keys \
    --custom-data cloud-init.txt

Demora alguns minutos até a VM ser criada, os pacotes serem instalados e a aplicação ser iniciada. Existem tarefas em segundo plano que continuam em execução após a CLI do Azure o devolver à linha de comandos. Poderão ser necessários mais alguns minutos antes de poder aceder à aplicação. Quando a VM tiver sido criada, tome nota do publicIpAddress apresentado pela CLI do Azure. Este endereço é utilizado para aceder à aplicação Node.js num browser.

Para permitir que o tráfego da Web aceda à VM, abra a porta 80 a partir da Internet com az vm open-port:

az vm open-port --port 80 --resource-group myResourceGroupAutomate --name myAutomatedVM

Testar a aplicação Web

Agora, pode abrir um browser e introduzir http://< publicIpAddress> na barra de endereço. Forneça o seu próprio endereço IP público a partir do processo de criação da VM. A aplicação Node.js é apresentada conforme mostrada no exemplo seguinte:

Ver site NGINX em execução

Inserir certificados a partir do Key Vault

Esta secção opcional mostra como pode, em segurança, armazenar certificados no Azure Key Vault e inseri-los durante a implementação de VMs. Em vez de utilizar uma imagem personalizada que inclui os certificados integrados, este processo garante que os certificados mais atualizados são inseridos numa VM no primeiro arranque. Durante o processo, o certificado nunca sai da plataforma do Azure nem é exposto num script, histórico de linha de comandos ou modelo.

O Azure Key Vault salvaguarda as chaves criptográficas e os segredos, como os certificados ou as palavras-passe. O Key Vault ajuda a simplificar o processo de gestão de chaves e permite-lhe manter o controlo de chaves que acedem aos seus dados e os encriptam. Este cenário apresenta alguns conceitos do Key Vault para criar e utilizar um certificado, embora não seja uma descrição geral exaustiva de como utilizar o Key Vault.

Os passos seguintes mostram como pode:

  • Criar um Azure Key Vault
  • Gerar ou carregar um certificado para o Key Vault
  • Criar um segredo do certificado para inserir numa VM
  • Criar uma VM e inserir o certificado

Criar um Azure Key Vault

Em primeiro lugar, crie um Key Vault com az keyvault create e ative-o para utilização quando implementar uma VM. Cada Key Vault requer um nome exclusivo com todas as letras minúsculas. Substitua mykeyvault no exemplo seguinte pelo seu próprio nome exclusivo do Key Vault:

keyvault_name=mykeyvault
az keyvault create \
    --resource-group myResourceGroupAutomate \
    --name $keyvault_name \
    --enabled-for-deployment

Gerar um certificado e armazená-lo no Key Vault

Para efeitos de produção, deve importar um certificado válido assinado por um fornecedor fidedigno com az keyvault certificate import. Para este tutorial, o exemplo seguinte mostra como pode gerar um certificado autoassinado com az keyvault certificate create que utiliza a política de certificado predefinida:

az keyvault certificate create \
    --vault-name $keyvault_name \
    --name mycert \
    --policy "$(az keyvault certificate get-default-policy --output json)"

Preparar um certificado para utilização numa VM

Para utilizar o certificado durante o processo de criação da VM, obtenha o ID do certificado com az keyvault secret list-versions. A VM precisa do certificado num determinado formato para o inserir no arranque, por isso, converta o certificado com az vm secret format. O exemplo seguinte atribui o resultado destes comandos a variáveis para uma utilização mais fácil nos passos que se seguem:

secret=$(az keyvault secret list-versions \
          --vault-name $keyvault_name \
          --name mycert \
          --query "[?attributes.enabled].id" --output tsv)
vm_secret=$(az vm secret format --secret "$secret" --output json)

Criar uma configuração do cloud-init para proteger o NGINX

Quando criar uma VM, os certificados e as chaves são armazenados no diretório /var/lib/waagent/ protegido. Para automatizar a adição do certificado à VM e configurar o NGINX, pode utilizar uma configuração atualizada de cloud-init do exemplo anterior.

Crie um ficheiro com o nome cloud-init-secured.txt e cole a seguinte configuração. Se utilizar o Cloud Shell, crie aí o ficheiro de configuração cloud-init e não no computador local. Por exemplo, escreva sensible-editor cloud-init-secured.txt para criar o ficheiro e ver uma lista de editores disponíveis. Certifique-se de que o ficheiro de inicialização da cloud é copiado corretamente, especialmente a primeira linha:

#cloud-config
package_upgrade: true
packages:
  - nginx
  - nodejs
  - npm
write_files:
  - owner: www-data:www-data
    path: /etc/nginx/sites-available/default
    defer: true
    content: |
      server {
        listen 80;
        listen 443 ssl;
        ssl_certificate /etc/nginx/ssl/mycert.cert;
        ssl_certificate_key /etc/nginx/ssl/mycert.prv;
        location / {
          proxy_pass http://localhost:3000;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection keep-alive;
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
        }
      }
  - owner: azureuser:azureuser
    path: /home/azureuser/myapp/index.js
    defer: true
    content: |
      var express = require('express')
      var app = express()
      var os = require('os');
      app.get('/', function (req, res) {
        res.send('Hello World from host ' + os.hostname() + '!')
      })
      app.listen(3000, function () {
        console.log('Hello world app listening on port 3000!')
      })
runcmd:
  - secretsname=$(find /var/lib/waagent/ -name "*.prv" | cut -c -57)
  - mkdir /etc/nginx/ssl
  - cp $secretsname.crt /etc/nginx/ssl/mycert.cert
  - cp $secretsname.prv /etc/nginx/ssl/mycert.prv
  - service nginx restart
  - cd "/home/azureuser/myapp"
  - npm init
  - npm install express -y
  - nodejs index.js

Criar uma VM segura

Agora, crie uma VM com az vm create. Os dados do certificado são inseridos a partir do Key Vault com o parâmetro --secrets. Como no exemplo anterior, também transmite a configuração do cloud-init com o parâmetro --custom-data:

az vm create \
    --resource-group myResourceGroupAutomate \
    --name myVMWithCerts \
    --image Ubuntu2204 \
    --admin-username azureuser \
    --generate-ssh-keys \
    --custom-data cloud-init-secured.txt \
    --secrets "$vm_secret"

Demora alguns minutos até a VM ser criada, os pacotes serem instalados e a aplicação ser iniciada. Existem tarefas em segundo plano que continuam em execução após a CLI do Azure o devolver à linha de comandos. Poderão ser necessários mais alguns minutos antes de poder aceder à aplicação. Quando a VM tiver sido criada, tome nota do publicIpAddress apresentado pela CLI do Azure. Este endereço é utilizado para aceder à aplicação Node.js num browser.

Para permitir que o tráfego da Web seguro aceda à VM, abra a porta 443 a partir da Internet com az vm open-port:

az vm open-port \
    --resource-group myResourceGroupAutomate \
    --name myVMWithCerts \
    --port 443

Testar uma aplicação Web segura

Agora, pode abrir um browser e introduzir https://< publicIpAddress> na barra de endereço. Forneça o seu próprio endereço IP público conforme apresentado na saída do processo de criação da VM anterior. Aceite o aviso de segurança se utilizou um certificado autoassinado:

Aceitar o aviso de segurança do browser

O site NGINX protegido e a aplicação Node.js são apresentados como no exemplo seguinte:

Ver site NGINX seguro em execução

Passos seguintes

Neste tutorial, configurou as VMs no primeiro arranque com o cloud-init. Aprendeu a:

  • Criar um ficheiro de configuração do cloud-init
  • Criar uma VM que utiliza um ficheiro cloud-init
  • Ver uma aplicação Node.js em execução depois de a VM ser criada
  • Utilizar o Key Vault para armazenar certificados
  • Automatizar implementações seguras do NGINX com o cloud-init

Avance para o tutorial seguinte para aprender a criar imagens de VM personalizadas.