Revista Tecnología

Automatización de infraestructura en Proxmox con Ansible

Publicado el 05 febrero 2021 por Debadastra @jdaanial

En esta ocasión, nos centraremos en cómo automatizar despliegues de máquinas virtuales en una infraestructura on-premise operada con Proxmox. Usaremos Ansible tanto para comunicarnos con Proxmox como para hacer la configuración de la máquina después del despliegue.

Escenario previo

Automatización de infraestructura en Proxmox con Ansible

Para poder poner en práctica la automatización, es deseable tener configurado un escenario que cuente con VLANs configuradas, un servidor de DHCP en cada una de las VLANs y una zona DNS con actualización dinámica por DHCP (RFC 2136).

En nuestro caso, tenemos configurado Pfsense como firewall y servidor DHCP de las dos VLANs:

  • VLAN001: red de gestión donde se encontrarán los servicios publicados a todas las redes. En nuestro caso, solo necesitamos el servidor DNS con Bind9.
  • VLAN002: red de despliegue donde crearemos las nuevas máquinas.

Para mayor información sobre estas configuraciones, consultar los enlaces correspondientes:

Por último, debemos tener disponibles plantillas de máquinas virtuales. En nuestro caso, solo usaremos plantillas de Ubuntu y Debian. A partir de estas plantillas, el automatismo podrá generar las nuevas máquinas virtuales. Para más información, consultar el siguiente enlace.

Creación y borrado de máquinas virtuales con proxmox-ansible

Para esta automatización, hemos preparado el repositorio proxmox-ansible. Se trata de un role de Ansible que realiza acciones concretas en función de la variable action. Concretamente, este role permite realizar dos acciones que nos interesan en este momento:

  • create_vm : Clona de una máquina virtual a partir de una plantilla existente. Para más información, accede aquí.
  • delete_vm : Borra una máquina virtual. Para más información, accede aquí.

Para usar este role, tenemos dos opciones:

  • Clonar el repositorio en ~/.ansible/roles/ e instalar las dependencias que aparecen en el fichero requirements.txt.
  • Ejecutar el playbook desde la imagen de docker atorrescogollo/proxmox-ansible:latest.

En este caso, usaremos la imagen de docker del siguiente modo:

  1. Creamos el playbook create_vm.yml indicando la acción y los parámetros que requiere:
    $ cat create_vm.yml
    - name: Create VM
      hosts: localhost
      roles:
      - role: proxmox-ansible
        vars:
          action: create_vm
          proxmox_host: 10.0.0.2:8006
          proxmox_user: user@pam
          proxmox_pass: password
          vm_name: testvm01
          cpu_sockets: 1
          cpu_cores: 1
          ram_mb: 2048
          disk_gb: 20
          datastore: ds01
          vlan: 2
          template_name: TEMPLATE-UBUNTU-SERVER-20-04
          proxmox_node: proxmoxnode01
  2. Ejecutamos el role montando el fichero de playbook como un volumen:
    $ docker run --rm \
        -v "$PWD/create_vm.yml:/playbook.yml" \
        atorrescogollo/proxmox-ansible:latest

Por otro lado, el borrado de la máquina, se podría ejecutar de igual forma pero usando el playbook delete_vm.yml:

$ cat delete_vm.yml
- name: Delete VM
  hosts: localhost
  roles:
  - role: proxmox-ansible
    vars:
      action: delete_vm
      proxmox_host: 10.0.0.2:8006
      proxmox_user: user@pam
      proxmox_pass: password
      vm_name: testvm01
$ docker run --rm \
    -v "$PWD/delete_vm.yml:/playbook.yml" \
    atorrescogollo/proxmox-ansible:latest

Configuración tras despliegue con linux-ansible

Una vez ya podemos crear máquinas de forma automatizada, necesitamos realizar algunas configuraciones. Por ejemplo, queremos adecuar los volumenes lógicos de LVM, actualizar el nombre del host según el nombre de la máquina virtual, actualizar los paquetes de la máquina, etc.

