Creare Express.js macchina virtuale con l'interfaccia della riga di comando di Azure

In questa esercitazione verrà creata una macchina virtuale Linux per un'app Express.js. La macchina virtuale è configurata con un file di configurazione cloud-init e include NGINX e un repository GitHub per un'app Express.js. Connessione alla macchina virtuale con SSH, modificare l'app Web in modo da includere la registrazione della traccia e visualizzare l'app server Express.js pubblica in un Web browser.

Questa esercitazione include le attività seguenti:

  • Accedere ad Azure con l'interfaccia della riga di comando di Azure
  • Creare una risorsa vm Linux di Azure con l'interfaccia della riga di comando di Azure
    • Aprire la porta pubblica 80
    • Installare l'app Web Express.js demo da un repository GitHub
    • Installare le dipendenze dell'app Web
    • Avviare l'app Web
  • Creare una risorsa di monitoraggio di Azure con l'interfaccia della riga di comando di Azure
    • Connettersi alla macchina virtuale con SSH
    • Installare la libreria client di Azure SDK con npm
    • Aggiungere il codice della libreria client di Application Insights per creare la traccia personalizzata
  • Visualizzare l'app Web dal browser
    • Richiedere alla route /trace di generare la traccia personalizzata nel log di Application Insights
    • Visualizzare il numero di tracce raccolte nei log con l'interfaccia della riga di comando di Azure
    • Visualizzare l'elenco di tracce con il portale di Azure
  • Rimuovere le risorse con l'interfaccia della riga di comando di Azure

Creare o usare una sottoscrizione di Azure esistente

È necessario un account utente di Azure con una sottoscrizione attiva. Crearne una gratuitamente.

Prerequisiti

  • SSH per connettersi alla macchina virtuale: usare Azure Cloud Shell o un terminale moderno, ad esempio bash shell, che include SSH.

1. Creare una risorsa di Application Insights per le pagine Web

Creare un gruppo di risorse di Azure per tutte le risorse di Azure e una risorsa di Monitoraggio di Azure per raccogliere i file di log dell'app Web nel cloud di Azure. La creazione di un gruppo di risorse consente di trovare facilmente le risorse ed eliminarle al termine. Monitoraggio di Azure è il nome del servizio di Azure, mentre Application Insights è il nome della libreria client utilizzata nell'esercitazione.

  1. Facoltativo, se sono presenti più sottoscrizioni, usare az account set per impostare la sottoscrizione predefinita prima di completare i comandi rimanenti.

    az account set \
        --subscription "ACCOUNT NAME OR ID" 
    
  2. Creare un gruppo di risorse di Azure con az group create. Usare il nome rg-demo-vm-eastus:

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

Creare una risorsa di Monitoraggio di Azure con l'interfaccia della riga di comando di Azure

  1. Installare l'estensione di Application Insights nell'interfaccia della riga di comando di Azure.

    az extension add -n application-insights
    
  2. Usare il comando seguente per creare una risorsa di monitoraggio con 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. Copiare il risultato dall'output, che sarà necessario come instrumentationKey indicato in un secondo momento.

  4. Lasciare aperto il terminale, verrà usato nel passaggio successivo.

2. Creare una macchina virtuale Linux con l'interfaccia della riga di comando di Azure

Usa un file di configurazione cloud-init per creare sia il server proxy inverso NGINX che il server Express.js. NGINX viene usato per trasferire la porta Express.js (3000) alla porta pubblica (80).

  1. Creare un file locale denominato cloud-init-github.txt e salvarvi il contenuto seguente oppure è possibile salvare il file del repository nel computer locale. Il file cloud-init formattato deve esistere nella stessa cartella del percorso del terminale per i comandi dell'interfaccia della riga di comando di 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. Esaminare la runcmd sezione del file per comprendere le operazioni che esegue.

    Il comando runcmd ha diverse attività:

    • Scaricare Node.js e installarlo
    • Clonare il repository di esempio Express.js da GitHub nella myapp directory
    • Installare le dipendenze dell'applicazione
    • Avviare l'app Express.js con PM2

