Ansible en Nube ARSAT: lo básico para empezar
===
### ¿Qué es Ansible?
Ansible es una herramienta de automatización de TI que permite gestionar, configurar y desplegar aplicaciones en servidores de manera eficiente. Simplifica tareas repetitivas y asegura la coherencia en la configuración de los sistemas. Gracias a su enfoque agente-less y su compatibilidad con SSH, Ansible se adapta perfectamente a entornos dinámicos, incluyendo instancias en la nube como las que se crean en nuestra plataforma, donde puede integrarse de forma natural para automatizar desde el aprovisionamiento hasta la operación continua.
### Conceptos
* **Inventario:** es un archivo en el cual se listan los nodos (servidores) que vamos a gestionar. Puede ser un archivo estático en formato *.ini o *.yml, o puede ser generado a partir de un script. En nuestro caso de uso, podría ser una máquina virtual o un conjunto de máquinas virtuales creadas en nuestro servicio IaaS.
<pre style="white-space: pre-wrap;">
mi_inventario.ini
[webservers]
VM1-web1 ansible_host=IP_VM/hostname_real ansible_user=usuario
VM2-web2 ansible_host=IP_VM/hostname_real ansible_user=usuario
[dbservers]
VM3-db1 ansible_host=IP_VM/hostname_real ansible_user=usuario
VM4-db2 ansible_host=IP_VM/hostname_real ansible_user=usuario
</pre>
Respecto al "ansible_user=usuario", el usuario va a ser el que utilicemos en las VMs destino para poder utilizar ansible en las mismas. El mismo tiene que contar con permisos necesarios para ejecutar los comandos que enviemos.
* **Módulos y Playbooks:**
Los módulos son pequeños programas que Ansible ejecuta en los nodos gestionados para realizar tareas específicas, como instalar software, gestionar usuarios o configurar servicios.
Ejemplos:
<pre style="white-space: pre-wrap;">
# ansible all -i inventario.ini -m ping 8.8.8.8
</pre>
En este ejemplo ejecutamos el comando "ping 8.8.8.8" en todos los nodos gestionados a partir del archivo "inventario.ini".
<pre style="white-space: pre-wrap;">
# ansible all -i inventario.ini -m apt -a "name=nginx state=present" -b
</pre>
En este ejemplo:
- ansible all -i inventario.ini: se refiere a que la tarea se ejecutará en todos los hosts definidos en el inventario "inventario.ini".
- -m apt: especifica el módulo "apt"
- -a "name=nginx state=present: pasa los argumentos al módulo.
- -b: para ejecutar la tarea con privelegios de superusuario.
Con este comando instalaríamos nginx en todos los host del inventario.
Por otro lado, los Playbooks son archivos en formato .yml que son capaces de contener tareas a ejecutar en nodos específicos. Cada tarea en un playbook puede utilizar uno o más módulos para realizar determinadas acciones.
Entonces...
Los módulos son las herramientas con las que Ansible realiza acciones, mientras que los playbooks son guiones que orquestan esas acciones en una secuencia lógica y organizada
* **SSH:** Ansible utiliza SSH para conectarse a los nodos gestionados. Para esto es necesario configurar las claves SSH para que Ansible pueda conectarse automáticamente a los nodos.
```
Ejemplo de generación y copia de clave SSH:
ssh-keygen -t rsa
ssh-copy-id usuario@host
```
* Comandos Ad Hoc: Los comandos ad hoc son comandos de Ansible que se ejecutan en tiempo real para realizar tareas rápidas y específicas sin necesidad de escribir un playbook.
```
Ejemplo de comando ad hoc para reiniciar servidores:
# ansible all -i inventario.ini -a "reboot"
```
### Resumen
* Automatización y Consistencia: Evita errores manuales y asegura que todos los nodos estén configurados de manera uniforme.
* Sin Agentes: Solo requiere acceso SSH, lo que simplifica la gestión de nodos.
* Escalabilidad: Puede gestionar desde unos pocos hasta miles de nodos.
* Flexibilidad: Compatible con diversas plataformas y entornos, incluyendo la nube.
Ansible permite a los administradores de sistemas y desarrolladores gestionar grandes infraestructuras de manera eficiente y efectiva, automatizando tareas y garantizando consistencia en toda la red.
### Primeros Pasos
:::info
**1 - Instalación de Ansible**
:::
En nuestro caso vamos a estar utilizando una instancia con Debian 12 creada en la Nube ARSAT.
* Actualizar Debian para asegurarnos de tener disponible la última version de Ansible
```
# sudo apt update
# sudo apt upgrade -y
```
* Instalación de Ansible y verificación
```
# sudo apt install ansible -y
# ansible --version
```
:::info
**2 - Como usar ansible con la Nube ARSAT**
:::
* Para poder utilizar Ansible con el motor de orquestación de la Nube ARSAT (Apache Cloudstack) necesitamos instalar "pip", el mismo es un gestor de paquetes escritos en python:
```
# sudo apt install python3-pip
```
* Luego instalamos el módulo para interactuar con Cloudstack:
```
# pip3 install cs
```
* Para poder utilizar los modulos de Ansible para Cloudstack, tenemos que instalar Ansible Collection "ngine_io.cloudstack", que es un plugin que agrupa módulos para poder trabajar con Cloudstack:
<pre style="white-space: pre-wrap;"># ansible-galaxy collection install ngine_io.cloudstack
</pre>
Para más detalles puede consultarse la documentación oficial en el siguiente link:
<sup>:information_source:</sup> https://docs.ansible.com/ansible/latest/collections/ngine_io/cloudstack.
:::info
**3 - Uso de Ansible para despliegue de VMs**
:::
* Creo la estructura de archivos para referencia de los trabajos a realizar, en este caso voy a comenzar con la Nube de Arsat.
<pre style="white-space: pre-wrap;">
# mkdir -p /home/ansible/nube-basica/template-test
</pre>
* Creo el archivo que va a contener los datos para poder conectarme via api con mi cuenta de dominio en la Nube de Arsat.
<pre style="white-space: pre-wrap;">
# nano cs_temp_test.yml
cs_api_url: "https://cloud.arsat.com.ar/client/api"
cs_api_key: "api-key-de-dominio"
cs_api_secret: "secret-key-de-dominio"
</pre>
* Como estos datos son propios de mi cuenta en el dominio, vamos a encriptarlos utilizando ansible-vault
```
# ansible-vault encrypt cs_temp_test.yml
```
y para desencriptarlo utilizamos:
```
# ansible-vault decrypt cs_temp_test.yml
```
asignamos una contraseña y listo, vamos a poder usar estos datos como variables globales para otros archivos.
Tambien puedo guardar la contraseña de encriptacion en un archivo y utilizarla desde ahi para no tener que recordarla o usarla cada vez que la necesite.
Para esto creo un archivo vault-password que contenga la contraseña de desenciptación
```
# nano vault-password
# chmod 600 vault-pass
```
Luego
```
# ansible-playbook cs_temp_test.yml --vault-password-file vault-password
```
Entonces... para poder usar un playbook con archivos cifrados lo hacemos con:
````
# ansible-playbook cs_temp_test.yml --ask-vault-pass
````
o también con:
```
# ansible-playbook cs_temp_test.yml --vault-password-file vault-password
```
* Pruebo primer despliegue de una VM Debian 12 de nombre "test-ansible"
```
# nano vm-test-ansible.yml
```
completo con:
```
# En este primer despliegue con Ansible voy a crear 1 VM: test-ansible
- name: Instanciar una VM Debian 12 utilizando ansible
hosts: localhost
vars_files:
- /home/ansible/nube-basica/template-test/cs_temp_test.yml
tasks:
- name: Despliegue de primer VM
ngine_io.cloudstack.cs_instance:
name: "test-ansible"
service_offering: "id de oferta de computa elegida"
template: Debian 12 x64 (vSphere)
zone: Sala 1
network: net-ansible-test
display_name: "test-ansible"
api_url: "{{ cs_api_url }}"
api_key: "{{ cs_api_key }}"
api_secret: "{{ cs_api_secret }}"
api_timeout: 20
```
:::info
:information_source: **INFO**
**Un poco de descripción de este primer playbook**
* **name:** cada vez que aparece "name" hace referencia al nombre del playbook, del task o de lo que vamos a crear, sea VM, template, red, etc.
* **host:** localhost hace referencia a que la tarea se va a ejecutar de forma local donde tengamos instalado ansible. Este parámetro podría utilizar un archivo que especfique nodos destino donde va a aplicarse la tarea a realizar, como el ejemplo de "mi_inventario.ini" del principio.
* **vars_file:** la ruta del archivo que va a contener las variables a utilizar en la tarea a realizar.
* **task:** es la tarea que va a realizar.
* **ngine_io.cloudstack.cs_instance:** Es el módulo que permite generar instancias con el plugin "ngine_io.cloudstack".
Hay módulos para generar reglas de firewall, portforwarding, templates, vpc, etc, etc, etc.
* Apartir de aquí todo lo que sigue son parámetros propios del módulo que elijamos según la tarea que querramos realizar, verificar la documentación para cada módulo.
:::
Ejecutamos el siguiente comando para realizar el despliegue de la VM "test-ansible" en mi dominio:
```
# ansible-playbook vm-test-ansible.yml --vault-password-file vault-pass
```
* Verificamos el despliegue de la misma
```
# ansible-playbook vm-test-ansible.yml --vault-password-file vault-pass
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Desplegar dos VMs] *************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************
ok: [localhost]
TASK [Despliegue de primer VM] *******************************************************************************************
changed: [localhost]
PLAY RECAP ***************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
```
:::success
:+1: VM instanciada, verificar en cloudstack.
:::
**Otra forma de realizar el despliegue de la VM es con el comando:**
```
# ansible-playbook vm-test-ansible.yml -vvvv --vault-password-file vault-pass
```
donde "-vvvv" activa el modo verbose en su nivel más detallado, mostrando en pantalla todo el proceso de ejecución paso a paso. Ansible permite ajustar el nivel de verbosidad desde -v (mínimo detalle) hasta -vvvv (máximo detalle), lo que resulta útil para depuración, aprendizaje o auditoría del playbook, sin alterar el resultado final de la ejecución.
###### Tags: `acs` `cloudstack` `ansible`