Creare una macchina virtuale Windows in Azure usando Ansible

Questo articolo illustra come distribuire una macchina virtuale Windows Server 2019 in Azure con Ansible.

In questo articolo vengono illustrate le operazioni seguenti:

  • Creare un gruppo di risorse
  • Creare una rete virtuale, un indirizzo IP pubblico, un gruppo di sicurezza di rete e un'interfaccia di rete
  • Distribuire una macchina virtuale Windows Server
  • Connessione alla macchina virtuale tramite WinRM
  • Eseguire un playbook ansible per configurare Windows IIS

Prerequisiti

  • Sottoscrizione di Azure: se non si ha una sottoscrizione di Azure, creare un account gratuito prima di iniziare.
  • Entità servizio di Azure: creare un'entità servizio, prendere nota dei valori seguenti: appId, displayName, password e tenant.

Aggiungere il supporto WinRM ad Ansible

Per comunicare tramite WinRM, il server di controllo Ansible richiede il pacchetto pywinrmPython .

Eseguire il comando seguente nel server Ansible per installare pywinrm:

pip install "pywinrm>=0.3.0"

Per altre informazioni, vedere Gestione remota Windows per Ansible.

Creare un gruppo di risorse

Creare un playbook Ansible denominato azure_windows_vm.yml e copiare il contenuto seguente nel playbook:

---
- name: Create Azure VM
  hosts: localhost
  connection: local
  tasks:

  - name: Create resource group
    azure_rm_resourcegroup:
      name: myResourceGroup
      location: eastus

Punti principali:

  • Impostazione su hostslocalhost e connection come _local_ esegue il playbook in locale nel server Ansible.

Creare la rete virtuale e la subnet

Aggiungere le attività seguenti al azure_windows_vm.yml playbook ansible per creare una rete virtuale:

  - name: Create virtual network
    azure_rm_virtualnetwork:
      resource_group: myResourceGroup
      name: vNet
      address_prefixes: "10.0.0.0/16"

  - name: Add subnet
    azure_rm_subnet:
      resource_group: myResourceGroup
      name: subnet
      address_prefix: "10.0.1.0/24"
      virtual_network: vNet

Creare un indirizzo IP pubblico

Aggiungere le attività seguenti al azure_windows_vm.yml playbook per creare un indirizzo IP pubblico:

  - name: Create public IP address
    azure_rm_publicipaddress:
      resource_group: myResourceGroup
      allocation_method: Static
      name: pip
    register: output_ip_address

  - name: Output public IP
    debug:
      msg: "The public IP is {{ output_ip_address.state.ip_address }}"

Punti principali:

  • Il modulo Ansible register viene usato per archiviare l'output da azure_rm_publicipaddress in una variabile denominata output_ip_address.
  • Il debug modulo viene usato per restituire l'indirizzo IP pubblico della macchina virtuale nella console.

Creare un gruppo di sicurezza di rete e una scheda di interfaccia di rete

Il gruppo di sicurezza di rete definisce il traffico consentito e non è consentito raggiungere la macchina virtuale.

Per aprire le porte WinRM e HTTP, aggiungere le attività seguenti al azure_windows_vm.yml playbook ansible:

  - name: Create Network Security Group
    azure_rm_securitygroup:
      resource_group: myResourceGroup
      name: networkSecurityGroup
      rules:
        - name: 'allow_rdp'
          protocol: Tcp
          destination_port_range: 3389
          access: Allow
          priority: 1001
          direction: Inbound
        - name: 'allow_web_traffic'
          protocol: Tcp
          destination_port_range:
            - 80
            - 443
          access: Allow
          priority: 1002
          direction: Inbound
        - name: 'allow_powershell_remoting'
          protocol: Tcp
          destination_port_range: 
            - 5985
            - 5986
          access: Allow
          priority: 1003
          direction: Inbound

  - name: Create a network interface
    azure_rm_networkinterface:
      name: nic
      resource_group: myResourceGroup
      virtual_network: vNet
      subnet_name: subnet
      security_group: networkSecurityGroup
      ip_configurations:
        - name: default
          public_ip_address_name: pip
          primary: True

Punti principali:

  • Una scheda di interfaccia di rete virtuale connette la macchina virtuale alla rete virtuale, all'indirizzo IP pubblico e al gruppo di sicurezza.
  • azure_rm_securitygroup Crea un gruppo di sicurezza di rete di Azure per consentire il traffico WinRM dal server Ansible all'host remoto consentendo la porta 5985 e 5986.

