Creación de una máquina virtual Express.js con la CLI de Azure

En este tutorial, creará una máquina virtual Linux para una aplicación de Express.js. La máquina virtual se configura con un archivo de configuración cloud-init e incluye NGINX y un repositorio de GitHub para una aplicación de Express.js. Conectar a la máquina virtual con SSH, cambie la aplicación web para incluir el registro de seguimiento y vea la aplicación pública del servidor Express.js en un explorador web.

Este tutorial incluye las siguientes tareas:

  • Inicio de sesión en Azure con la CLI de Azure
  • Creación de un recurso de máquina virtual Linux de Azure con la CLI de Azure
    • Apertura del puerto público 80
    • Instalación de la aplicación web de Express.js de demostración desde un repositorio de GitHub
    • Instalación de las dependencias de la aplicación web
    • Inicio de la aplicación web
  • Creación de un recurso de supervisión de Azure con la CLI de Azure
    • Conexión a la máquina virtual con SSH
    • Instalación de la biblioteca cliente del SDK de Azure con npm
    • Adición del código de la biblioteca cliente de Application Insights para crear el seguimiento personalizado
  • Visualización de la aplicación web desde el explorador
    • Solicitud de la ruta /trace para generar el seguimiento personalizado en el registro de Application Insights
    • Visualización del recuento de seguimientos recopilados en el registro con la CLI de Azure
    • Visualización de la lista de seguimientos con Azure Portal
  • Eliminación de los recursos con la CLI de Azure

Creación o uso de una suscripción de Azure existente

Necesitará una cuenta de usuario de Azure con una suscripción activa. cree una de forma gratuita.

Requisitos previos

  • SSH para conectarse a la máquina virtual: use Azure Cloud Shell o un terminal moderno, como el shell de Bash, que incluye SSH.

1. Creación de un recurso de application Ideas para páginas web

Cree un grupo de recursos de Azure para todos los recursos de Azure y un recurso de Azure Monitor para recopilar los archivos de registro de la aplicación web en la nube de Azure. La creación de un grupo de recursos le permite encontrar fácilmente los recursos y eliminarlos cuando haya terminado. Azure Monitor es el nombre del servicio de Azure, mientras que Application Insights es el nombre de la biblioteca cliente que usa el tutorial.

  1. Opcional, si tiene más de una suscripción, use az account set para establecer la suscripción predeterminada antes de completar los comandos restantes.

    az account set \
        --subscription "ACCOUNT NAME OR ID" 
    
  2. Cree un grupo de recursos de Azure con az group create. Use el nombre rg-demo-vm-eastus:

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

Creación de un recurso de Azure Monitor con la CLI de Azure

  1. Instale la extensión de Application Insights en la CLI de Azure.

    az extension add -n application-insights
    
  2. Use el comando siguiente para crear un recurso de supervisión, 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. Copie el resultado de la salida; necesitará ese valor como el instrumentationKey más adelante.

  4. Deje abierto el terminal, lo usará en el paso siguiente.

2. Creación de una máquina virtual Linux mediante la CLI de Azure

Usa un archivo de configuración cloud-init para crear el servidor proxy inverso NGINX y el servidor Express.js. NGINX se usa para reenviar el puerto de Express.js (3000) al puerto público (80).

  1. Cree un archivo local llamado cloud-init-github.txt y guarde el contenido siguiente en el archivo, o bien guarde el archivo del repositorio en el equipo local. El archivo con formato cloud-init debe existir en la misma carpeta que la ruta de acceso del terminal para los comandos de la CLI de 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. Revise la sección runcmd del archivo para comprender lo que hace.

    runcmd tiene varias tareas:

    • Descargar Node.js e instalarlo
    • Clonar el repositorio Express.js de ejemplo de GitHub en el directorio myapp
    • Instalar las dependencias de la aplicación
    • Iniciar la aplicación de Express.js con PM2

