Criar uma máquina virtual Express.js usando a CLI do Azure

Neste tutorial, crie uma VM (máquina virtual) Linux para um aplicativo Express.js. A VM é configurada com um arquivo de configuração cloud-init e inclui o NGINX e um repositório GitHub de um aplicativo Express.js. Conecte-se à VM com o SSH, altere o aplicativo Web para incluir o registro em log do rastreamento e exibir o aplicativo de servidor Express.js público em um navegador da Web.

Este tutorial inclui as seguintes tarefas:

  • Entrar no Azure com a CLI do Azure
  • Criar um recurso da VM Linux do Azure com a CLI do Azure
    • Abrir a porta pública 80
    • Instalar o aplicativo Web de demonstração Express.js por meio de um repositório GitHub
    • Instalar as dependências do aplicativo Web
    • Iniciar o aplicativo Web
  • Criar um recurso de Monitoramento do Azure com a CLI do Azure
    • Conectar-se à VM com o SSH
    • Instalar a biblioteca de clientes do SDK do Azure com npm
    • Adicionar o código da biblioteca de clientes do Application Insights para criar o rastreamento personalizado
  • Exibir o aplicativo Web no navegador
    • Solicitar que a rota /trace gere o rastreamento personalizado no log do Application Insights
    • Exibir a contagem de rastreamentos coletados no log com a CLI do Azure
    • Exibir a lista de rastreamentos com o portal do Azure
  • Remover os recursos com a CLI do Azure

Pré-requisitos

  • Uma conta de usuário e uma assinatura do Azure: crie uma assinatura gratuita.
  • SSH para se conectar à VM: use o Azure Cloud Shell ou um terminal moderno, como o bash shell, que inclui SSH.

1. Crie um recurso do Application Insights para páginas da Web

Crie um grupo de recursos do Azure para todos os seus recursos do Azure e um recurso do Monitor para coletar os arquivos de log do aplicativo Web para a nuvem do Azure. A criação de um grupo de recursos permite que você encontre facilmente os recursos e exclua-os quando terminar. O Azure Monitor é o nome do serviço do Azure, enquanto Application Insights é o nome da biblioteca de clientes usada pelo tutorial.

  1. Opcional, se você tiver mais de uma assinatura, use az account set para definir a assinatura padrão antes de concluir os comandos restantes.

    az account set \
        --subscription "ACCOUNT NAME OR ID" 
    
  2. Crie um grupo de recursos do Azure com o comando az group create. Use o nome rg-demo-vm-eastus:

    az group create \
        --location eastus \
        --name rg-demo-vm-eastus 
    

Criar um recurso do Azure Monitor com a CLI do Azure

  1. Instale a extensão do Application Insights na CLI do Azure.

    az extension add -n application-insights
    
  2. Use o seguinte comando para criar um recurso de monitoramento, com az monitor app-insights component create:

    az monitor app-insights component create \
      --app demoWebAppMonitor \
      --location eastus \
      --resource-group rg-demo-vm-eastus \
      --query instrumentationKey --output table
    
  3. Copie o Resultado da saída, você precisará desse valor como seu instrumentationKey mais tarde.

  4. Deixe o terminal aberto, você o usará na próxima etapa.

2. Crie uma máquina virtual Linux usando a CLI do Azure

Usa um arquivo de configuração cloud-init para criar o servidor proxy reverso NGINX e o servidor Express.js. O NGINX é usado para encaminhar a porta Express.js (3000) para a porta pública (80).

  1. Crie um arquivo local chamado cloud-init-github.txt e salve o conteúdo a seguir no arquivo ou salve o arquivo do repositório no computador local. O arquivo formatado cloud-init deve estar na mesma pasta que o caminho de terminal dos seus comandos da CLI do Azure.

    #cloud-config
    package_upgrade: true
    packages:
      - nginx
    write_files:
      - owner: www-data:www-data
        path: /etc/nginx/sites-available/default
        content: |
          server {
            listen 80 default_server;
            server_name _;
            location / {
              # First, try if the file exists locally, otherwise request it from the app
              try_files $uri @app;
            }
            location @app {
              proxy_pass http://localhost:3000;
              proxy_http_version 1.1;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection 'upgrade';
              proxy_set_header X-Forwarded-For $remote_addr;
              proxy_set_header Host $host;
              proxy_cache_bypass $http_upgrade;
            }
          }
    runcmd:
      # install Node.js
      - 'curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -'
      - 'sudo apt-get install -y nodejs'
      # clone GitHub Repo into myapp directory
      - 'cd /home/azureuser'
      - git clone "https://github.com/Azure-Samples/js-e2e-vm" myapp
      # Start app
      - 'cd myapp && npm install && npm start'
      # restart NGINX
      - systemctl restart nginx
    
  2. Examine a seção runcmd do arquivo para entender o que ele faz.

    O runcmd tem várias tarefas:

    • Baixar e instalar o Node.js
    • Clonar o repositório de Express.js de exemplo de GitHub para o diretório myapp
    • Instalar as dependências do aplicativo
    • Iniciar o aplicativo Express.js com o PM2