Creare una macchina virtuale

Creare quindi una macchina virtuale che usa tutte le risorse create nelle sezioni precedenti di questo articolo.

Aggiungere l'attività seguente al azure_windows_vm.yml playbook ansible:

  - name: Create VM
    azure_rm_virtualmachine:
      resource_group: myResourceGroup
      name: win-vm
      vm_size: Standard_DS1_v2
      admin_username: azureuser
      admin_password: "{{ password }}"
      network_interfaces: nic
      os_type: Windows
      image:
          offer: WindowsServer
          publisher: MicrosoftWindowsServer
          sku: 2019-Datacenter
          version: latest
    no_log: true

Il admin_password valore di {{ password }} è una variabile Ansible che contiene la password della macchina virtuale Windows. Per popolare in modo sicuro tale variabile, aggiungere una var_prompts voce all'inizio del playbook.

- name: Create Azure VM
  hosts: localhost
  connection: local
  vars_prompt:
    - name: password
      prompt: "Enter local administrator password"
  tasks:

Punti principali:

  • Evitare di archiviare dati sensibili come testo normale. Usare var_prompts per popolare le variabili in fase di esecuzione. Aggiungere no_log: true per impedire che le password vengano registrati.

Configurare il listener WinRM

Ansible usa PowerShell per connettersi e configurare host remoti Di Windows tramite WinRM.

Per configurare WinRM, aggiungere quanto segue:azure_rm_virtualmachineextension

  - name: Create VM script extension to enable HTTPS WinRM listener
    azure_rm_virtualmachineextension:
      name: winrm-extension
      resource_group: myResourceGroup
      virtual_machine_name: win-vm
      publisher: Microsoft.Compute
      virtual_machine_extension_type: CustomScriptExtension
      type_handler_version: '1.9'
      settings: '{"fileUris": ["https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"],"commandToExecute": "powershell -ExecutionPolicy Unrestricted -File ConfigureRemotingForAnsible.ps1"}'
      auto_upgrade_minor_version: true

Ansible non può connettersi alla macchina virtuale fino a quando WinRM non è completamente configurato.

Aggiungere le attività seguenti al playbook per attendere la connessione WinRM:

  - name: Get facts for one Public IP
    azure_rm_publicipaddress_info:
      resource_group: myResourceGroup
      name: pip
    register: publicipaddresses

  - name: set public ip address fact
    set_fact: publicipaddress="{{ publicipaddresses | json_query('publicipaddresses[0].ip_address')}}"

  - name: wait for the WinRM port to come online
    wait_for:
      port: 5986
      host: '{{ publicipaddress }}'
      timeout: 600

Punti principali:

  • Il azure_rm_virtualmachineextension modulo consente di eseguire uno script di PowerShell in locale in Windows di Azure. L'esecuzione dello ConfigureRemotingForAnsible.ps1 script di PowerShell configura WinRM creando certificati autofirmato e aprendo le porte necessarie per la connessione di Ansible.
  • Il azure_rm_publicipaddress_info modulo esegue una query sull'indirizzo IP pubblico da Azure e quindi set_fact archivia l'output in una variabile da usare per il wait_for modulo.

Playbook Ansible di esempio completo

In questa sezione è riportato l'intero playbook Ansible che è stato creato durante l'esercitazione presentata in questo articolo.