Creación de un recurso de máquina virtual

  1. Escriba el comando de la CLI de Azure, az vm create, en un terminal para crear un recurso de Azure de una máquina virtual Linux. El comando crea la máquina virtual a partir del archivo cloud-init y genera las claves SSH automáticamente. El comando en ejecución muestra dónde se almacenan las claves.

    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. Espere mientras el proceso puede tardar unos minutos.

  3. Mantenga el valor publicIpAddress de la respuesta, es necesario ver la aplicación web en un explorador y conectarse a la máquina virtual. Si pierde esta dirección IP, use el comando de la CLI de Azure, az vm list-ip-addresses para obtenerla de nuevo.

  4. El proceso creó claves SSH y, sin embargo, en una ubicación indicada en la respuesta.

  5. Vaya a esa ubicación y cree el authorized_keys archivo:

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

Apertura del puerto de la máquina virtual

Cuando se crea por primera vez, la máquina virtual no tiene puertos abiertos. Abra el puerto 80 con el siguiente comando de la CLI de Azure, az vm open-port para que la aplicación web esté disponible públicamente:

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

Ir al sitio web

  1. Use la dirección IP pública en un explorador web para asegurarse de que la máquina virtual está disponible y en ejecución. Cambie la dirección URL para usar el valor de publicIpAddress.

    http://YOUR-VM-PUBLIC-IP-ADDRESS
    
  2. Si se produce un error de puerta de enlace en el recurso, inténtelo de nuevo en un minuto, la aplicación web puede tardar un minuto en iniciarse.

  3. La aplicación web de la máquina virtual devuelve la siguiente información:

    • Nombre de la máquina virtual
    • Dirección IP del cliente
    • Fecha y hora actuales

    Screenshot of web browser showing simple app served from Linus virtual machine on Azure.

  4. El archivo de código inicial de la aplicación web tiene una sola ruta, que pasa mediante el 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. Conectar a la máquina virtual Linux mediante SSH

En esta sección del tutorial, usará SSH en un terminal para conectarse a la máquina virtual. SSH es una herramienta común que se proporciona con muchos shells modernos, incluido Azure Cloud Shell.

Conexión con SSH y cambio de la aplicación web

  1. Conéctese a la máquina virtual remota con el siguiente comando.

    Reemplace YOUR-VM-PUBLIC-IP por la dirección IP pública de su propia máquina virtual.

    ssh azureuser@YOUR-VM-PUBLIC-IP
    

    En este proceso se supone que el cliente SSH puede encontrar las claves SSH, creadas como parte de la creación de la máquina virtual y ubicadas en el equipo local.

  2. Si se le pregunta si está seguro de que desea conectarse, responder y o yes continuar.

  3. Use el comando siguiente para saber dónde se encuentra en la máquina virtual. Debe estar en la carpeta raíz de azureuser: /home/azureuser.

    pwd
    
  4. Una vez completada la conexión, el símbolo del sistema del terminal debe cambiar para indicar el nombre de usuario y el nombre del recurso de la máquina virtual remota.

    azureuser@demo-vm:
    
  5. La aplicación web se encuentra en el subdirectorio myapp. Cambie al directorio myapp y enumere el contenido:

    cd myapp && ls -l
    
  6. Debería ver el contenido que representa el repositorio de GitHub clonado en la máquina virtual y los archivos de paquete de 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
    

Instalación del SDK de supervisión

  1. En el terminal SSH, que está conectado a la máquina virtual, instale la biblioteca cliente del SDK de Azure para Application Ideas.

    sudo npm install --save applicationinsights
    
  2. Espere hasta que se complete el comando antes de continuar.

Adición de la clave de instrumentación de supervisión

  1. En el terminal SSH, que está conectado a la máquina virtual, use el editor Nano para abrir el archivo package.json.

    sudo nano package.json
    
  2. Agregue la variable de entorno APPINSIGHTS_INSTRUMENTATIONKEY al principio del script de inicio. En el ejemplo siguiente, reemplace REPLACE-WITH-YOUR-KEY por el valor de la clave de instrumentación.

    "start": "APPINSIGHTS_INSTRUMENTATIONKEY=REPLACE-WITH-YOUR-KEY pm2 start index.js --watch --log /var/log/pm2.log"
    
  3. Todavía en el terminal SSH, guarde el archivo en el editor Nano con control + X.

  4. Si se le solicita en el editor nano, escriba Y para guardar.

  5. Si se le solicita en el editor nano, acepte el nombre de archivo cuando se le solicite.