Criar um recurso de máquina virtual

  1. Insira o comando da CLI do Azure az vm create em um terminal para criar um recurso do Azure de uma máquina virtual Linux. O comando cria a VM no arquivo cloud-init e gera as chaves SSH para você. O comando em execução exibe o local em que as chaves são armazenadas.

    az vm create \
      --resource-group rg-demo-vm-eastus \
      --name demo-vm \
      --location eastus \
      --public-ip-sku Standard \
      --image UbuntuLTS \
      --admin-username azureuser \
      --generate-ssh-keys \
      --custom-data cloud-init-github.txt
    
  2. Aguarde, o processo pode levar alguns minutos.

  3. Mantenha o valor publicIpAddress da resposta, ele é necessário para exibir o aplicativo Web em um navegador e conectar-se à VM. Se você perder esse IP, use o comando da CLI do Azure az vm list-ip-addresses para obtê-lo novamente.

  4. O processo criou chaves SSH e as colocou em um local indicado na resposta.

  5. Vá para esse local e crie o arquivo authorized_keys:

    cd <SSH-KEY-LOCATION> && cat id_rsa >> authorized_keys
    

Abrir a porta para a máquina virtual

Quando criada pela primeira vez, a máquina virtual não tem portas abertas. Abra a porta 80 com o seguinte comando da CLI do Azure az vm open-port para que o aplicativo Web esteja publicamente disponível:

az vm open-port \
  --port 80 \
  --resource-group rg-demo-vm-eastus \
  --name demo-vm

Navegar até o site Web

  1. Use o endereço IP público em um navegador da Web para verificar se a máquina virtual está disponível e em execução. Altere a URL para usar o valor de publicIpAddress.

    http://YOUR-VM-PUBLIC-IP-ADDRESS
    
  2. Se o recurso falhar com um erro de gateway, tente novamente em alguns minutos, o aplicativo Web pode demorar um pouco para começar.

  3. O aplicativo Web da máquina virtual retorna as seguintes informações:

    • Nome da VM
    • Seu IP do cliente
    • Data/hora atual

    Captura de tela do navegador da Web mostrando o aplicativo simples servido da máquina virtual Linus no Azure.

  4. O arquivo de código inicial para o aplicativo Web tem apenas uma rota, que passou pelo proxy NGINX.

    const os = require('os');
    const express = require('express')
    const app = express()
    
    app.use('/public', express.static('public'))
    app.get('/', function (req, res) {
    
        const clientIP = req.headers['x-forwarded-for'];
        const msg = `HostName: ${os.hostname()}<br>ClientIP: ${clientIP}<br>DateTime: ${new Date()}<br><img width='200' height='200' src='/public/leaves.jpg' alt='flowers'>`
        console.log(msg)
    
        res.send(msg)
    })
    app.listen(3000, function () {
        console.log(`Hello world app listening on port 3000! ${Date.now()}`)
    })
    

3. Conecte-se à máquina virtual Linux usando o SSH

Nesta seção do tutorial, use o SSH em um terminal para se conectar à sua máquina virtual. O SSH é uma ferramenta comum fornecida com vários shells modernos, incluindo o Azure Cloud Shell.