Todas las configuraciones para máquinas Linux forman parte de otro role de Ansible disponible en el repositorio linux-ansible y, de igual modo, podemos configurar la máquina que acabamos de desplegar. El procedimiento, en este caso, es ligeramente distinto ya que necesitamos un inventario:

  1. Creamos el playbook post_deploy.yml:
    $ cat post_deploy.yml
    - name: Configure VM
      hosts: vms
      roles:
      - role: linux-ansible
        vars:
          action: post_deploy
          lvmap:
            "/tmp": "+500M"
            "/var/log": "2G"
            "/var": "+30%FREE"
            "/": "+100%FREE"
          install_packages:
          - vim
          - tmux
    Similar a lo que vimos anteriormente, estos parámetros se pueden consultar en este enlace. En esta documentación, además, se indica que la acción post_deploy simplemente es una agrupación de acciones, por lo que podemos personalizar nuestro despliegue en función de lo que necesitemos.
  2. Creamos el fichero de inventario:
    $ cat inventory.ini
    [vms]
    testvm01.example.org ansible_host=10.0.2.150
    
    [vms:vars]
    ansible_user=adminuser
    ansible_ssh_extra_args='-o StrictHostKeyChecking=no'
    Es importante definir la IP ya que la plantilla aún no tiene el hostname correcto por lo que el DNS no ha registrado ese hostname. Además, el usuario con el que nos vamos a conectar necesita tener acceso con sudo sin contraseña para realizar las tareas que requieren ciertos privilegios.
  3. Ejecutamos el role usando la imagen de docker atorrescogollo/linux-ansible:latest:
    $ ssh-add ~/.ssh/id_rsa # Cargar la clave privada en ssh-agent
    $ docker run -it --rm \
       -v $SSH_AUTH_SOCK:/ssh-agent \
       -e SSH_AUTH_SOCK=/ssh-agent  \
       -v $PWD/inventory.ini:/inventory      \
       -v $PWD/post_deploy.yml:/playbook.yml \
       atorrescogollo/linux-ansible:latest
    Cabe destacar que, en este caso, hemos tenido que compartir el ssh-agent con el contenedor a través de la variable de entorno SSH_AUTH_SOCK para poder usar la clave privada cargada con ssh-add. Para más información sobre esta característica, acceder a este enlace.

Conclusiones

Hemos logrado estandarizar el proceso de creación y configuración de máquinas virtuales. Esto nos permite definir políticas de bastionado, configuraciones comunes en todo el entorno, etc, que se aplicarán en todos los despliegues.

También, hemos propuesto un tratamiento distinto al modelo estándar de roles de Ansible. En este caso, cada role agrupa todas las automatizaciones realizacionadas con un ámbito concreto usando la variable action. Por ejemplo, proxmox-ansible es el role que trata todos los procedimientos de interacción con nuestro hipervisor y linux-ansible es el role que define todos los procedimientos de configuración de máquinas Linux.

Por otro lado, cabe mencionar que existen otros mecanismos para ejecutar la configuración de una máquina después del despliegue: suele ser la opción más usada. Esto no quiere decir que la fase de configuración de la máquina sea completamente reemplazable por cloud-init. Habiendo implementado el role linux-ansible tenemos dos posibilidades:

  • Ejecutar el role desde fuera de la máquina, como hemos presentado.
  • Ejecutar el role en local dentro de la máquina con cloud-init.

Por tanto, Ansible nos aporta, principalmente, dos beneficios con respecto a otras opciones:

  • Versatilidad en los modos de configuración: una vez se definen las tareas, solo hace falta indicar sobre qué máquinas ejecutar el automatismo.
  • Facilidad de mantenimiento: la complejidad debe residir en el módulo de Ansible (en la mayoría de casos, ya mantenido por la comunidad) para que las tareas, roles y playbooks sean fáciles de interpretar.

Sabiendo esto, ¿te atreves a automatizar tu infraestructura?

Álvaro Torres Cogollo.

Quieres contactar conmigo? Te dejo mis redes sociales a continuación.


Volver a la Portada de Logo Paperblog