Personalizzare una macchina virtuale al primo avvioHow to customize a Linux virtual machine on first boot

In un'esercitazione precedente si è appreso come eseguire una connessione SSH a una macchina virtuale (VM) e come installare manualmente NGINX.In a previous tutorial, you learned how to SSH to a virtual machine (VM) and manually install NGINX. Per creare macchine virtuali in modo rapido e coerente, di norma è consigliabile una qualche forma di automazione.To create VMs in a quick and consistent manner, some form of automation is typically desired. Un approccio comune per personalizzare una macchina virtuale al primo avvio consiste nell'usare cloud-init.A common approach to customize a VM on first boot is to use cloud-init. In questa esercitazione si apprenderà come:In this tutorial you learn how to:

  • Creare un file di configurazione cloud-initCreate a cloud-init config file
  • Creare una macchina virtuale che usa un file cloud-initCreate a VM that uses a cloud-init file
  • Visualizzare un'esecuzione dell'app Node.js dopo aver creato la macchina virtualeView a running Node.js app after the VM is created
  • Usare Key Vault per archiviare in modo sicuro i certificatiUse Key Vault to securely store certificates
  • Automatizzare le distribuzioni sicure di NGINX con cloud-initAutomate secure deployments of NGINX with cloud-init

Avviare Azure Cloud ShellLaunch Azure Cloud Shell

Azure Cloud Shell è una shell Bash gratuita che può essere eseguita direttamente nel portale di Azure.The Azure Cloud Shell is a free Bash shell that you can run directly within the Azure portal. Include l'interfaccia della riga di comando di Azure preinstallata e configurata per l'uso con l'account.It has the Azure CLI preinstalled and configured to use with your account. Fare clic sul pulsante Cloud Shell nel menu nel riquadro in alto a destra nel portale di Azure.Click the Cloud Shell button on the menu in the upper-right of the Azure portal.

Cloud ShellCloud Shell

Il pulsante avvia una shell interattiva che è possibile usare per eseguire i passaggi di questo argomento:The button launches an interactive shell that you can use to run the steps in this topic:

Screenshot che mostra la finestra di Cloud Shell nel portaleScreenshot showing the Cloud Shell window in the portal

Se si sceglie di installare e usare l'interfaccia della riga di comando in locale, per questa esercitazione è necessario eseguire l'interfaccia della riga di comando di Azure versione 2.0.4 o successiva.If you choose to install and use the CLI locally, this tutorial requires that you are running the Azure CLI version 2.0.4 or later. Eseguire az --version per trovare la versione.Run az --version to find the version. Se è necessario eseguire l'installazione o l'aggiornamento, vedere Installare l'interfaccia della riga di comando di Azure 2.0.If you need to install or upgrade, see Install Azure CLI 2.0.

Panoramica di cloud-initCloud-init overview

Cloud-init è un approccio diffuso per personalizzare una macchina virtuale Linux al primo avvio.Cloud-init is a widely used approach to customize a Linux VM as it boots for the first time. Cloud-init consente di installare pacchetti e scrivere file o configurare utenti e impostazioni di sicurezza.You can use cloud-init to install packages and write files, or to configure users and security. Quando cloud-init viene eseguito durante il processo di avvio iniziale non vi sono altri passaggi o agenti necessari per applicare la configurazione.As cloud-init runs during the initial boot process, there are no additional steps or required agents to apply your configuration.

Cloud-init funziona anche fra distribuzioni.Cloud-init also works across distributions. Ad esempio, non si usa apt-get install o yum install per installare un pacchetto.For example, you don't use apt-get install or yum install to install a package. In alternativa, è possibile definire un elenco di pacchetti da installare.Instead you can define a list of packages to install. Cloud-init userà automaticamente lo strumento di gestione del pacchetto nativo per la distribuzione selezionata.Cloud-init automatically uses the native package management tool for the distro you select.

Microsoft collabora con i partner per promuovere l'inclusione e il funzionamento di cloud-init con le immagini da essi fornite per Azure.We are working with our partners to get cloud-init included and working in the images that they provide to Azure. La tabella seguente illustra l'attuale disponibilità di cloud-init nelle immagini della piattaforma Azure:The following table outlines the current cloud-init availability on Azure platform images:

AliasAlias AutorePublisher OffertaOffer SKUSKU VersioneVersion
UbuntuLTSUbuntuLTS CanonicalCanonical UbuntuServerUbuntuServer 16.04-LTS16.04-LTS più recentilatest
UbuntuLTSUbuntuLTS CanonicalCanonical UbuntuServerUbuntuServer 14.04.5-LTS14.04.5-LTS più recentilatest
CoreOSCoreOS CoreOSCoreOS CoreOSCoreOS StabileStable più recentilatest

Creare un file di configurazione cloud-initCreate cloud-init config file

Per visualizzare cloud-init in azione, creare una macchina virtuale, installare NGINX ed eseguire una semplice app Node.js "Hello World".To see cloud-init in action, create a VM that installs NGINX and runs a simple 'Hello World' Node.js app. La configurazione cloud-init seguente installa i pacchetti necessari, crea un'applicazione Node.js, quindi inizializza e avvia l'applicazione.The following cloud-init configuration installs the required packages, creates a Node.js app, then initialize and starts the app.

Nella shell corrente creare un file denominato cloud-init.txt e incollare la configurazione seguente.In your current shell, create a file named cloud-init.txt and paste the following configuration. Ad esempio, creare il file in Cloud Shell anziché nel computer locale.For example, create the file in the Cloud Shell not on your local machine. È possibile usare qualsiasi editor.You can use any editor you wish. Immettere sensible-editor cloud-init.txt per creare il file e visualizzare un elenco degli editor disponibili.Enter sensible-editor cloud-init.txt to create the file and see a list of available editors. Assicurarsi che l'intero file cloud-init venga copiato correttamente, in particolare la prima riga: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

Per altre informazioni sulle opzioni di configurazione di cloud-init, vedere gli esempi di configurazione di cloud-init.For more information about cloud-init configuration options, see cloud-init config examples.

Crea macchina virtualeCreate virtual machine

Per poter creare una macchina virtuale è prima necessario creare un gruppo di risorse con il comando az group create.Before you can create a VM, create a resource group with az group create. Nell'esempio seguente viene creato un gruppo di risorse denominato myResourceGroupAutomate nella posizione eastus:The following example creates a resource group named myResourceGroupAutomate in the eastus location:

az group create --name myResourceGroupAutomate --location eastus

Creare quindi una macchina virtuale con il comando az vm create.Now create a VM with az vm create. Usare il parametro --custom-data per specificare il file di configurazione di cloud-init.Use the --custom-data parameter to pass in your cloud-init config file. Se il file è stato salvato all'esterno della directory di lavoro corrente, specificare il percorso completo della configurazione cloud-init.txt .Provide the full path to the cloud-init.txt config if you saved the file outside of your present working directory. L'esempio seguente crea una macchina virtuale denominata myAutomatedVM:The following example creates a VM named myAutomatedVM:

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

Per creare la macchina virtuale, installare i pacchetti e avviare l'applicazione sono necessari alcuni minuti.It takes a few minutes for the VM to be created, the packages to install, and the app to start. Sono presenti attività in background la cui esecuzione continua dopo che l'interfaccia della riga di comando di Azure è tornata al prompt.There are background tasks that continue to run after the Azure CLI returns you to the prompt. Potrebbe trascorrere ancora qualche minuto prima che sia possibile accedere all'app.It may be another couple of minutes before you can access the app. Dopo aver creato la macchina virtuale, prendere nota del publicIpAddress visualizzato dall'interfaccia della riga di comando di Azure.When the VM has been created, take note of the publicIpAddress displayed by the Azure CLI. Questo indirizzo viene usato per accedere all'app Node.js tramite un Web browser.This address is used to access the Node.js app via a web browser.

Per consentire al traffico Web di raggiungere la macchina virtuale, aprire la porta 80 da Internet con il 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 myVM

Testare l'app WebTest web app