Detener la máquina virtual para cambiar la aplicación

La biblioteca cliente de Azure está ahora en el directorio node_modules y la clave se pasa a la aplicación como una variable de entorno. En el paso siguiente se usa application Ideas mediante programación.

  1. Detenga PM2, que es un administrador de procesos de producción para aplicaciones de Node.js, con los siguientes comandos:

    sudo npm run-script stop 
    
  2. Reemplace original index.js por archivo mediante Application Ideas.

    sudo npm run-script appinsights
    
  3. La biblioteca cliente y el código de registro se proporcionan automáticamente.

    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 la aplicación con PM2 para seleccionar la siguiente variable de entorno.

    sudo npm start
    

Uso de la aplicación para comprobar el registro

  1. En un explorador web, pruebe la aplicación con la nueva ruta trace:

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

    El explorador muestra la respuesta trace route demo-vm YOUR-CLIENT-IP VM-DATE-TIME con la dirección IP.

Visualización del registro de NGINX

La máquina virtual (VM) recopila registros de NGINX, que están disponibles para ver.

Servicio Ubicación del registro
NGINX /var/log/nginx/access.log
  1. Todavía en el terminal SSH, consulte el registro de la máquina virtual para el servicio de proxy NGINX con el siguiente comando para ver el registro:
cat /var/log/nginx/access.log
  1. El registro incluye la llamada desde el equipo local.
"GET /trace HTTP/1.1" 200 10 "-"

Visualización del registro de PM2

La máquina virtual recopila registros de PM2, que están disponibles para ver.

Servicio Ubicación del registro
PM2 /var/log/pm2.log
  1. Consulte el registro de la máquina virtual para el servicio PM2, que es la aplicación web de Node de Express.js. En el mismo shell de Bash, use el siguiente comando para ver el registro:

    cat /var/log/pm2.log
    
  2. El registro incluye la llamada desde el equipo local.

    grep "Hello world app listening on port 3000!" /var/log/pm2.log
    
  3. El registro también incluye las variables de entorno, incluida la clave de ApplicationInsights, que se pasan en el script de inicio de npm. Utilice el siguiente comando grep para comprobar que la clave está en las variables de entorno.

    grep APPINSIGHTS_INSTRUMENTATIONKEY /var/log/pm2.log
    

    Esto muestra el registro de PM2 con el valor de APPINSIGHTS_INSTRUMENTATIONKEY resaltado en un color diferente.

Registro de máquinas virtuales y registro en la nube

En esta aplicación, el uso de console.log escribe solo los mensajes en los registros de PM2 que se encuentran en la máquina virtual. Si elimina los registros o la máquina virtual, perderá esa información.

Si desea conservar los registros más allá de la duración de la máquina virtual, use Application Insights.

5. Limpieza de recursos

Una vez completado este tutorial, debe quitar el grupo de recursos, que incluye todos sus recursos para asegurarse de que no se le factura ningún uso más.

En el mismo terminal, use el comando de la CLI de Azure, az group delete, para eliminar el grupo de recursos:

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

Este comando tarda unos minutos.

Solucionar problemas

Si tiene problemas, use la tabla siguiente para saber cómo resolver el problema:

Problema Solución
Error de puerta de enlace incorrecta 502 Esto podría indicar que el archivo index.js o package.js tienen un error. Consulte los registros de PM2 en /var/log/pm2.log para más información. El error más reciente se encuentra en la parte inferior del archivo. Si está seguro de que esos archivos son correctos, detenga e inicie pm2 mediante los scripts de npm en package.json.

Código de ejemplo

Pasos siguientes