Creare una risorsa di macchina virtuale

  1. Immettere il comando dell'interfaccia della riga di comando di Azure az vm create in un terminale per creare una risorsa di Azure di una macchina virtuale Linux. Il comando crea la macchina virtuale dal file cloud-init e genera le chiavi SSH. Il comando in esecuzione visualizza la posizione di archiviazione delle chiavi.

    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. Attendere alcuni minuti.

  3. Mantenere il valore publicIpAddress dalla risposta, è necessario visualizzare l'app Web in un browser e connettersi alla macchina virtuale. Se si perde questo indirizzo IP, usare il comando dell'interfaccia della riga di comando di Azure, az vm list-ip-addresses per recuperarlo di nuovo.

  4. Il processo ha creato chiavi SSH e ma in una posizione indicata nella risposta.

  5. Passare a tale percorso e creare il authorized_keys file:

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

Aprire la porta per la macchina virtuale

Al momento della creazione, la macchina virtuale non ha porte aperte. Aprire la porta 80 con il comando seguente dell'interfaccia della riga di comando di Azure, az vm open-port in modo che l'app Web sia disponibile pubblicamente:

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

Passare al sito Web

  1. Usare l'indirizzo IP pubblico in un Web browser per assicurarsi che la macchina virtuale sia disponibile e in esecuzione. Modificare l'URL in modo da usare il valore di publicIpAddress.

    http://YOUR-VM-PUBLIC-IP-ADDRESS
    
  2. In caso di errore del gateway della risorsa, riprovare tra qualche minuto, l'avvio dell'app Web potrebbe richiedere qualche minuto.

  3. L'app Web della macchina virtuale restituisce le informazioni seguenti:

    • Nome della VM.
    • INDIRIZZO IP client
    • Data/ora correnti

    Screenshot del Web browser che mostra un'app semplice servita dalla macchina virtuale Linus in Azure.

  4. Il file di codice iniziale per l'app Web ha una singola route, che passa attraverso il 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. Connessione alla macchina virtuale Linux tramite SSH

In questa sezione dell'esercitazione usare SSH in un terminale per connettersi alla macchina virtuale. SSH è uno strumento comune fornito con numerose shell moderne, tra cui Azure Cloud Shell.

Connettersi con SSH e modificare l'app Web

  1. Connettersi alla macchina virtuale remota con il comando seguente.

    Sostituire YOUR-VM-PUBLIC-IP con l'indirizzo IP pubblico della macchina virtuale.

    ssh azureuser@YOUR-VM-PUBLIC-IP
    

    Questo processo presuppone che il client SSH riesca a trovare le chiavi SSH, create come parte della creazione della macchina virtuale e posizionate nel computer locale.

  2. Se viene chiesto se si è certi di volersi connettere, rispondere y o yes continuare.

  3. Usare il comando seguente per comprendere la posizione nella macchina virtuale. La posizione dovrebbe essere la radice azureuser: /home/azureuser.

    pwd
    
  4. Al termine della connessione, il prompt del terminale deve cambiare per indicare il nome utente e il nome della risorsa della macchina virtuale remota.

    azureuser@demo-vm:
    
  5. L'app Web si trova nella sottodirectory myapp. Passare alla directory myapp ed elencare il contenuto:

    cd myapp && ls -l
    
  6. Verrà visualizzato il contenuto che rappresenta il repository GitHub clonato nella macchina virtuale e nei file del pacchetto 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
    

Installare Monitoring SDK

  1. Nel terminale SSH, connesso alla macchina virtuale, installare la libreria client di Azure SDK per Application Insights.

    sudo npm install --save applicationinsights
    
  2. Attendere il completamento del comando prima di continuare.

Aggiungere la chiave di strumentazione di Monitoraggio

  1. Nel terminale SSH, connesso alla macchina virtuale, usare l'editor Nano per aprire il package.json file.

    sudo nano package.json
    
  2. Aggiungere una APPINSIGHTS_INSTRUMENTATIONKEY variabile di ambiente all'inizio dello script Start . Nell'esempio seguente sostituire REPLACE-WITH-YOUR-KEY con il valore della chiave di strumentazione.

    "start": "APPINSIGHTS_INSTRUMENTATIONKEY=REPLACE-WITH-YOUR-KEY pm2 start index.js --watch --log /var/log/pm2.log"
    
  3. Sempre nel terminale SSH salvare il file nell'editor Nano con il controllo + X.

  4. Se richiesto nell'editor Nano, immettere Y per salvare.

  5. Se richiesto nell'editor Nano, accettare il nome del file quando richiesto.