Conectar-se com o SSH e alterar o aplicativo Web

  1. Conecte-se à sua máquina virtual remota com o comando a seguir.

    Substitua YOUR-VM-PUBLIC-IP pelo IP público da sua máquina virtual.

    ssh azureuser@YOUR-VM-PUBLIC-IP
    

    Esse processo pressupõe que o cliente SSH pode encontrar as suas chaves SSH, criadas como parte da criação da VM e colocadas no seu computador local.

  2. Se perguntado se deseja continuar se conectando, responda y ou yes para continuar.

  3. Use o comando a seguir para entender o local em que você está na máquina virtual. Você deve estar na raiz azureuser: /home/azureuser.

    pwd
    
  4. Quando a conexão for concluída, o prompt do terminal deverá ser alterado para indicar o nome de usuário e o nome de recurso de máquina virtual remota.

    azureuser@demo-vm:
    
  5. O seu aplicativo Web está no subdiretório myapp. Altere para o diretório myapp e liste o conteúdo:

    cd myapp && ls -l
    
  6. Você deve ver o conteúdo representando o repositório GitHub clonado na máquina virtual e os arquivos do pacote npm:

    -rw-r--r--   1 root root   891 Nov 11 20:23 cloud-init-github.txt
    -rw-r--r--   1 root root  1347 Nov 11 20:23 index-logging.js
    -rw-r--r--   1 root root   282 Nov 11 20:23 index.js
    drwxr-xr-x 190 root root  4096 Nov 11 20:23 node_modules
    -rw-r--r--   1 root root 84115 Nov 11 20:23 package-lock.json
    -rw-r--r--   1 root root   329 Nov 11 20:23 package.json
    -rw-r--r--   1 root root   697 Nov 11 20:23 readme.md
    

Instalar SDK de monitoramento

  1. No terminal SSH que está conectado à sua máquina virtual, instale a biblioteca de clientes do SDK do Azure para o Application Insights.

    sudo npm install --save applicationinsights
    
  2. Aguarde até que o comando seja concluído antes de continuar.

Adicionar chave de instrumentação de monitoramento

  1. No terminal SSH que está conectado à sua máquina virtual, use o editor Nano para abrir o arquivo package.json.

    sudo nano package.json
    
  2. Adicione uma variável de ambiente APPINSIGHTS_INSTRUMENTATIONKEY ao início do script Iniciar. No exemplo a seguir, substitua REPLACE-WITH-YOUR-KEY pelo valor da sua chave de instrumentação.

    "start": "APPINSIGHTS_INSTRUMENTATIONKEY=REPLACE-WITH-YOUR-KEY pm2 start index.js --watch --log /var/log/pm2.log"
    
  3. Ainda no terminal SSH, salve o arquivo no editor Nano com o controle + X.

  4. Se solicitado no editor Nano, insira S para salvar.

  5. Se solicitado no editor Nano, aceite o nome do arquivo.

Pare a VM para alterar o aplicativo

A biblioteca de clientes do Azure agora está no seu diretório node_modules e a chave é passada para o aplicativo como uma variável de ambiente. A próxima etapa usa programaticamente o Application Insights.

  1. Interrompa PM2, que é um gerenciador de processo de produção para aplicativos Node.js, com os seguintes comandos:

    sudo npm run-script stop 
    
  2. Substitua o original index.js pelo arquivo usando o Application Insights.

    sudo npm run-script appinsights
    
  3. A biblioteca de cliente e o código de log são fornecidos para você.

    const express = require('express')
    const app = express()
    const os = require('os');
    
    console.log(JSON.stringify(process.env));
    
    const AppInsights = require('applicationinsights');
    
    if (process.env.APPINSIGHTS_INSTRUMENTATIONKEY) {
        console.log(`AppInsights configured with key ${process.env.APPINSIGHTS_INSTRUMENTATIONKEY}`);
    } else{
        console.log(`AppInsights not configured`);
    }
    
    AppInsights.setup(process.env.APPINSIGHTS_INSTRUMENTATIONKEY)
        .setAutoDependencyCorrelation(true)
        .setAutoCollectRequests(true)
        .setAutoCollectPerformance(true, true)
        .setAutoCollectExceptions(true)
        .setAutoCollectDependencies(true)
        .setAutoCollectConsole(true)
        .setUseDiskRetryCaching(true)
        .setSendLiveMetrics(false)
        .setDistributedTracingMode(AppInsights.DistributedTracingModes.AI)
        .start();
    
    const AppInsightsClient = AppInsights.defaultClient;
    
    
    app.get('/trace', (req, res) => {
    
        const clientIP = req.headers['x-forwarded-for'];
        const msg = `trace route ${os.hostname()} ${clientIP} ${new Date()}`;
    
        console.log(msg)
    
        if (process.env.APPINSIGHTS_INSTRUMENTATIONKEY) {
            AppInsightsClient.trackPageView();
            AppInsightsClient.trackTrace({ message: msg })
            AppInsightsClient.flush();
        } else {
            msg += ' AppInsights not configured';
        }
    
        res.send(`${msg}`)
    })
    
    app.get('/', function (req, res) {
    
        const clientIP = req.headers['x-forwarded-for'];
        const msg = `root route ${os.hostname()} ${clientIP} ${new Date()}`
    
        console.log(msg)
    
        res.send(msg)
    
    })
    app.listen(3000, function () {
        console.log(`Hello world app listening on port 3000! ${os.hostname()}`)
    })
    
  4. Reinicie o aplicativo com PM2 para escolher a próxima variável de ambiente.

    sudo npm start
    

