Tutorial: Uso de cloud-init para personalizar una máquina virtual Linux en Azure durante el primer arranqueTutorial - How to use cloud-init to customize a Linux virtual machine in Azure on first boot

En un tutorial anterior, ha aprendido cómo acceder mediante SSH a una máquina virtual y a instalar NGINX de forma manual.In a previous tutorial, you learned how to SSH to a virtual machine (VM) and manually install NGINX. Para crear máquinas virtuales de manera rápida y coherente, alguna forma de automatización suele ser deseable.To create VMs in a quick and consistent manner, some form of automation is typically desired. Un enfoque común para personalizar una máquina virtual en el primer arranque es usar el comando cloud-init.A common approach to customize a VM on first boot is to use cloud-init. En este tutorial, aprenderá a:In this tutorial you learn how to:

  • Crear un archivo de configuración cloud-initCreate a cloud-init config file
  • Crear una máquina virtual que usa un archivo cloud-initCreate a VM that uses a cloud-init file
  • Ver una aplicación Node.js en ejecución una vez creada la máquina virtualView a running Node.js app after the VM is created
  • Usar Key Vault para almacenar de forma segura certificadosUse Key Vault to securely store certificates
  • Automatizar implementaciones seguras de NGINX con cloud-initAutomate secure deployments of NGINX with cloud-init

Si decide instalar y usar la CLI localmente, en este tutorial es preciso que ejecute la CLI de Azure de la versión 2.0.30, u otra posterior.If you choose to install and use the CLI locally, this tutorial requires that you are running the Azure CLI version 2.0.30 or later. Ejecute az --version para encontrar la versión.Run az --version to find the version. Si necesita instalarla o actualizarla, vea Instalación de la CLI de Azure.If you need to install or upgrade, see Install Azure CLI.

Introducción a cloud-initCloud-init overview

cloud-init es un enfoque ampliamente usado para personalizar una máquina virtual Linux la primera vez que se arranca.Cloud-init is a widely used approach to customize a Linux VM as it boots for the first time. Puede usar cloud-init para instalar paquetes y escribir archivos o para configurar los usuarios y la seguridad.You can use cloud-init to install packages and write files, or to configure users and security. Como cloud-init se ejecuta durante el proceso de arranque inicial, no hay pasos adicionales o agentes requeridos que aplicar a la configuración.As cloud-init runs during the initial boot process, there are no additional steps or required agents to apply your configuration.

cloud-init también funciona entre distribuciones.Cloud-init also works across distributions. Por ejemplo, no use apt-get install o yum install para instalar un paquete.For example, you don't use apt-get install or yum install to install a package. En su lugar, puede definir una lista de paquetes que se van a instalar.Instead you can define a list of packages to install. Cloud-init usará automáticamente la herramienta de administración de paquetes nativos para la distribución de Linux (distro) que seleccione.Cloud-init automatically uses the native package management tool for the distro you select.

Trabajamos con nuestros asociados para que cloud-init se incluya y funcione en las imágenes que estos proporcionan a Azure.We are working with our partners to get cloud-init included and working in the images that they provide to Azure. Para obtener información detallada sobre la compatibilidad de cloud-init con cada distribución, consulte Compatibilidad con cloud-init para máquinas virtuales en Azure.For detailed information cloud-init support for each distribution, see Cloud-init support for VMs in Azure.

Creación de un archivo de configuración cloud-initCreate cloud-init config file

Para ver cloud-init en acción, cree una máquina virtual que instale NGINX y ejecute una aplicación Node.js sencilla "Hello World".To see cloud-init in action, create a VM that installs NGINX and runs a simple 'Hello World' Node.js app. Con la siguiente configuración de cloud-init se instalan los paquetes necesarios, se crea una aplicación Node.js y luego se inicializa e inicia la aplicación.The following cloud-init configuration installs the required packages, creates a Node.js app, then initialize and starts the app.