È ora possibile aprire un Web browser e immettere http:// nella barra degli indirizzi.Now you can open a web browser and enter http:// in the address bar. Fornire il proprio indirizzo IP pubblico dal processo di creazione della macchina virtuale.Provide your own public IP address from the VM create process. L'app Node.js viene visualizzata come illustrato nell'esempio seguente:Your Node.js app is displayed as in the following example:

Visualizzare il sito NGINX in esecuzione

Inserire certificati da Key VaultInject certificates from Key Vault

Questa sezione facoltativa illustra come archiviare in modo protetto i certificati in Azure Key Vault e inserirli durante la distribuzione della macchina virtuale.This optional section shows how you can securely store certificates in Azure Key Vault and inject them during the VM deployment. Anziché usare un'immagine personalizzata che includa i certificati integrati, questo processo assicura che i certificati aggiornati vengano inseriti in una macchina virtuale al primo avvio.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 il processo, il certificato non lascia mai la piattaforma Azure e non viene mai esposto in uno script, in una cronologia della riga di comando o in un modello.During the process, the certificate never leaves the Azure platform or is exposed in a script, command-line history, or template.

Azure Key Vault consente di proteggere chiavi crittografiche e segreti, come certificati e password.Azure Key Vault safeguards cryptographic keys and secrets, such as certificates or passwords. Key Vault semplifica il processo di gestione delle chiavi e consente di mantenere il controllo delle chiavi che accedono ai dati e li crittografano.Key Vault helps streamline the key management process and enables you to maintain control of keys that access and encrypt your data. Questo scenario introduce alcuni concetti chiave di Key Vault per creare e usare un certificato, sebbene non rappresenti una panoramica esaustiva sull'uso di 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.

I passaggi seguenti mostrano come sia possibile:The following steps show how you can:

  • Creare un Azure Key VaultCreate an Azure Key Vault
  • Generare o caricare un certificato in Key VaultGenerate or upload a certificate to the Key Vault
  • Creare una chiave privata dal certificato da inserire in una macchina virtualeCreate a secret from the certificate to inject in to a VM
  • Creare una macchina virtuale e inserire il certificatoCreate a VM and inject the certificate

Creare un Azure Key VaultCreate an Azure Key Vault

Innanzitutto, creare un Key Vault con il comando az keyvault create e abilitarlo all'uso quando si distribuisce una macchina virtuale.First, create a Key Vault with az keyvault create and enable it for use when you deploy a VM. Ogni Key Vault deve avere un nome univoco in lettere minuscole.Each Key Vault requires a unique name, and should be all lower case. Nell'esempio seguente sostituire mykeyvault con il nome univoco del proprio 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

Generare certificati e archiviarli in Key VaultGenerate certificate and store in Key Vault

Per la produzione è necessario importare un certificato valido firmato da un provider attendibile con il comando az keyvault certificate import.For production use, you should import a valid certificate signed by trusted provider with az keyvault certificate import. Per questa esercitazione, l'esempio seguente illustra come sia possibile generare un certificato autofirmato con il comando az keyvault certificate create che usi i criteri dei certificati predefiniti: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)"

Preparare i certificati per l'uso con macchine virtualiPrepare certificate for use with VM

Per usare il certificato durante il processo di creazione della macchina virtuale, ottenere l'ID del certificato con il comando 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 macchina virtuale richiede che il certificato abbia un formato specifico per inserirlo all'avvio, quindi è necessario convertire il certificato con az vm format-secret.The VM needs the certificate in a certain format to inject it on boot, so convert the certificate with az vm format-secret. L'esempio seguente assegna l'output di questi comandi a delle variabili per semplificarne l'uso nei passaggi successivi: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 format-secret --secret "$secret")

Creare una configurazione cloud-init per proteggere NGINXCreate cloud-init config to secure NGINX

Quando si crea una macchina virtuale, certificati e chiavi vengono archiviati nella directory /var/lib/waagent/ protetta.When you create a VM, certificates and keys are stored in the protected /var/lib/waagent/ directory. Per automatizzare l'aggiunta del certificato alla macchina virtuale e la configurazione di NGINX, è possibile usare una configurazione di cloud-init aggiornata dall'esempio precedente.To automate adding the certificate to the VM and configuring NGINX, you can use an updated cloud-init config from the previous example.

