Apuntes sobre Ansible

per Victor Carceler darrera modificació 2021-01-17T10:58:42+01:00

Ansible_logo.svg.pngAnsible es una herramienta libre que permite automatizar la administración de un conjunto de equipos. Toma el nombre de un dispositivo ficticio imaginado por Ursula K. Le Guin que permite la comunicación instantánea entre dos puntos del universo.

Nuestra herramienta utiliza SSH para establecer la comunicación con los hosts remotos que administra y no necesita que se instale en ellos ningún agente o software especial (únicamente Python que en el caso de GNU/Linux ya suele formar parte de la instalación).

Es suficiente con tener una máquina en la que esté instalado Ansible (empaquetado en los repositorios de las principales distribuciones) para controlar un parque informático de muchas máquinas. De hecho en el centro se utiliza una máquina virtual KVM con  el nombre de Baba-Yaga para mantener en el estado deseado todos los equipos de las diferentes aulas y departamentos. Así, por ejemplo, cuando se desea instalar un nuevo paquete o definir un nuevo usuario basta con añadir la tarea al playbook para que se lleve a cabo en todos aquellos equipos donde sea necesario.

Algunas de las características de Ansible son:

  • Mínimo por naturaleza. Basta con instalarlo en un equipo para controlar un gran parque de ordenadores.
  • Seguro. No necesita instalar ningún software en los agentes y únicamente utiliza OpenSSH.
  • Confiable. Ansible proporciona muchos módulos que realizan operaciones idempotentes.
  • Sencillo. Curva de aprendizaje suave en parte gracias a su completa documentación.

Ansible en el instituto

En el instituto hay diversas aulas informáticas, carros con portátiles y ordenadores en los departamentos. Todos estos equipos tienen instalado GNU/Linux y mantener su estado que exista determinado usuario con determinada contraseña, que esté instalado determinado paquete, que el nombre del host sea el adecuado, que cierto fichero de configuración incluya cierta directiva... exigiría un trabajo manual exhaustivo. Aún con la mejor de las intenciones y un numeroso equipo de personas revisando los ordenadores no evitaría inconsistencias.

Pero gracias a Ansible este trabajo se puede automatizar para que todos los equipos se encuentren en el estado deseado y, de no ser así, se lleven a cabo las acciones necesarias.

Normalmente la instalación de un ordenador en el centro se realiza en modo desatendido anteriormente se utilizó Clonezilla para restaurar una imagen arrancando con iPXE y deja configurada la autenticación con clave pública en SSH. De hecho la configuración del servicio OpenSSH está configurado para no aceptar más que la conexión de Ansible y no existe en los ordenadores ningún usuario capaz de utilizar sudo o su para convertirse en administrador.

Es decir, durante la instalación se añade al fichero /root/.ssh/authorized_keys las claves públicas de los usuarios que han de iniciar sesión. Por ejemplo:

root@dptinf-187:~# cat /root/.ssh/authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDS6jT/BT20rFrFLT1HcjoEDb6PAN8p5YgE1OtCEZcmhgqHlcqhX3643ikMny5YxIhqMB6lVQgQrwM3tMsx/aQU+WYbobBIkABK/ig/O8uP/R4vU7g9ihsFAVNWCviHUql43Jg1QJoJpU0m7IgofyWhFzIe/bvk/kxDblHFhDqzYL2P5ENdwivyEOS9vCV8LVesHwpJ7TgWgQMr4NRnEOW0uAGD8rgT2UtdJdh3jSwMo3+KM/MQ6RW4VZdoG/7MLm0U+ti8TF5ugd4Oeeth5vC2nq6I9OGS2foQEGllPMXmIsp0fMgw+QwMuJWpPSo08wjOINcI5ps2VBIFptBp6BtR vcarceler@baba-yaga
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDpngj3H/aI9pTQBGsqRGaqYzEQUYJ+SXy4jbkOZpEhfy71Xm83m9npoIuHcH8wGlzdN8xBIeRsC1LioLeBU4ZyzJGTrcpRLHVcfoV81ulETPbbXzcZ+pe29RY6zMl01Sg8KPUzORkB2Lb7OUPtVfss8q6UZR3g2x0AiuRST2jAqnJ692dIOZ/2+ILbEcrEqLFw9hmswlfEHzPL3kghRbADmFSzZu80TGB6yeOyiJ7LVz7O5l5qd9ZUA0KKOQ0mqHkloorI07Oimq1wquQnWpV608DMVUzdD9V4FUw8U8AYLC5x1V3iwxVjEJZImBQ2TK+cMNJHG52xxwIx/OHFtOAl q2dg@baba-yaga
root@dptinf-187:~#