Use o aplicativo para verificar o registro em log

  1. Em um navegador da Web, teste o aplicativo com a nova rota trace:

    http://YOUR-VM-PUBLIC-IP-ADDRESS/trace
    

    O navegador exibe a resposta trace route demo-vm YOUR-CLIENT-IP VM-DATE-TIME com o seu endereço IP.

Exibir o log para NGINX

A máquina virtual (VM) coleta logs para NGINX, que estão disponíveis para exibição.

Serviço Local do log
NGINX /var/log/nginx/access.log
  1. Ainda no terminal SSH, exiba o log da VM para o serviço proxy NGINX com o seguinte comando:
cat /var/log/nginx/access.log
  1. O log inclui a chamada do seu computador local.
"GET /trace HTTP/1.1" 200 10 "-"

Exibir o log para PM2

A máquina virtual coleta logs para PM2, que estão disponíveis para exibição.

Serviço Local do log
PM2 /var/log/pm2.log
  1. Exiba o log da VM para o serviço PM2, que é seu aplicativo Web do nó de Express.js. No mesmo shell do bash, use o seguinte comando para exibir o log:

    cat /var/log/pm2.log
    
  2. O log inclui a chamada do seu computador local.

    grep "Hello world app listening on port 3000!" /var/log/pm2.log
    
  3. O log também inclui suas variáveis de ambiente, incluindo a chave ApplicationInsights, passada no script de início do NPM. Use o seguinte comando grep para verificar se a chave está nas variáveis de ambiente.

    grep APPINSIGHTS_INSTRUMENTATIONKEY /var/log/pm2.log
    

    Isso exibe o log do PM2 com APPINSIGHTS_INSTRUMENTATIONKEY realçado em uma cor diferente.

Log de VM e log de nuvem

Neste aplicativo, o uso de console.log grava as mensagens nos logs do PM2 encontrados somente na VM. Se você excluir os logs ou a VM, perderá essas informações.

Se você quiser manter os logs além do ciclo de vida de sua máquina virtual, use o Application Insights.

5. Limpar os recursos

Depois de concluir este tutorial, você precisará remover o grupo de recursos, que inclui todos os seus recursos, a fim de garantir que você não será cobrado por mais nenhum uso.

No mesmo terminal, use o comando da CLI do Azure az group delete para excluir o grupo de recursos:

az group delete --name rg-demo-vm-eastus -y

Esse comando leva alguns minutos.

Solução de problemas

Se você tiver problemas, use a seguinte tabela para entender como resolver o problema:

Problema Resolução
Erro de Gateway 502 Isso pode indicar que o arquivo index.js ou package.js tem um erro. Exiba seus logs do PM2 em /var/log/pm2.log para obter mais informações. O erro mais recente está na parte inferior do arquivo. Se você tiver certeza de que esses arquivos estão corretos, pare e inicie o PM2 usando os scripts NPM em package.json.

Código de exemplo

Próximas etapas