Creare un file denominato cloud-init-secured.txt e incollare la configurazione seguente.Create a file named cloud-init-secured.txt and paste the following configuration. Anche in questo caso, se si usa Cloud Shell, creare il file di configurazione cloud-init in questa posizione e non nel computer locale.Again, if you use the Cloud Shell, create the cloud-init config file there and not on your local machine. Usare sensible-editor cloud-init-secured.txt per creare il file e visualizzare un elenco degli editor disponibili.Use sensible-editor cloud-init-secured.txt to create the file and see a list of available editors. Assicurarsi che l'intero file cloud-init venga copiato correttamente, in particolare la prima riga: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

Creare una macchina virtuale protettaCreate secure VM

Creare quindi una macchina virtuale con il comando az vm create.Now create a VM with az vm create. I dati del certificato sono inseriti da Key Vault con il parametro --secrets.The certificate data is injected from Key Vault with the --secrets parameter. Come nell'esempio precedente, si seleziona anche la configurazione cloud-init con il parametro --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 myVMSecured \
    --image UbuntuLTS \
    --admin-username azureuser \
    --generate-ssh-keys \
    --custom-data cloud-init-secured.txt \
    --secrets "$vm_secret"

Per creare la macchina virtuale, installare i pacchetti e avviare l'applicazione sono necessari alcuni minuti.It takes a few minutes for the VM to be created, the packages to install, and the app to start. Sono presenti attività in background la cui esecuzione continua dopo che l'interfaccia della riga di comando di Azure è tornata al prompt.There are background tasks that continue to run after the Azure CLI returns you to the prompt. Potrebbe trascorrere ancora qualche minuto prima che sia possibile accedere all'app.It may be another couple of minutes before you can access the app. Dopo aver creato la macchina virtuale, prendere nota del publicIpAddress visualizzato dall'interfaccia della riga di comando di Azure.When the VM has been created, take note of the publicIpAddress displayed by the Azure CLI. Questo indirizzo viene usato per accedere all'app Node.js tramite un Web browser.This address is used to access the Node.js app via a web browser.

Per consentire al traffico Web protetto di raggiungere la macchina virtuale, aprire la porta 443 da Internet con il 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 myVMSecured \
    --port 443

Testare l'applicazione Web protettaTest secure web app

È ora possibile aprire un Web browser e immettere https:// nella barra degli indirizzi.Now you can open a web browser and enter https:// in the address bar. Fornire il proprio indirizzo IP pubblico dal processo di creazione della macchina virtuale.Provide your own public IP address from the VM create process. Se è stato usato un certificato autofirmato, accettare l'avviso di sicurezza:Accept the security warning if you used a self-signed certificate:

Accettare l'avviso di sicurezza del Web browser

Il sito protetto NGINX e la app Node.js sono visualizzati come illustrato nell'esempio seguente:Your secured NGINX site and Node.js app is then displayed as in the following example:

Visualizzare il sito protetto NGINX in esecuzione

Passaggi successiviNext steps

In questa esercitazione vengono configurate macchine virtuali al primo avvio con cloud-init.In this tutorial, you configured VMs on first boot with cloud-init. Si è appreso come:You learned how to:

  • Creare un file di configurazione cloud-initCreate a cloud-init config file
  • Creare una macchina virtuale che usa un file cloud-initCreate a VM that uses a cloud-init file
  • Visualizzare un'esecuzione dell'app Node.js dopo aver creato la macchina virtualeView a running Node.js app after the VM is created
  • Usare Key Vault per archiviare in modo sicuro i certificatiUse Key Vault to securely store certificates
  • Automatizzare le distribuzioni sicure di NGINX con cloud-initAutomate secure deployments of NGINX with cloud-init

Passare all'esercitazione successiva per imparare a creare immagini di macchine virtuali personalizzate.Advance to the next tutorial to learn how to create custom VM images.