Arrestare la macchina virtuale per modificare l'applicazione

La libreria client di Azure è ora presente nella directory node_modules e la chiave viene passata all'app come variabile di ambiente. Il passaggio successivo usa Application Insights a livello di codice.

  1. Arrestare PM2, ovvero un gestore di processi di produzione per le applicazioni Node.js, con i comandi seguenti:

    sudo npm run-script stop 
    
  2. Sostituire l'originale index.js con il file usando Application Insights.

    sudo npm run-script appinsights
    
  3. La libreria client e il codice di registrazione vengono forniti per l'utente.

    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. Riavviare l'app con PM2 per selezionare la variabile di ambiente successiva.

    sudo npm start
    

Usare l'app per verificare la registrazione

  1. In un Web browser testare l'app con la nuova route trace:

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

    Il browser mostra la risposta trace route demo-vm YOUR-CLIENT-IP VM-DATE-TIME con l'indirizzo IP dell'utente.

Visualizzazione del log per NGINX

La macchina virtuale raccoglie i log per NGINX, disponibili per la visualizzazione.

Service Percorso log
NGINX /var/log/nginx/access.log
  1. Sempre nel terminale SSH, visualizzare il log delle macchine virtuali per il servizio proxy NGINX con il comando seguente per visualizzare il log:
cat /var/log/nginx/access.log
  1. Il log include la chiamata dal computer locale.
"GET /trace HTTP/1.1" 200 10 "-"

Visualizzazione del log per PM2

La macchina virtuale raccoglie i log per PM2, disponibili per la visualizzazione.

Service Percorso log
PM2 /var/log/pm2.log
  1. Visualizzare il log delle macchine virtuali per il servizio PM2, ovvero l'app Web node Express.js. Nella stessa shell Bash, usare il comando seguente per visualizzare il log:

    cat /var/log/pm2.log
    
  2. Il log include la chiamata dal computer locale.

    grep "Hello world app listening on port 3000!" /var/log/pm2.log
    
  3. Il log include anche le variabili di ambiente, inclusa la chiave ApplicationInsights, passata nello script di avvio npm. usare il comando grep seguente per verificare che la chiave si trova nelle variabili di ambiente.

    grep APPINSIGHTS_INSTRUMENTATIONKEY /var/log/pm2.log
    

    Verrà visualizzato il log PM2 con APPINSIGHTS_INSTRUMENTATIONKEY evidenziato in un colore diverso.

Registrazione delle macchine virtuali e registrazione cloud

In questa applicazione, usando console.log scrive i messaggi nei log PM2 trovati solo nella macchina virtuale. Se si eliminano i log o la macchina virtuale, si perdono tali informazioni.

Se si vogliono conservare i log oltre la durata della macchina virtuale, usare Application Insights.

5. Pulire le risorse

Dopo aver completato questa esercitazione, è necessario rimuovere il gruppo di risorse, che include tutte le relative risorse per assicurarsi che non vengano addebitate altre spese per l'utilizzo.

Nello stesso terminale usare il comando dell'interfaccia della riga di comando di Azure az group delete per eliminare il gruppo di risorse:

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

L'esecuzione di questo comando richiede alcuni minuti.

Risoluzione dei problemi

In caso di problemi, usare la tabella seguente per comprendere come risolvere il problema:

Problema Risoluzione
502 Errore del gateway Ciò potrebbe indicare che il file index.js o package.js presenta un errore. Per altre informazioni, vedere i log pm2 all'indirizzo /var/log/pm2.log . L'errore più recente si trova nella parte inferiore del file. Se si è certi che tali file siano corretti, arrestare e avviare PM2 usando gli script npm in package.json.

Codice di esempio

Passaggi successivi