En el símbolo del sistema de bash o en Cloud Shell, cree un archivo denominado cloud-init.txt y pegue la siguiente configuración.At your bash prompt or in the Cloud Shell, create a file named cloud-init.txt and paste the following configuration. Por ejemplo, escriba sensible-editor cloud-init.txt para crear el archivo y ver una lista de editores disponibles.For example, type sensible-editor cloud-init.txt to create the file and see a list of available editors. Asegúrese de que todo el archivo cloud-init se copia correctamente, especialmente la primera línea:Make sure that the whole cloud-init file is copied correctly, especially the first line:

#cloud-config
package_upgrade: true
packages:
  - nginx
  - nodejs
  - npm
write_files:
  - owner: www-data:www-data
    path: /etc/nginx/sites-available/default
    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
    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 más información sobre las opciones de configuración de cloud-init, consulte los ejemplos de configuración de cloud-init.For more information about cloud-init configuration options, see cloud-init config examples.

Crear máquina virtualCreate virtual machine

Antes de poder crear una máquina virtual, cree un grupo de recursos con az group create.Before you can create a VM, create a resource group with az group create. En el ejemplo siguiente, se crea un grupo de recursos denominado myResourceGroupAutomate en la ubicación eastus:The following example creates a resource group named myResourceGroupAutomate in the eastus location:

az group create --name myResourceGroupAutomate --location eastus

Ahora cree una máquina virtual con el comando az vm create.Now create a VM with az vm create. Use el parámetro --custom-data para pasar su archivo de configuración cloud-init.Use the --custom-data parameter to pass in your cloud-init config file. Proporcione la ruta de acceso completa a la configuración de cloud-init.txt si guardó el archivo fuera de su directorio de trabajo actual.Provide the full path to the cloud-init.txt config if you saved the file outside of your present working directory. En el ejemplo siguiente se crea una máquina virtual denominada myVM:The following example creates a VM named myVM:

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

Transcurren unos minutos hasta que la máquina virtual se crea, los paquetes se instalan y la aplicación se inicia.It takes a few minutes for the VM to be created, the packages to install, and the app to start. Hay tareas en segundo plano que continúan ejecutándose después de que la CLI de Azure vuelve a abrir el símbolo del sistema.There are background tasks that continue to run after the Azure CLI returns you to the prompt. Es posible que tenga que esperar otros dos minutos antes de poder acceder a la aplicación.It may be another couple of minutes before you can access the app. Cuando se haya creado la máquina virtual, anote el valor publicIpAddress mostrado por la CLI de Azure.When the VM has been created, take note of the publicIpAddress displayed by the Azure CLI. Esta dirección se usa para acceder a la aplicación Node.js mediante un explorador web.This address is used to access the Node.js app via a web browser.

Para permitir que el tráfico web llegue a la máquina virtual, abra el puerto 80 desde Internet con el comando az vm open-port:To allow web traffic to reach your VM, open port 80 from the Internet with az vm open-port:

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

Prueba de la aplicación webTest web app

Ahora puede abrir un explorador web y escribir http://<publicIpAddress> en la barra de direcciones.Now you can open a web browser and enter http://<publicIpAddress> in the address bar. Proporcione su propia dirección IP pública obtenida del proceso de creación de la máquina virtual.Provide your own public IP address from the VM create process. Su aplicación Node.js se muestra como en el ejemplo siguiente:Your Node.js app is displayed as shown in the following example:

Ver sitio de NGINX en funcionamiento

Inserción de certificados desde Key VaultInject certificates from Key Vault

En esta sección opcional se muestra cómo puede almacenar certificados de forma segura en Azure Key Vault e insertarlos durante la implementación de máquinas virtuales.This optional section shows how you can securely store certificates in Azure Key Vault and inject them during the VM deployment. En lugar de usar una imagen personalizada que incluye los certificados ya preparados, este proceso garantiza que los certificados más actualizados se insertan en una máquina virtual en el primer arranque.Rather than using a custom image that includes the certificates baked-in, this process ensures that the most up-to-date certificates are injected to a VM on first boot. Durante el proceso, el certificado nunca deja la plataforma de Azure ni se expone en un script, el historial de la línea de comandos o una plantilla.During the process, the certificate never leaves the Azure platform or is exposed in a script, command-line history, or template.

