Tutoriales

Cómo crear un archivo de inventario dinámico en Ansible

Si usa Ansible, sabe que el inventario es uno de sus componentes fundamentales. Un inventario es solo una lista de máquinas y posibles variables en las que puede ejecutar su libro de jugadas de Ansible.

Los archivos de manifiesto se pueden escribir en formato YAML, JSON o INI de Windows y pueden describir grupos de máquinas. P.ej:

---
all:
  children:
    servers:
      hosts:
        macmini2:
        raspberrypi:
      vars:
        description: Linux servers for the Nunez family
    desktops:
      hosts:
        dmaf5:
        mac-pro-1-1:
      vars:
        description: Desktops for the Nunez family

También puede confirmar que el archivo tiene la estructura correcta.Por ejemplo, puede filtrar solo desktops patrón:

[[email protected] ExtendingAnsibleWithPython]$ ansible-inventory --yaml --inventory /home/josevnz/EnableSysadmin/BashHere/hosts.yaml --graph desktops
@desktops:
  |--dmaf5
  |--mac-pro-1-1

Tener un manifiesto YAML estático puede no ser del todo práctico por las siguientes razones:

  1. Su lista de alojamiento es extensa. Admítelo, tienes mejores cosas que hacer que editar archivos YAML, ¿verdad?
  2. Su archivo de manifiesto tiene un formato incompatible con Ansible YAML. Puede estar en una base de datos o en un archivo de texto sin formato.
  3. Los servidores que forman parte de su inventario son de hecho dinámicos. Puede crear máquinas en la nube privada según sea necesario y sus direcciones IP cambian con frecuencia. Alternativamente, su red doméstica puede tener muchos dispositivos itinerantes (tabletas y teléfonos). ¿Quieres mantenerlo manualmente?

Formas de administrar el inventario en Ansible

Hay muchas formas de administrar su inventario en Ansible. Aquí hay algunas posibilidades:

  • Convierta el inventario del formato antiguo a Ansible.
  • Use manifiestos dinámicos con complementos, especialmente Nmap.
  • Escriba sus propios scripts de inventario para generar inventario dinámicamente.
  • Escriba un complemento de inventario de Ansible.

Este artículo incluye los dos primeros elementos de esa lista, y los artículos posteriores explicarán los dos últimos. Recuerde, cualquiera que sea el método que utilice, debe seguir buenas prácticas para empaquetar herramientas, utilizar entornos virtuales y realizar pruebas unitarias de su código para realizar esta tarea.

No te repitas: primero comprueba si alguien te lo ha escrito

Lo más probable es que lo hicieran. Puede ver rápidamente si alguien ha escrito un complemento que puede generar inventario de diferentes fuentes como esta:

$ ansible-doc -t inventory -l

P.ej:

$ ansible-doc -t inventory -l
advanced_host_list  Parses a 'host list' with ranges                                                                                                                                                                     
auto                Loads and executes an inventory plugin specified in a YAML config                                                                                                                                    
aws_ec2             EC2 inventory source                                                                                                                                                                                 
aws_rds             rds instance source                                                                                                                                                                                  
azure_rm            Azure Resource Manager inventory plugin                                                                                                                                                              
cloudscale          cloudscale.ch inventory source                                                                                                                                                                       
constructed         Uses Jinja2 to construct vars and groups based on existing inventory                                                                                                                                 
docker_machine      Docker Machine inventory source                                                                                                                                                                      
docker_swarm        Ansible dynamic inventory plugin for Docker swarm nodes                                                                                                                                              
foreman             foreman inventory source                                                                                                                                                                             
gcp_compute         Google Cloud Compute Engine inventory source                                                                                                                                                         
generator           Uses Jinja2 to construct hosts and groups from patterns                                                                                                                                              
gitlab_runners      Ansible dynamic inventory plugin for GitLab runners                                                                                                                                                  
hcloud              Ansible dynamic inventory plugin for the Hetzner Cloud                                                                                                                                               
host_list           Parses a 'host list' string                                                                                                                                                                          
ini                 Uses an Ansible INI file as inventory source                                                                                                                                                         
k8s                 Kubernetes (K8s) inventory source                                                                                                                                                                    
kubevirt            KubeVirt inventory source                                                                                                                                                                            
linode              Ansible dynamic inventory plugin for Linode                                                                                                                                                          
netbox              NetBox inventory source                                                                                                                                                                              
nmap                Uses nmap to find hosts to target                                                                                                                                                                    
online              Online inventory source                                                                                                                                                                              
openshift           OpenShift inventory source                                                                                                                                                                           
openstack           OpenStack inventory source                                                                                                                                                                           
scaleway            Scaleway inventory source                                                                                                                                                                            
script              Executes an inventory script that returns JSON                                                                                                                                                       
toml                Uses a specific TOML file as an inventory source                                                                                                                                                     
tower               Ansible dynamic inventory plugin for Ansible Tower                                                                                                                                                   
virtualbox          virtualbox inventory source                                                                                                                                                                          
vmware_vm_inventory VMware Guest inventory source                                                                                                                                                                        
vultr               Vultr inventory source                                                                                                                                                                               
yaml                Uses a specific YAML file as an inventory source  

