Ansible: include dinámico por host
En el centro se utiliza Ansible para administrar los equipos informáticos. Sin esta herramienta sería imposible mantener a todo el parque informático en un estado coherente y adaptado a la función que debe cumplir. Gracias a esta herramienta es posible definir el estado en el que se deben encontrar las máquinas y ella aplicará los cambios necesarios en el conjunto de máquinas especificado de manera automática.
Se pueden consultar los playbooks que utilizamos este curso en el repositorio: https://github.com/vcarceler/playbooks-ubuntu2004
La idea básica es que en el fichero inventario
se declaran conjuntos de equipos. Y en el playbook
se declaran tareas que se deben aplicar en esos equipos. Cada tarea utiliza un módulo idempotente que únicamente provoca cambios en el ordenador si es necesario.
Durante la ejecución del playbook
Ansible se encarga de conectar con todos los equipos y orquestar en ellos los cambios necesarios para llevarlos hasta el estado deseado. En los playbooks
se pueden utilizar variables, bucles, condiciones, handlers
y otros elementos que aportan una gran flexibilidad.
Caso práctico: configurar una VPN en muchos ordenadores portátiles
Durante este curso se espera una dotación de ordenadores portátiles para los alumnos y profesores. Estos equipos se utilizarán tanto en el centro como fuera así que se necesita una manera de conectar con ellos para administrarlos con Ansible y monitorizarlos con Prometheus que no dependa del lugar en el que se encuentran.
La solución es utilizar una VPN para que todos los portátiles tengan una interfaz de red con una IP conocida independientemente de donde se encuentren. Afortunadamente utilizar WireGuard resulta muy sencillo y este curso se han implementado diferentes VLANs:
- Una VLAN para los portátiles que se utilizarán en el centro y fuera del centro.
- Una VLAN por cada grupo clase de informática para que las máquinas virtuales que utilizan los alumnos mantengan la conectividad estén en el aula, en su casa o en un proveedor de la nube.
Se puede leer sobre WireGuard y las VPNs utilizadas en el centro en los siguientes artículos:
Así la configuración de una VPN con WireGuard en uno de los portátiles del centro incluye:
- Instalación del paquete
wireguard-tools
. - Configuración en el fichero
/etc/wireguard/wg0.conf
que incluye los siguientes parámetros particulares para cada portátil:- Clave privada del equipo.
- IP a utilizar en la VPN.
- Activado y encendido del servicio
wg-quick@wg0
.
Todas estas tareas se van a realizar automáticamente utilizando Ansible y en este caso particular hay un detalle interesante: por razones de seguridad no se desea que los datos de la VPN de cada equipo (clave privada e IP) acaben en el repositorio de control de versiones. Ni siquiera en su forma cifrada, pues Ansible Vault permite cifrar estos datos.
Hack: include dinámico por host
Es decir se desea tener un playbook
para todos los portátiles pero que configure la VPN de una manera particular en cada uno de ellos. Y que los datos de esta configuración estén en otro fichero que se incluya en el playbook
para cada uno de los equipos.
Así será posible:
- Añadir al fichero
.gitignore
el directoriovpn/
para que su contenido no acabe en el repositorio público. - Escribir los ficheros particulares para cada portátil a medida que se añadan máquinas a este sistema.
Y la solución es tan sencilla como utilizar la variable ansible_host
para componer dinámicamente el nombre del fichero particular a incluir en el playbook
.
--- - hosts: equipos user: root tasks: - name: Instala wireguard-tools apt: update_cache: yes pkg: - wireguard-tools - include: "vpn/{{ ansible_host }}.yml"
La variable especial de Ansible ansible_host
contiene la IP del equipo concreto y permite, para ese equipo, hacer un include
concreto —como por ejemplo vpn/192.168.1.201.yml
— que tendrá las tareas particulares para configurar la VPN en ese equipo.
Se puede comprobar en la ejecución del playbook
que el include
particular se realiza para cada host.
PLAY [equipos] ******************************************************************************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************************************ ok: [192.168.1.201] ok: [192.168.1.202] TASK [Instala wireguard-tools] **************************************************************************************************************************************************************************** ok: [192.168.1.202] ok: [192.168.1.201] TASK [include] ******************************************************************************************************************************************************************************************** included: /home/usuario/playbooks/vpn/192.168.1.201.yml for 192.168.1.201 included: /home/usuario/playbooks/vpn/192.168.1.202.yml for 192.168.1.202 TASK [Prueba de hostname] ********************************************************************************************************************************************************************************* ok: [192.168.1.201] TASK [Prueba de hostname] ********************************************************************************************************************************************************************************* changed: [192.168.1.202] PLAY RECAP ************************************************************************************************************************************************************************************************ 192.168.1.201 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.1.202 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Relación de direcciones LAN-VPN
Cuando se preparan equipos nuevos la ejecución del playbook
es especialmente larga debido a la gran cantidad de software que se instala. Esta tarea conviene realizarla, si es posible, con el equipo conectado a la red cableada del centro. Así será necesario especificar la relación entre la IP que tiene el equipo en la LAN del centro y la IP que tendrá el equipo en la VPN.
Una de las maneras de especificar esta relación puede ser utilizando variables en el fichero inventory
:
[equipos]
192.168.1.201 vpn=10.0.0.101
192.168.1.202 vpn=10.0.0.102
192.168.1.203 vpn=10.0.0.103
A las que se accederá en el playbook
de la siguiente manera:
--- - hosts: equipos user: root vars: tasks: - name: Instala wireguard-tools apt: update_cache: yes pkg: - wireguard-tools - include: "vpn/{{ vpn }}.yml"
Produciendo la siguiente ejecución:
PLAY [equipos] ******************************************************************************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************************************ ok: [192.168.1.201] ok: [192.168.1.202] fatal: [192.168.1.203]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.1.203 port 22: No route to host", "unreachable": true} TASK [Instala wireguard-tools] **************************************************************************************************************************************************************************** ok: [192.168.1.202] changed: [192.168.1.201] TASK [include] ******************************************************************************************************************************************************************************************** included: /home/usuario/playbooks/vpn/10.0.0.101.yml for 192.168.1.201 included: /home/usuario/playbooks/vpn/10.0.0.102.yml for 192.168.1.202 TASK [Prepara /etc/wireguard/wg0.conf] ******************************************************************************************************************************************************************** ok: [192.168.1.201] TASK [Activa la VPN wg0 (enable y start)] ***************************************************************************************************************************************************************** changed: [192.168.1.201] TASK [Prepara /etc/wireguard/wg0.conf] ******************************************************************************************************************************************************************** ok: [192.168.1.202] TASK [Activa la VPN wg0 (enable y start)] ***************************************************************************************************************************************************************** ok: [192.168.1.202] PLAY RECAP ************************************************************************************************************************************************************************************************ 192.168.1.201 : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.1.202 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.1.203 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
Tareas para configurar la VPN
En el interior del directorio vpn/
se encuentran las tareas que configuran la VPN para cada equipo. Aquí unos scripts habrán dejado un fichero .yml
para cada equipo. Por ejemplo para el equipo 10.0.0.101.yml
el fichero será:
- name: Prepara /etc/wireguard/wg0.conf vars: privatekey: CLAVEPRIVADADELEQUIPO address: 10.0.0.101/20 template: src: templates/vpn-control.j2 dest: /etc/wireguard/wg0.conf owner: root group: root mode: 0400 - name: Activa la VPN wg0 (enable y start) systemd: name: wg-quick@wg0 enabled: yes state: started
La primera tarea prepara el fichero de configuración /etc/wireguard/wg0.conf
para el equipo a partir del template vpn/templates/vpn-control.j2
que contiene:
[Interface]
PrivateKey = {{ privatekey }}
Address = {{ address }}
[Peer]
Endpoint = ENDPOINT:PORT
PublicKey = CLAVEPÚBLICADELSERVIDOR
AllowedIPs = 10.0.0.0/20
PersistentKeepalive = 25
La segunda tarea, Activa la VPN wg0 (enable y start)
, como su nombre indica utiliza el módulo systemd
para activar y enciender la VPN en el equipo. Esta segunda tarea podría estar en el playbook
inicial, fuera del include
, ejecutándose en paralelo en los diferentes equipos.