Azure Key Vault protege claves y secretos criptográficos, como certificados y contraseñas.Azure Key Vault safeguards cryptographic keys and secrets, such as certificates or passwords. Key Vault ayuda a agilizar el proceso de administración de claves y le permite mantener el control de las claves que acceden a sus datos y los cifran.Key Vault helps streamline the key management process and enables you to maintain control of keys that access and encrypt your data. En este escenario se presentan algunos conceptos de Key Vault para crear y usar un certificado, si bien no es una introducción exhaustiva sobre cómo usar Key Vault.This scenario introduces some Key Vault concepts to create and use a certificate, though is not an exhaustive overview on how to use Key Vault.

Los pasos siguientes muestran cómo puede:The following steps show how you can:

  • Crear una instancia de Azure Key VaultCreate an Azure Key Vault
  • Generar o cargar un certificado en Key VaultGenerate or upload a certificate to the Key Vault
  • Crear un secreto a partir del certificado para insertarlo en una máquina virtualCreate a secret from the certificate to inject in to a VM
  • Crear una máquina virtual e insertar el certificadoCreate a VM and inject the certificate

Crear una instancia de Azure Key VaultCreate an Azure Key Vault

En primer lugar, cree una instancia de Key Vault con az keyvault create y habilítela para su uso al implementar una máquina virtual.First, create a Key Vault with az keyvault create and enable it for use when you deploy a VM. Cada instancia de Key Vault requiere un nombre único, que debe estar todo en minúsculas.Each Key Vault requires a unique name, and should be all lower case. Reemplace mykeyvault en el siguiente ejemplo por su propio nombre único de Key Vault:Replace mykeyvault in the following example with your own unique Key Vault name:

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

Generación de un certificado y su almacenamiento en Key VaultGenerate certificate and store in Key Vault

Para usarlo en producción, debe importar un certificado válido firmado por un proveedor de confianza con az keyvault certificate import.For production use, you should import a valid certificate signed by trusted provider with az keyvault certificate import. En este tutorial, el ejemplo siguiente muestra cómo puede generar un certificado autofirmado con az keyvault certificate create que usa la directiva de certificado predeterminada:For this tutorial, the following example shows how you can generate a self-signed certificate with az keyvault certificate create that uses the default certificate policy:

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

Preparación del certificado para usarlo con la máquina virtualPrepare certificate for use with VM

Para usar el certificado durante el proceso de creación de la máquina virtual, obtenga el id. del certificado con az keyvault secret list-versions.To use the certificate during the VM create process, obtain the ID of your certificate with az keyvault secret list-versions. La máquina virtual necesita el certificado en un formato determinado para insertarlo en el arranque, por lo que convierte el certificado con az vm secret format.The VM needs the certificate in a certain format to inject it on boot, so convert the certificate with az vm secret format. En el ejemplo siguiente se asigna la salida de estos comandos a las variables para facilitar su uso en los pasos siguientes:The following example assigns the output of these commands to variables for ease of use in the next steps:

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)

Creación de la configuración de cloud-init para proteger NGINXCreate cloud-init config to secure NGINX

Cuando crea una máquina virtual, los certificados y las claves se almacenan en el directorio /var/lib/waagent/ protegido.When you create a VM, certificates and keys are stored in the protected /var/lib/waagent/ directory. Para automatizar el proceso de agregar el certificado a la máquina virtual y configurar NGINX, puede utilizar la configuración de cloud-init actualizada del ejemplo anterior.To automate adding the certificate to the VM and configuring NGINX, you can use an updated cloud-init config from the previous example.