Usando el complemento host_list

Este es el complemento más simple. Pasa una lista de máquinas o direcciones IP y está listo para comenzar.

[ Need more on Ansible? Take a free technical overview course from Red Hat. Ansible Essentials: Simplicity in Automation Technical Overview. ]

Aquí hay un ejemplo usando el módulo de ping y un usuario remoto josevnz:

$ cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.17 mac-pro-1-1
192.168.1.16 macmini2
192.168.1.11 raspberrypi

$ cat /etc/hosts| /bin/cut -f1 -d' '|/bin/grep -P '^[a-z1]'
127.0.0.1
192.168.1.17
192.168.1.16
192.168.1.11

$ ansible -u josevnz -i $(/bin/cat /etc/hosts| /bin/cut -f1 -d' '|/bin/grep -P '^[a-z1]'|/bin/xargs|/bin/sed 's# #,#g') -m ping all
127.0.0.1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.1.11 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.1.16 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.1.17 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

No hay sorpresas aquí. Pero como puede ver, esto no es muy conveniente porque tuve que escribir un pequeño script Bash para generar la lista de hosts.Además, el inventario es estacionario (En cierto sentido, proviene de /etc/host documento).

Aquí hay un complemento más interesante que usa Nmap.

Usando el complemento Nmap

El complemento Nmap le permite crear su lista de inventario utilizando escáneres de red conocidos. Primero, explicaré cómo funciona Nmap cuando lo ejecuta manualmente.

[ Download a Bash shell scripting cheat sheet. ]

Curso intensivo de Nmap

Puede usar Nmap en la línea de comandos para obtener una buena visión general de las máquinas y los servicios en la red:

$ sudo nmap -v -n -p- -sT -sV -O --osscan-limit --max-os-tries 1 -oX $HOME/home_scan.xml 192.168.1.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2022-03-05 10:29 EST
NSE: Loaded 45 scripts for scanning.
Initiating ARP Ping Scan at 10:29
Scanning 254 hosts [1 port/host]
Completed ARP Ping Scan at 10:29, 5.10s elapsed (254 total hosts)
Nmap scan report for 192.168.1.0 [host down]
Nmap scan report for 192.168.1.2 [host down]
Initiating Connect Scan at 10:29
Scanning 4 hosts [65535 ports/host]
Discovered open port 443/tcp on 192.168.1.1
Discovered open port 8080/tcp on 192.168.1.1
Discovered open port 445/tcp on 192.168.1.1
Discovered open port 139/tcp on 192.168.1.1
Discovered open port 80/tcp on 192.168.1.1
Discovered open port 80/tcp on 192.168.1.4
Discovered open port 35387/tcp on 192.168.1.4

Recuerde que este escaneo es una operación que requiere mucho tiempo. Nmap comprueba todos los puertos y hosts de la red, por lo que esto puede tardar unos minutos. incluso horas Si no ajusta su consulta.

Con eso en mente, por favor mantenga estos enlaces útiles. Los usará para ajustar sus parámetros de Nmap:

Para este inventario, le interesan las máquinas en las que Ansible puede usar Secure Shell (SSH) y realizar operaciones. Restringir el número de puerto a TCP 22 acelerará considerablemente el escaneo:

# '-n': 'Never do DNS resolution',
# '-p-': 'All ports. Use -p22 to limit scan to port 22',
# '-sV': 'Probe open ports to determine service/version info',
# '-T4': 'Aggressive timing template',
# '-PE': 'Enable this echo request behavior. Good for internal networks',
# '--version-intensity 1': 'Set version scan intensity. Default is 7',
# '--disable-arp-ping': 'No ARP or ND Ping',
# '--max-hostgroup 100': 'Hostgroup (batch of hosts scanned concurrently) size',
# '--min-parallelism 20': 'Number of probes that may be outstanding for a host group',
# '--osscan-limit': 'Limit OS detection to promising targets',
# '--max-os-tries 1': 'Maximum number of OS detection tries against a target',
# '-oX -': 'Send XML output to STDOUT, avoid creating a temp file'

