Créer une machine virtuelle Windows dans Azure à l’aide d’Ansible

Cet article explique comment déployer une machine virtuelle Windows Server 2019 dans Azure avec Ansible.

Dans cet article, vous apprendrez comment :

  • Créer un groupe de ressources
  • Créer un réseau virtuel, adresse IP publique, groupe de sécurité réseau et interface réseau
  • Déployer une machine virtuelle Windows Server
  • Se connecter à la machine virtuelle avec WinRM
  • Exécuter un playbook Ansible pour configurer Windows IIS

Prérequis

  • Abonnement Azure : Si vous n’avez pas d’abonnement Azure, créez un compte gratuit avant de commencer.

Ajouter la prise en charge de WinRM à Ansible

Pour communiquer sur WinRM, le serveur de contrôle Ansible a besoin du package Python pywinrm.

Exécutez la commande suivante sur le serveur Ansible pour installer pywinrm :

pip install "pywinrm>=0.3.0"

Pour plus d’informations, consultez Windows Remote Management pour Ansible.

Créer un groupe de ressources

Créez un playbook Ansible nommé azure_windows_vm.yml et copiez le contenu suivant dans le playbook :

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

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

Points essentiels :

  • Définir hosts sur localhost et connection exécuter _local_ le playbook localement sur le serveur Ansible.

Créer le réseau virtuel et le sous-réseau

Ajoutez les tâches suivantes au azure_windows_vm.yml playbook Ansible pour créer un réseau virtuel :

  - 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

Créer une adresse IP publique

Ajoutez les tâches suivantes au azure_windows_vm.yml playbook pour créer une adresse IP publique :

  - 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 }}"

Points essentiels :

  • Le module register Ansible est utilisé pour stocker la sortie de azure_rm_publicipaddress dans une variable appelée output_ip_address.
  • Le debug module est utilisé pour générer l’adresse IP publique de la machine virtuelle dans la console.

Créer un groupe de sécurité réseau et une carte réseau

Le groupe de sécurité réseau définit le trafic qui est autorisé ou non à atteindre la machine virtuelle.

Pour ouvrir les ports WinRM et HTTP, ajoutez les tâches suivantes au playbook Ansible azure_windows_vm.yml :

  - 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

Points essentiels :

  • Une carte réseau virtuelle connecte votre machine virtuelle à son réseau virtuel, son adresse IP publique et son groupe de sécurité.
  • azure_rm_securitygroup crée un groupe de sécurité réseau Azure pour autoriser le trafic WinRM du serveur Ansible jusqu’à l’hôte distant en autorisant les ports 5985 et 5986.

Création d'une machine virtuelle

Ensuite, créez une machine virtuelle qui utilise toutes les ressources que vous avez créées dans les sections précédentes de cet article.

Ajoutez la tâche suivante au playbook Ansible azure_windows_vm.yml :

  - 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

La valeur admin_password de {{ password }} est une variable Ansible qui contient le mot de passe de la machine virtuelle Windows. Pour remplir de manière sécurisée cette variable, ajoutez une entrée var_prompts au début du playbook.

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

Points essentiels :

  • Évitez de stocker des données sensibles sous forme de texte brut. Utilisez var_prompts pour remplir les variables au moment de l’exécution. Ajoutez no_log: true pour empêcher la journalisation des mots de passe.

Configurer l’écouteur WinRM

Ansible utilise PowerShell pour connecter et configurer des hôtes distants Windows avec WinRM.

Pour configurer WinRM, ajoutez l’extension 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 ne peut pas se connecter à la machine virtuelle tant que WinRM n’est pas entièrement configuré.

Ajoutez les tâches suivantes à votre playbook pour attendre la connexion 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

Points essentiels :

  • Le module azure_rm_virtualmachineextension vous permet d’exécuter un script PowerShell localement sur Windows Azure. L’exécution du script PowerShell ConfigureRemotingForAnsible.ps1 configure WinRM en créant des certificats auto-signés et en ouvrant les ports nécessaires pour qu’Ansible se connecte.
  • Le module azure_rm_publicipaddress_info demande l’adresse IP publique à Azure, puis set_fact stocke la sortie dans une variable exploitable par le module wait_for.

Exemple de playbook Ansible complet

Cette section présente l’exemple de playbook Ansible complet que vous avez élaboré dans le cadre de cet article.

---
- 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

Se connecter à la machine virtuelle Windows

Créez un playbook Ansible nommé connect_azure_windows_vm.yml et copiez le contenu suivant dans le 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:

Exécutez le playbook Ansible.

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

Remplacez <publicIPaddress> par l’adresse de votre machine virtuelle.

Points essentiels :

  • La configuration d’Ansible détermine la façon dont Ansible se connecte aux hôtes distants et s’authentifie auprès d’eux. Les variables que vous devez définir pour la connexion à un hôte Windows dépendent de votre type de connexion WinRM et de l’option d’authentification que vous avez choisie. Pour plus d’informations, consultez Connexion à un hôte Windows et Options d’authentification Windows.
  • L’ajout d’une virgule après l’adresse IP publique contourne l’analyseur d’inventaire Ansible. Cette technique vous permet d’exécuter des playbooks sans fichier d’inventaire.

Nettoyer les ressources

  1. Enregistrez le code suivant en tant que delete_rg.yml.

    ---
    - hosts: localhost
      tasks:
        - name: Deleting resource group - "{{ name }}"
          azure_rm_resourcegroup:
            name: "{{ name }}"
            state: absent
          register: rg
        - debug:
            var: rg
    
  2. Exécutez le playbook en utilisant la commande ansible-playbook. Remplacez l’espace réservé par le nom du groupe de ressources à supprimer. Toutes les ressources du groupe de ressources seront supprimées.

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

    Points essentiels :

    • En raison de la variable register et de la section debug du playbook, les résultats s’affichent quand la commande se termine.

Étapes suivantes