---
- name: Create Azure VM
  hosts: localhost
  connection: local
  vars_prompt:
    - name: password
      prompt: "Enter local administrator password"
  tasks:

  - name: Create resource group
    azure_rm_resourcegroup:
      name: myResourceGroup
      location: eastus

  - name: Create virtual network
    azure_rm_virtualnetwork:
      resource_group: myResourceGroup
      name: vNet
      address_prefixes: "10.0.0.0/16"

  - name: Add subnet
    azure_rm_subnet:
      resource_group: myResourceGroup
      name: subnet
      address_prefix: "10.0.1.0/24"
      virtual_network: vNet

  - name: Create public IP address
    azure_rm_publicipaddress:
      resource_group: myResourceGroup
      allocation_method: Static
      name: pip
    register: output_ip_address

  - name: Output public IP
    debug:
      msg: "The public IP is {{ output_ip_address.state.ip_address }}"
  
  - name: Create Network Security Group
    azure_rm_securitygroup:
      resource_group: myResourceGroup
      name: networkSecurityGroup
      rules:
        - name: 'allow_rdp'
          protocol: Tcp
          destination_port_range: 3389
          access: Allow
          priority: 1001
          direction: Inbound
        - name: 'allow_web_traffic'
          protocol: Tcp
          destination_port_range:
            - 80
            - 443
          access: Allow
          priority: 1002
          direction: Inbound
        - name: 'allow_powershell_remoting'
          protocol: Tcp
          destination_port_range: 
            - 5985
            - 5986
          access: Allow
          priority: 1003
          direction: Inbound

  - name: Create a network interface
    azure_rm_networkinterface:
      name: nic
      resource_group: myResourceGroup
      virtual_network: vNet
      subnet_name: subnet
      security_group: networkSecurityGroup
      ip_configurations:
        - name: default
          public_ip_address_name: pip
          primary: True

  - name: Create VM
    azure_rm_virtualmachine:
      resource_group: myResourceGroup
      name: win-vm
      vm_size: Standard_DS1_v2
      admin_username: azureuser
      admin_password: "{{ password }}"
      network_interfaces: nic
      os_type: Windows
      image:
          offer: WindowsServer
          publisher: MicrosoftWindowsServer
          sku: 2019-Datacenter
          version: latest
    no_log: true

  - name: Create VM script extension to enable HTTPS WinRM listener
    azure_rm_virtualmachineextension:
      name: winrm-extension
      resource_group: myResourceGroup
      virtual_machine_name: win-vm
      publisher: Microsoft.Compute
      virtual_machine_extension_type: CustomScriptExtension
      type_handler_version: '1.9'
      settings: '{"fileUris": ["https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"],"commandToExecute": "powershell -ExecutionPolicy Unrestricted -File ConfigureRemotingForAnsible.ps1"}'
      auto_upgrade_minor_version: true

  - name: Get facts for one Public IP
    azure_rm_publicipaddress_info:
      resource_group: myResourceGroup
      name: pip
    register: publicipaddresses

  - name: set public ip address fact
    set_fact: publicipaddress="{{ publicipaddresses | json_query('publicipaddresses[0].ip_address')}}"

  - name: wait for the WinRM port to come online
    wait_for:
      port: 5986
      host: '{{ publicipaddress }}'
      timeout: 600

Connessione alla macchina virtuale Windows

Creare un nuovo playbook Ansible denominato connect_azure_windows_vm.yml e copiare il contenuto seguente nel playbook:

---
- hosts: all
  vars_prompt:
    - name: ansible_password
      prompt: "Enter local administrator password"
  vars:
    ansible_user: azureuser
    ansible_connection: winrm
    ansible_winrm_transport: ntlm
    ansible_winrm_server_cert_validation: ignore
  tasks:

  - name: Test connection
    win_ping:

Eseguire il playbook ansible.

ansible-playbook connect_azure_windows_vm.yml -i <publicIPaddress>,

Sostituire <publicIPaddress> con l'indirizzo della macchina virtuale.

Punti principali:

  • La configurazione di Ansible determina la modalità di connessione e autenticazione di Ansible agli host remoti. Le variabili da definire per connettersi a un host Windows dipendono dal tipo di connessione WinRM e dall'opzione di autenticazione scelta. Per altre informazioni, vedere Connessione a un host Windows e opzioni di autenticazione di Windows.
  • L'aggiunta di una virgola dopo che l'indirizzo IP pubblico ignora il parser di inventario di Ansible. Questa tecnica consente di eseguire playbook senza un file di inventario.

Pulire le risorse

  1. Salvare il codice seguente come delete_rg.yml.

    ---
    - hosts: localhost
      tasks:
        - name: Deleting resource group - "{{ name }}"
          azure_rm_resourcegroup:
            name: "{{ name }}"
            state: absent
          register: rg
        - debug:
            var: rg
    
  2. Eseguire il playbook usando il comando ansible-playbook. Sostituire il segnaposto con il nome del gruppo di risorse da eliminare. Tutte le risorse presenti nel gruppo di risorse verranno eliminate.

    ansible-playbook delete_rg.yml --extra-vars "name=<resource_group>"
    

    Punti principali:

    • A causa della variabile e debug della register sezione del playbook, i risultati vengono visualizzati al termine del comando.

Passaggi successivi