Cree un archivo denominado "cloud-init-secured.txt" y pegue la siguiente configuración.Create a file named cloud-init-secured.txt and paste the following configuration. Si se utiliza Cloud Shell, cree ahí el archivo de configuración de cloud-init y no en la máquina local.If you use the Cloud Shell, create the cloud-init config file there and not on your local machine. Por ejemplo, escriba sensible-editor cloud-init-secured.txt para crear el archivo y ver una lista de editores disponibles.For example, type sensible-editor cloud-init-secured.txt to create the file and see a list of available editors. Asegúrese de que todo el archivo cloud-init se copia correctamente, especialmente la primera línea:Make sure that the whole cloud-init file is copied correctly, especially the first line:

#cloud-config
package_upgrade: true
packages:
  - nginx
  - nodejs
  - npm
write_files:
  - owner: www-data:www-data
    path: /etc/nginx/sites-available/default
    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
    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

Creación de una máquina virtual seguraCreate secure VM

Ahora cree una máquina virtual con el comando az vm create.Now create a VM with az vm create. Los datos del certificado se insertan desde Key Vault con el parámetro --secrets.The certificate data is injected from Key Vault with the --secrets parameter. Como en el ejemplo anterior, se pasa la configuración de cloud-init con el parámetro --custom-data:As in the previous example, you also pass in the cloud-init config with the --custom-data parameter:

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

Transcurren unos minutos hasta que la máquina virtual se crea, los paquetes se instalan y la aplicación se inicia.It takes a few minutes for the VM to be created, the packages to install, and the app to start. Hay tareas en segundo plano que continúan ejecutándose después de que la CLI de Azure vuelve a abrir el símbolo del sistema.There are background tasks that continue to run after the Azure CLI returns you to the prompt. Es posible que tenga que esperar otros dos minutos antes de poder acceder a la aplicación.It may be another couple of minutes before you can access the app. Cuando se haya creado la máquina virtual, anote el valor publicIpAddress mostrado por la CLI de Azure.When the VM has been created, take note of the publicIpAddress displayed by the Azure CLI. Esta dirección se usa para acceder a la aplicación Node.js mediante un explorador web.This address is used to access the Node.js app via a web browser.

Para permitir que el tráfico web llegue a la máquina virtual, abra el puerto 443 desde Internet con el comando az vm open-port:To allow secure web traffic to reach your VM, open port 443 from the Internet with az vm open-port:

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

Prueba de la aplicación web seguraTest secure web app

Ahora puede abrir un explorador web y escribir https://<publicIpAddress> en la barra de direcciones.Now you can open a web browser and enter https://<publicIpAddress> in the address bar. Proporcione su propia dirección IP pública, como se muestra en la salida del proceso anterior de creación de máquinas virtuales.Provide your own public IP address as shown in the output of the previous VM create process. Acepte la advertencia de seguridad si usó un certificado autofirmado:Accept the security warning if you used a self-signed certificate:

Aceptar la advertencia de seguridad del explorador web

Se muestran el sitio de NGINX protegido y la aplicación Node.js, como en el ejemplo siguiente:Your secured NGINX site and Node.js app is then displayed as in the following example:

Ver el sitio de NGINX seguro en funcionamiento

Pasos siguientesNext steps

En este tutorial, ha configurado las máquinas virtuales en el primer inicio con cloud-init.In this tutorial, you configured VMs on first boot with cloud-init. Ha aprendido a:You learned how to:

  • Crear un archivo de configuración cloud-initCreate a cloud-init config file
  • Crear una máquina virtual que usa un archivo cloud-initCreate a VM that uses a cloud-init file
  • Ver una aplicación Node.js en ejecución una vez creada la máquina virtualView a running Node.js app after the VM is created
  • Usar Key Vault para almacenar de forma segura certificadosUse Key Vault to securely store certificates
  • Automatizar implementaciones seguras de NGINX con cloud-initAutomate secure deployments of NGINX with cloud-init

Avanzar al siguiente tutorial para aprender a crear imágenes de máquina virtual personalizadas.Advance to the next tutorial to learn how to create custom VM images.