$ nmap -v -n -p22 -sT -sV  --osscan-limit --max-os-tries 1 -oX $HOME/home_scan.xml 192.168.1.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2022-03-05 10:51 EST
NSE: Loaded 45 scripts for scanning.
Initiating Ping Scan at 10:51
Scanning 256 hosts [2 ports/host]
Completed Ping Scan at 10:51, 2.31s elapsed (256 total hosts)
Nmap scan report for 192.168.1.0 [host down]
Nmap scan report for 192.168.1.2 [host down]
Nmap scan report for 192.168.1.5 [host down]
Nmap scan report for 192.168.1.7 [host down]
...
Completed NSE at 10:51, 0.00s elapsed
Nmap scan report for 192.168.1.1
Host is up (0.0024s latency).

PORT   STATE  SERVICE VERSION
22/tcp closed ssh

Nmap scan report for 192.168.1.3
Host is up (0.070s latency).
...
Nmap scan report for 192.168.1.11
Host is up (0.00036s latency).
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
...
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 256 IP addresses (8 hosts up) scanned in 2.71 seconds

Pero si no le importa el escaneo de puertos, entonces reemplace -p22 y -sn (escaneo de ping) bandera:

$ time nmap -v -n -sn --osscan-limit --max-os-tries 1 -oX $HOME/home_scan.xml 192.168.1.0/24
Read data files from: /usr/bin/../share/nmap
Nmap done: 256 IP addresses (8 hosts up) scanned in 2.52 seconds

Esta ligera diferencia podría ser un factor en una red más grande, pero este ejemplo mantiene el escaneo de puertos en el puerto 22.

Una cosa más: de ahora en adelante, no usaré -n cambio. Si pasa, la resolución de nombres DNS se desactivará y no sabrá el nombre de la máquina que acaba de escanear.

¿Es posible extender Nmap? sí. Ansible tiene un buen complemento de código abierto que envuelve el programa de línea de comandos de Nmap y analiza los resultados. Para ilustrar cómo funciona, me gustaría compartir un script de Python llamado nmap_scan_rpt.py que correlaciona los servicios encontrados por Nmap con avisos de seguridad (esta es una de las formas en que puede ampliar la herramienta original):

$ git clone [email protected]:josevnz/home_nmap.git $HOME/home_nmap.git
pushd home_nmap/
python3 -m venv $HOME/virtualenv/home_nmap/
. ~/virtualenv/home_nmap/bin/activate
nmap_scan_rpt.py $HOME/home_scan.xml
(José Vicente Nunes, CC BY-SA 4.0)

Siéntete libre de jugar con el código. También puede ejecutar Nmap como un servicio web, pero por ahora volveré a Ansible con Nmap.

Complemento Nmap para Ansible

Ahora está listo para explorar el complemento Ansible Nmap:

# We do not want to do a port scan, only get the list of hosts dynamically
---
plugin: nmap
address: 192.168.1.0/24
strict: False
ipv4: yes
ports: no
groups:
  appliance: "'Amazon' in hostname"
  regular: "'host' in hostname"

Entonces pruébalo:

$ ansible-inventory -i ExtendingAnsibleWithPython/Inventories/home_nmap_inventory.yaml --lis

Esto produce un buen JSON para que lo consuma Ansible:

{
    "_meta": {
      "hostvars": {
        "android-1c5660ab7065af69.home": {
          "ip": "192.168.1.4",
          "ports": []
        },
        "dmaf5.home": {
          "ip": "192.168.1.26",
          "ports": []
        }
      },
      "all": {
        "children": [
          "ungrouped"
        ]
      },
      "ungrouped": {
        "hosts": [
          "android-1c5660ab7065af69.home",
          "dmaf5.home",
          "macmini2",
          "new-host-2.home",
          "new-host-6.home",
          "raspberrypi"
        ]
      }
    }
}

Nota: No puedo hacer funcionar la característica de ‘grupos’ de jinja2. Su propósito es poner hosts en grupos dinámicos basados ​​en sus nombres de host.

Inventario dinámico en Ansible

He cubierto mucho material, así que aquí hay un resumen rápido de lo que has hecho:

  • introducido host_list plugin y vi algunas limitaciones obvias, especialmente cuando se usa una gran cantidad de hosts.
  • Aprendió rápidamente Nmap y cómo usarlo para escanear todos los hosts de la red. Usaste este escaneo para crear un inventario.
  • Configure y ejecute la herramienta comunitaria Ansible Nmap y compare su funcionalidad con un escaneo manual de Nmap.

En el próximo artículo de esta serie, le mostraré cómo crear un script para su propio inventario dinámico y por qué esta podría ser una mejor opción que usar un complemento estándar.

Recuerda, puedes descargar el código y experimentar. La mejor manera de aprender es a través de la práctica y los errores.

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Botón volver arriba