Así cualquiera de estos dos usuarios de Baba-Yaga puede acceder como root mediante SSH a las máquinas. Evidentemente esta no es la única manera de configurar OpenSSH pero es una manera sencilla y conveniente de permitir que mi usuario (o el de q2dg) de Baba-Yaga pueda administrar remotamente cualquier máquina de cualquier aula.

Por supuesto en Baba-Yaga será necesario instalar Ansible.

ARA-logo.pngAunque no es un requisito imprescindible en Baba-Yaga también está instalada una aplicación ARA Records Ansible que registra la ejecución de cada playblook de Ansible para mostrar en una interfaz web en qué ordenadores se han hecho cambios, ha fallado alguna cosa, no se han encontrado encendidos, etc...

Componentes y filosofía de uso

Ansible utiliza algunos conceptos con los que conviene familiarizarse:

Inventario

El fichero inventario por defecto /etc/ansible/hosts lista los equipos que se van a gestionar. Además permite agrupar los ordenadores indicando un nombre de grupo o especificar rangos para no tener que escribir la dirección de todos los ordenadores.

Después se puede lanzar un playbook de Ansible en un ordenador, un grupo de ordenadores o todos aquellos equipos que coincidan con un patrón.

Un fichero inventario de ejemplo puede ser:

[profesores]
192.168.10.100
192.168.11.100
192.168.12.100
192.168.14.100

[torvalds]
192.168.10.[100:123]

[servidores]
servidor1.elpuig.xeill.net
servidor2.elpuig.xeill.net
servidor[10:20].elpuig.xeill.net

Donde se aprecian los grupos profesores, torvalds y servidores. Se puede comprobar que se puede indicar la IP del equipo o bien el nombre DNS y que es posible utilizar rangos para especificar múltiples equipos.

Módulo

Ansible permite hacer prácticamente cualquier gestión en los ordenadores controlados. Las operaciones concretas (instalar un paquete, dar de alta un usuario, copiar un fichero) están agrupadas en módulos con una función común.

El índice de módulos es muy grande y probablemente encontraremos todos lo que estemos buscando pero en el improbable caso de que no exista el módulo que buscamos es bastante sencillo escribir uno nuevo.

Por ejemplo:

Una característica importante es que todas las funciones de un módulo deben tener un comportamiento idempotente. Esto quiere decir que Ansible invocará la función del módulo cada vez que se ejecute el playbook pero la función únicamente debe provocar cambios en el ordenador controlado si el estado en el que se encuentra no coincide con el estado deseado.

Playbook

Los playbooks son ficheros YAML que enumeran las tareas que deben realizarse en los equipos administrados.

Cuando se ejecuta un playbook Ansible:

- Intenta conectar con cada uno de los ordenadores.

- Recoge información —los llamados facts— sobre cada uno de los equipos.

- Lanza de manera simultánea la primera tarea en cada uno de los ordenadores y espera a que se complete resultando:

- No es necesario hacer ningún cambio.

- Se ha realizado la tarea provocando un cambio.

- Se ha producido un error.

- Los equipos que no contestan, pierden la conexión o provocan un error dejan de tenerse en cuenta.

- Cuando todos los equipos restantes han completado la tarea se lanza la siguiente tarea del playbook hasta que se llega a su fin.

Se pueden ver algunos de los playbooks utilizados en el centro.

Un ejemplo de playbook puede ser el fichero /home/usuario/playbook-ejemplo.yml:

---
- hosts: equipos
  user: root

  tasks:
          - name: Instala lolcat
            apt:
                    name: lolcat
                    state: present

          - name: Hace apt update e instala una lista de paquetes. ipcalc, net-tools, glances
            apt:
                    update_cache: yes
                    pkg:
                            - ipcalc
                            - net-tools
                            - glances

En este playbook se puede apreciar:

  • Que se va a aplicar al grupo equipos definido en el inventario.
  • Que se va a intentar conectar con el usuario root con cada uno de los equipos.
  • Se declaran dos tareas.
    • La primera instala lolcat (si no está instalado)
    • La segunda tiene una lista de paquetes (ipcalc, net-tools, glances) que instalará si no están instalados. Además antes de comenzar la instalación se realizará un apt update.
  • Cada una de las tareas puede:
    • No realizar nada si el host ya se encuentra en el estado especificado.
    • Aplicar el cambio para llevar el host hasta el estado especificado.
    • Provocar un error si, por ejemplo, no se puede descargar el paquete o falla la instalación.

El playbook se podrá lanzar con el comando:

usuario@ansible:~$ ansible-playbook playbook-ejemplo.yml

Cuando se lanza un playbook de Ansible:

  • Se intenta conectar con cada uno de los hosts. Los equipos que no contestan son descartados.
  • Se recogen los facts de cada uno de los hosts.
  • Para cada una de las tareas definidas, de manera secuencial (tarea a tarea):
    • Se comprueba el estado de cada host
    • Si es necesario se aplica el cambio
    • Se recoge el resultado: sin cambios, cambios, error.
  • Finalmente se muestra un informe con los resultados de la ejecución del playbook.

Un posible resultado de la ejecución del playbook anterior podría ser:

usuario@ansible:~$ time ansible-playbook playbook-ejemplo.yml 

PLAY [equipos] *********************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************************
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}
ok: [192.168.1.201]
ok: [192.168.1.202]

TASK [Instala lolcat] **************************************************************************************************************************************************************************************
ok: [192.168.1.201]
changed: [192.168.1.202]

TASK [Hace apt update e instala una lista de paquetes. ipcalc, net-tools, glances] *************************************************************************************************************************
changed: [192.168.1.201]
changed: [192.168.1.202]

PLAY RECAP *************************************************************************************************************************************************************************************************
192.168.1.201              : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.1.202              : ok=3    changed=2    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   


real	1m18,922s
user	0m11,562s
sys	0m2,985s
usuario@ansible:~$

Facts

En los playbooks se pueden utilizar variables definidas por el usuario o extraídas a partir de las propiedades del host (los llamados facts).

Por ejemplo el siguiente playbook puede fijar el hostname de la máquina y el contenido del fichero /etc/hosts de acuerdo a:

  • La variable base_hostname especificada en el playbook
  • El fact ansible_default_ipv4.address

Combinando el nombre especificado por el administrador (en el ejemplo superhost) con el último dígitio de la dirección IP para formar un hostname tal que: superhost-201, superhost-202, ...

Fichero cambiahostname.yml:

---
- hosts: equipos
  user: root

  vars:
          base_hostname: superhost

  tasks:
          - name: Configura hostname a partir de la variable base_hostname y la IP
            hostname: name={{ base_hostname }}-{{ ansible_default_ipv4.address.split('.')[3] }}

          - name: Actualiza /etc/hosts con el nuevo hostname
            replace:
                    dest: /etc/hosts
                    regexp: '^127\.0\.1\.1.+$'
                    replace: "127.0.1.1\t{{ base_hostname }}-{{ ansible_default_ipv4.address.split('.')[3] }}"

Puede utilizarse directamente ansible con el módulo setup para obtener todos los facts de un equipo:

usuario@ansible:~$ ansible -u root -m setup 192.168.1.201

Lo que proporciona algo similar a:

192.168.1.201 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.1.201"
        ],
        "ansible_all_ipv6_addresses": [
            "2a0c:5a84:3300:e500:a00:27ff:fe64:b344",
            "fe80::a00:27ff:fe64:b344"
        ],
        "ansible_apparmor": {
            "status": "enabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "12/01/2006",
        "ansible_bios_version": "VirtualBox",
        "ansible_cmdline": {
            "BOOT_IMAGE": "/boot/vmlinuz-5.4.0-28-generic",
            "debian-installer/language": "es",
            "keyboard-configuration/layoutcode?": "es",
            "ro": true,
            "root": "UUID=318a984c-9707-4f75-8b6e-f4ef56523a88"
        },
        "ansible_date_time": {
            "date": "2020-05-02",
            "day": "02",
            "epoch": "1588414464",
            "hour": "10",
            "iso8601": "2020-05-02T10:14:24Z",
            "iso8601_basic": "20200502T101424366657",
            "iso8601_basic_short": "20200502T101424",
            "iso8601_micro": "2020-05-02T10:14:24.366741Z",
            "minute": "14",
            "month": "05",
            "second": "24",
            "time": "10:14:24",
            "tz": "UTC",
            "tz_offset": "+0000",
            "weekday": "sábado",
            "weekday_number": "6",
            "weeknumber": "17",
            "year": "2020"
        },
        "ansible_default_ipv4": {
            "address": "192.168.1.201",
            "alias": "enp0s3",
            "broadcast": "192.168.1.255",
            "gateway": "192.168.1.1",
            "interface": "enp0s3",
            "macaddress": "08:00:27:64:b3:44",
            "mtu": 1500,
            "netmask": "255.255.255.0",
            "network": "192.168.1.0",
            "type": "ether"
        },
        "ansible_default_ipv6": {
            "address": "2a0c:5a84:3300:e500:a00:27ff:fe64:b344",
            "gateway": "fe80::1",
            "interface": "enp0s3",
            "macaddress": "08:00:27:64:b3:44",
            "mtu": 1500,
            "prefix": "64",
            "scope": "global",
            "type": "ether"
        },
        "ansible_device_links": {
            "ids": {
                "sda": [
                    "ata-VBOX_HARDDISK_VB1a71aea8-6f0aa4ab",
                    "scsi-0ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab",
                    "scsi-1ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab",
                    "scsi-SATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab"
                ],
                "sda1": [
                    "ata-VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part1",
                    "scsi-0ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part1",
                    "scsi-1ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part1",
                    "scsi-SATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part1"
                ],
                "sda2": [
                    "ata-VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part2",
                    "scsi-0ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part2",
                    "scsi-1ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part2",
                    "scsi-SATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part2"
                ],
                "sr0": [
                    "ata-VBOX_CD-ROM_VB2-01700376"
                ]
            },
            "labels": {},
            "masters": {},
            "uuids": {
                "sda2": [
                    "318a984c-9707-4f75-8b6e-f4ef56523a88"
                ]
            }
        },
        "ansible_devices": {
            "loop0": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "192352",
                "sectorsize": "512",
                "size": "93.92 MB",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "loop1": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "112528",
                "sectorsize": "512",
                "size": "54.95 MB",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "loop2": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "112536",
                "sectorsize": "512",
                "size": "54.95 MB",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "loop3": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "137792",
                "sectorsize": "512",
                "size": "67.28 MB",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "loop4": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "141248",
                "sectorsize": "512",
                "size": "68.97 MB",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "loop5": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "141528",
                "sectorsize": "512",
                "size": "69.11 MB",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "loop6": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "55480",
                "sectorsize": "512",
                "size": "27.09 MB",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "loop7": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "120",
                "sectorsize": "512",
                "size": "60.00 KB",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "loop8": {
                "holders": [],
                "host": "",
                "links": {
                    "ids": [],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": null,
                "partitions": {},
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "0",
                "sectorsize": "512",
                "size": "0.00 Bytes",
                "support_discard": "4096",
                "vendor": null,
                "virtual": 1
            },
            "sda": {
                "holders": [],
                "host": "SATA controller: Intel Corporation 82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode] (rev 02)",
                "links": {
                    "ids": [
                        "ata-VBOX_HARDDISK_VB1a71aea8-6f0aa4ab",
                        "scsi-0ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab",
                        "scsi-1ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab",
                        "scsi-SATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "VBOX HARDDISK",
                "partitions": {
                    "sda1": {
                        "holders": [],
                        "links": {
                            "ids": [
                                "ata-VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part1",
                                "scsi-0ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part1",
                                "scsi-1ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part1",
                                "scsi-SATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part1"
                            ],
                            "labels": [],
                            "masters": [],
                            "uuids": []
                        },
                        "sectors": "2048",
                        "sectorsize": 512,
                        "size": "1.00 MB",
                        "start": "2048",
                        "uuid": null
                    },
                    "sda2": {
                        "holders": [],
                        "links": {
                            "ids": [
                                "ata-VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part2",
                                "scsi-0ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part2",
                                "scsi-1ATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part2",
                                "scsi-SATA_VBOX_HARDDISK_VB1a71aea8-6f0aa4ab-part2"
                            ],
                            "labels": [],
                            "masters": [],
                            "uuids": [
                                "318a984c-9707-4f75-8b6e-f4ef56523a88"
                            ]
                        },
                        "sectors": "20965376",
                        "sectorsize": 512,
                        "size": "10.00 GB",
                        "start": "4096",
                        "uuid": "318a984c-9707-4f75-8b6e-f4ef56523a88"
                    }
                },
                "removable": "0",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "20971520",
                "sectorsize": "512",
                "serial": "VB1a71aea8",
                "size": "10.00 GB",
                "support_discard": "0",
                "vendor": "ATA",
                "virtual": 1
            },
            "sr0": {
                "holders": [],
                "host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)",
                "links": {
                    "ids": [
                        "ata-VBOX_CD-ROM_VB2-01700376"
                    ],
                    "labels": [],
                    "masters": [],
                    "uuids": []
                },
                "model": "CD-ROM",
                "partitions": {},
                "removable": "1",
                "rotational": "1",
                "sas_address": null,
                "sas_device_handle": null,
                "scheduler_mode": "mq-deadline",
                "sectors": "2097151",
                "sectorsize": "512",
                "size": "1024.00 MB",
                "support_discard": "0",
                "vendor": "VBOX",
                "virtual": 1
            }
        },
        "ansible_distribution": "Ubuntu",
        "ansible_distribution_file_parsed": true,
        "ansible_distribution_file_path": "/etc/os-release",
        "ansible_distribution_file_variety": "Debian",
        "ansible_distribution_major_version": "20",
        "ansible_distribution_release": "focal",
        "ansible_distribution_version": "20.04",
        "ansible_dns": {
            "nameservers": [
                "127.0.0.53"
            ],
            "options": {
                "edns0": true
            }
        },
        "ansible_domain": "",
        "ansible_effective_group_id": 0,
        "ansible_effective_user_id": 0,
        "ansible_enp0s3": {
            "active": true,
            "device": "enp0s3",
            "features": {
                "esp_hw_offload": "off [fixed]",
                "esp_tx_csum_hw_offload": "off [fixed]",
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "off [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "off [fixed]",
                "netns_local": "off [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off",
                "rx_checksumming": "off",
                "rx_fcs": "off",
                "rx_gro_hw": "off [fixed]",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "rx_vlan_filter": "on [fixed]",
                "rx_vlan_offload": "on",
                "rx_vlan_stag_filter": "off [fixed]",
                "rx_vlan_stag_hw_parse": "off [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tls_hw_record": "off [fixed]",
                "tls_hw_rx_offload": "off [fixed]",
                "tls_hw_tx_offload": "off [fixed]",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "on",
                "tx_checksum_ipv4": "off [fixed]",
                "tx_checksum_ipv6": "off [fixed]",
                "tx_checksum_sctp": "off [fixed]",
                "tx_checksumming": "on",
                "tx_esp_segmentation": "off [fixed]",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_ipxip4_segmentation": "off [fixed]",
                "tx_ipxip6_segmentation": "off [fixed]",
                "tx_lockless": "off [fixed]",
                "tx_nocache_copy": "off",
                "tx_scatter_gather": "on",
                "tx_scatter_gather_fraglist": "off [fixed]",
                "tx_sctp_segmentation": "off [fixed]",
                "tx_tcp6_segmentation": "off [fixed]",
                "tx_tcp_ecn_segmentation": "off [fixed]",
                "tx_tcp_mangleid_segmentation": "off",
                "tx_tcp_segmentation": "on",
                "tx_udp_segmentation": "off [fixed]",
                "tx_udp_tnl_csum_segmentation": "off [fixed]",
                "tx_udp_tnl_segmentation": "off [fixed]",
                "tx_vlan_offload": "on [fixed]",
                "tx_vlan_stag_hw_insert": "off [fixed]",
                "vlan_challenged": "off [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "192.168.1.201",
                "broadcast": "192.168.1.255",
                "netmask": "255.255.255.0",
                "network": "192.168.1.0"
            },
            "ipv6": [
                {
                    "address": "2a0c:5a84:3300:e500:a00:27ff:fe64:b344",
                    "prefix": "64",
                    "scope": "global"
                },
                {
                    "address": "fe80::a00:27ff:fe64:b344",
                    "prefix": "64",
                    "scope": "link"
                }
            ],
            "macaddress": "08:00:27:64:b3:44",
            "module": "e1000",
            "mtu": 1500,
            "pciid": "0000:00:03.0",
            "promisc": false,
            "speed": 1000,
            "timestamping": [
                "tx_software",
                "rx_software",
                "software"
            ],
            "type": "ether"
        },
        "ansible_env": {
            "DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/0/bus",
            "HOME": "/root",
            "LANG": "es_ES.UTF-8",
            "LOGNAME": "root",
            "MOTD_SHOWN": "pam",
            "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games",
            "PWD": "/root",
            "SHELL": "/bin/bash",
            "SHLVL": "0",
            "SSH_CLIENT": "192.168.1.200 60472 22",
            "SSH_CONNECTION": "192.168.1.200 60472 192.168.1.201 22",
            "SSH_TTY": "/dev/pts/0",
            "TERM": "xterm-256color",
            "USER": "root",
            "XDG_RUNTIME_DIR": "/run/user/0",
            "XDG_SESSION_CLASS": "user",
            "XDG_SESSION_ID": "7",
            "XDG_SESSION_TYPE": "tty",
            "_": "/bin/sh"
        },
        "ansible_fibre_channel_wwn": [],
        "ansible_fips": false,
        "ansible_form_factor": "Other",
        "ansible_fqdn": "superhost-201",
        "ansible_hostname": "superhost-201",
        "ansible_hostnqn": "",
        "ansible_interfaces": [
            "enp0s3",
            "lo"
        ],
        "ansible_is_chroot": false,
        "ansible_iscsi_iqn": "iqn.1993-08.org.debian:01:8a7fa9c0e017",
        "ansible_kernel": "5.4.0-28-generic",
        "ansible_kernel_version": "#32-Ubuntu SMP Wed Apr 22 17:40:10 UTC 2020",
        "ansible_lo": {
            "active": true,
            "device": "lo",
            "features": {
                "esp_hw_offload": "off [fixed]",
                "esp_tx_csum_hw_offload": "off [fixed]",
                "fcoe_mtu": "off [fixed]",
                "generic_receive_offload": "on",
                "generic_segmentation_offload": "on",
                "highdma": "on [fixed]",
                "hw_tc_offload": "off [fixed]",
                "l2_fwd_offload": "off [fixed]",
                "large_receive_offload": "off [fixed]",
                "loopback": "on [fixed]",
                "netns_local": "on [fixed]",
                "ntuple_filters": "off [fixed]",
                "receive_hashing": "off [fixed]",
                "rx_all": "off [fixed]",
                "rx_checksumming": "on [fixed]",
                "rx_fcs": "off [fixed]",
                "rx_gro_hw": "off [fixed]",
                "rx_udp_tunnel_port_offload": "off [fixed]",
                "rx_vlan_filter": "off [fixed]",
                "rx_vlan_offload": "off [fixed]",
                "rx_vlan_stag_filter": "off [fixed]",
                "rx_vlan_stag_hw_parse": "off [fixed]",
                "scatter_gather": "on",
                "tcp_segmentation_offload": "on",
                "tls_hw_record": "off [fixed]",
                "tls_hw_rx_offload": "off [fixed]",
                "tls_hw_tx_offload": "off [fixed]",
                "tx_checksum_fcoe_crc": "off [fixed]",
                "tx_checksum_ip_generic": "on [fixed]",
                "tx_checksum_ipv4": "off [fixed]",
                "tx_checksum_ipv6": "off [fixed]",
                "tx_checksum_sctp": "on [fixed]",
                "tx_checksumming": "on",
                "tx_esp_segmentation": "off [fixed]",
                "tx_fcoe_segmentation": "off [fixed]",
                "tx_gre_csum_segmentation": "off [fixed]",
                "tx_gre_segmentation": "off [fixed]",
                "tx_gso_partial": "off [fixed]",
                "tx_gso_robust": "off [fixed]",
                "tx_ipxip4_segmentation": "off [fixed]",
                "tx_ipxip6_segmentation": "off [fixed]",
                "tx_lockless": "on [fixed]",
                "tx_nocache_copy": "off [fixed]",
                "tx_scatter_gather": "on [fixed]",
                "tx_scatter_gather_fraglist": "on [fixed]",
                "tx_sctp_segmentation": "on",
                "tx_tcp6_segmentation": "on",
                "tx_tcp_ecn_segmentation": "on",
                "tx_tcp_mangleid_segmentation": "on",
                "tx_tcp_segmentation": "on",
                "tx_udp_segmentation": "off [fixed]",
                "tx_udp_tnl_csum_segmentation": "off [fixed]",
                "tx_udp_tnl_segmentation": "off [fixed]",
                "tx_vlan_offload": "off [fixed]",
                "tx_vlan_stag_hw_insert": "off [fixed]",
                "vlan_challenged": "on [fixed]"
            },
            "hw_timestamp_filters": [],
            "ipv4": {
                "address": "127.0.0.1",
                "broadcast": "host",
                "netmask": "255.0.0.0",
                "network": "127.0.0.0"
            },
            "ipv6": [
                {
                    "address": "::1",
                    "prefix": "128",
                    "scope": "host"
                }
            ],
            "mtu": 65536,
            "promisc": false,
            "timestamping": [
                "tx_software",
                "rx_software",
                "software"
            ],
            "type": "loopback"
        },
        "ansible_local": {},
        "ansible_lsb": {
            "codename": "focal",
            "description": "Ubuntu 20.04 LTS",
            "id": "Ubuntu",
            "major_release": "20",
            "release": "20.04"
        },
        "ansible_lvm": {
            "lvs": {},
            "pvs": {},
            "vgs": {}
        },
        "ansible_machine": "x86_64",
        "ansible_machine_id": "a23736ffdca54b188f3fcd4f6d62ce9e",
        "ansible_memfree_mb": 353,
        "ansible_memory_mb": {
            "nocache": {
                "free": 753,
                "used": 228
            },
            "real": {
                "free": 353,
                "total": 981,
                "used": 628
            },
            "swap": {
                "cached": 0,
                "free": 1961,
                "total": 1961,
                "used": 0
            }
        },
        "ansible_memtotal_mb": 981,
        "ansible_mounts": [
            {
                "block_available": 1057421,
                "block_size": 4096,
                "block_total": 2563141,
                "block_used": 1505720,
                "device": "/dev/sda2",
                "fstype": "ext4",
                "inode_available": 531212,
                "inode_total": 655360,
                "inode_used": 124148,
                "mount": "/",
                "options": "rw,relatime",
                "size_available": 4331196416,
                "size_total": 10498625536,
                "uuid": "318a984c-9707-4f75-8b6e-f4ef56523a88"
            },
            {
                "block_available": 0,
                "block_size": 131072,
                "block_total": 752,
                "block_used": 752,
                "device": "/dev/loop0",
                "fstype": "squashfs",
                "inode_available": 0,
                "inode_total": 12857,
                "inode_used": 12857,
                "mount": "/snap/core/9066",
                "options": "ro,nodev,relatime",
                "size_available": 0,
                "size_total": 98566144,
                "uuid": "N/A"
            },
            {
                "block_available": 0,
                "block_size": 131072,
                "block_total": 440,
                "block_used": 440,
                "device": "/dev/loop1",
                "fstype": "squashfs",
                "inode_available": 0,
                "inode_total": 10765,
                "inode_used": 10765,
                "mount": "/snap/core18/1705",
                "options": "ro,nodev,relatime",
                "size_available": 0,
                "size_total": 57671680,
                "uuid": "N/A"
            },
            {
                "block_available": 0,
                "block_size": 131072,
                "block_total": 440,
                "block_used": 440,
                "device": "/dev/loop2",
                "fstype": "squashfs",
                "inode_available": 0,
                "inode_total": 10764,
                "inode_used": 10764,
                "mount": "/snap/core18/1754",
                "options": "ro,nodev,relatime",
                "size_available": 0,
                "size_total": 57671680,
                "uuid": "N/A"
            },
            {
                "block_available": 0,
                "block_size": 131072,
                "block_total": 539,
                "block_used": 539,
                "device": "/dev/loop3",
                "fstype": "squashfs",
                "inode_available": 0,
                "inode_total": 9866,
                "inode_used": 9866,
                "mount": "/snap/jupyter/6",
                "options": "ro,nodev,relatime",
                "size_available": 0,
                "size_total": 70647808,
                "uuid": "N/A"
            },
            {
                "block_available": 0,
                "block_size": 131072,
                "block_total": 552,
                "block_used": 552,
                "device": "/dev/loop4",
                "fstype": "squashfs",
                "inode_available": 0,
                "inode_total": 1465,
                "inode_used": 1465,
                "mount": "/snap/lxd/14804",
                "options": "ro,nodev,relatime",
                "size_available": 0,
                "size_total": 72351744,
                "uuid": "N/A"
            },
            {
                "block_available": 0,
                "block_size": 131072,
                "block_total": 553,
                "block_used": 553,
                "device": "/dev/loop5",
                "fstype": "squashfs",
                "inode_available": 0,
                "inode_total": 1465,
                "inode_used": 1465,
                "mount": "/snap/lxd/14890",
                "options": "ro,nodev,relatime",
                "size_available": 0,
                "size_total": 72482816,
                "uuid": "N/A"
            },
            {
                "block_available": 0,
                "block_size": 131072,
                "block_total": 217,
                "block_used": 217,
                "device": "/dev/loop6",
                "fstype": "squashfs",
                "inode_available": 0,
                "inode_total": 459,
                "inode_used": 459,
                "mount": "/snap/snapd/7264",
                "options": "ro,nodev,relatime",
                "size_available": 0,
                "size_total": 28442624,
                "uuid": "N/A"
            },
            {
                "block_available": 0,
                "block_size": 131072,
                "block_total": 1,
                "block_used": 1,
                "device": "/dev/loop7",
                "fstype": "squashfs",
                "inode_available": 0,
                "inode_total": 17,
                "inode_used": 17,
                "mount": "/snap/vitetris/1",
                "options": "ro,nodev,relatime",
                "size_available": 0,
                "size_total": 131072,
                "uuid": "N/A"
            }
        ],
        "ansible_nodename": "superhost-201",
        "ansible_os_family": "Debian",
        "ansible_pkg_mgr": "apt",
        "ansible_proc_cmdline": {
            "BOOT_IMAGE": "/boot/vmlinuz-5.4.0-28-generic",
            "debian-installer/language": "es",
            "keyboard-configuration/layoutcode?": "es",
            "ro": true,
            "root": "UUID=318a984c-9707-4f75-8b6e-f4ef56523a88"
        },
        "ansible_processor": [
            "0",
            "GenuineIntel",
            "Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz"
        ],
        "ansible_processor_cores": 1,
        "ansible_processor_count": 1,
        "ansible_processor_threads_per_core": 1,
        "ansible_processor_vcpus": 1,
        "ansible_product_name": "VirtualBox",
        "ansible_product_serial": "0",
        "ansible_product_uuid": "797ec5e6-c568-4185-b125-8e0153f31aa3",
        "ansible_product_version": "1.2",
        "ansible_python": {
            "executable": "/usr/bin/python3",
            "has_sslcontext": true,
            "type": "cpython",
            "version": {
                "major": 3,
                "micro": 2,
                "minor": 8,
                "releaselevel": "final",
                "serial": 0
            },
            "version_info": [
                3,
                8,
                2,
                "final",
                0
            ]
        },
        "ansible_python_version": "3.8.2",
        "ansible_real_group_id": 0,
        "ansible_real_user_id": 0,
        "ansible_selinux": {
            "status": "Missing selinux Python library"
        },
        "ansible_selinux_python_present": false,
        "ansible_service_mgr": "systemd",
        "ansible_ssh_host_key_dsa_public": "AAAAB3NzaC1kc3MAAACBALWMMldPsiOdXPQkzxt6ddtbnxNpC1u3X7UmJbJ+8fQf37kXRM+P2f48zCdmr3upRnZGGPRAJp96UixODiFwu3sbOaxON3evVgJHPo5CwHVE0U9etVGtHmYcasYLB2jigjN+Vv4szQBmp8eCgdrKxTLLsaWw7YGOeRUAlXCM22GJAAAAFQC8++dCMnJMW0RSD/1Vwlj8bLXJxQAAAIArHZQ7S8Srce0DpCDz9SyEKOL4wHIk2D1RMTP2QJEs/C/nFwfDH6DAfxlvUaOupczfxc/DjMx4Y2z/wKnc1sVOFBD1dXjTDuyTt04lFFIstKTQRnr96fJF5fgPV5gbIptVqRQqFgJAsUprF8EntVDpKoYHztI0NCJtCgy1jhVNRQAAAIEAlQVt5vBnbrexesmEEyIsZ8S9MDvNlAB3Xz7E7qhBTFPcXmXdzXXpgHuAHbjk6GeKdFD2JuJwgF/5QzXKnAklhvnh9q8v0giR7TOAgtImz1DnxGOrF5qAaKiqgNAvLehwoqLCr6qDX6o1LG/vvlOHrHq5J1jO6Z14erC49TdNz+I=",
        "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPfmA8qxx8Rx4ARfuJR2os9tLy9lNZrZl53O2i+75l9yARc8IWO3TZDxVcsaDVp33mwLIkHKlQM1iRR/ptYdyt0=",
        "ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIEgE8uqKKGb1V90aiWjj6H/417sKWCIgesCECM/nQeDm",
        "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABgQDW56OYNV4FG81Smek2CBmSp9BWqBnQ25B4XEOnqPc7jZ4JEj9S4jZSHV7wX5u3wIEKf5r8vFym+a7vWU34Q+Tc+K1NEtU+Wn3TYPqXrWW/ZbvwFkE2s946o1x3OJ277NllFeLGg/+ntI0tOCeXs2Bo6SQO2OjIYhaQypLLabLTnumirpoBZp+1ds7xmx4YfGQk2fA9+z9KesAzaWfxgsqB1c2wO/9CCq0CVef9S5b19HObfzRoN24IQXQbFUMWWYgEWQEHVaCjis8SZdBuDVMawPieVWjO6/RoDhsDicnmd8ZrHbwA7OW2VoaSqG5Nsqbxm7zKrlbrc7YCz90M1mcfk2PKQ/ktDeDenpEd4U1iXTYqnobIB/OsT8mpB7ufQGuLJegy//W4Ps8LjiklOqwIavw89U05rDADFexzBsm8IfnCcC6nYK7lJVbfPR1ygWzT2zYxVRfI+xoN6hghB2iuYNQ3ovMUi3Nw7zx401X9kBJ/WDtyPX6SXTyyuVwE0/M=",
        "ansible_swapfree_mb": 1961,
        "ansible_swaptotal_mb": 1961,
        "ansible_system": "Linux",
        "ansible_system_capabilities": [],
        "ansible_system_capabilities_enforced": "False",
        "ansible_system_vendor": "innotek GmbH",
        "ansible_uptime_seconds": 1964,
        "ansible_user_dir": "/root",
        "ansible_user_gecos": "root",
        "ansible_user_gid": 0,
        "ansible_user_id": "root",
        "ansible_user_shell": "/bin/bash",
        "ansible_user_uid": 0,
        "ansible_userspace_architecture": "x86_64",
        "ansible_userspace_bits": "64",
        "ansible_virtualization_role": "guest",
        "ansible_virtualization_type": "virtualbox",
        "discovered_interpreter_python": "/usr/bin/python3",
        "gather_subset": [
            "all"
        ],
        "module_setup": true
    },
    "changed": false
}

Más información: