ansible paso a paso

¿Qué es Ansible en pocas palabras? Una herramienta de automatización sin agente (no necesita instalar nada en las máquinas remotas), que usa SSH para comunicarse con los servidores. Permite automatizar configuraciones, instalaciones, despliegues y mucho más usando archivos llamados Playbooks, escritos en YAML.

Para este tutorial les cuento que estoy usando ubuntu 24.04 (en mi notebook) y ademas tengo virtualbox con 3 maquinas virtuales para practicar cuyas caracteristicas son 2gb de ram, 2 nucleos, 40gb de disco. ¿Es mucho?, por suerte mi maquina se lo banca, esto tambien se puede hacer utilizando equipos fisicos si es que lo requieren. Además van a ver que mis maquinas tienen un nombre como k8s-node o similar y es por que ademas las voy a utilizar para otro tutorial donde les mostrare como instalar Kubernetes, pero esto es más adelante……

Infraestructura para la practica de ansible
Infraestructura para la practica de ansible

La regla numero 1 deberia ser que los servidores (en mi caso las maquinas virtuales) tengan ip fija, ya que no queremos administrar algo que este cambiando todo el tiempo. Ubuntu 24.04 utiliza netplan para configuración de las placas de red. Para vamos a ir maquina por maquina la primera vez, y para dejar el entorno preparado, configurando las ips que queramos.

Vamos a editar la primer maquina virtual y para eso entramos con ssh (ejemplo ssh usuario@ipdelamaquina) y utilizamos el comando:

sudo nano /etc/netplan/50-cloud-init.yaml

Como podemos ver a continuación, netplan viene configurado con dhcp de este modo:

Dato importante de la imagen anterior «la placa de red se llama enp0s3».

Lo deberiamos dejar de este modo (dependiendo el rango de red que queres usar en la practica….)

network:
  version: 2
  ethernets:
    enp0s3:
      dhcp4: no
      addresses:
        - 192.168.0.160/24
      routes:
        - to: 0.0.0.0/0
          via: 192.168.0.1
      nameservers:
        addresses: [8.8.8.8, 1.1.1.1]

Luego vamos a aplicar los cambios con:

sudo netplan apply

Importante:

  • Si la maquina tenia una ip, y en la config ponemos otra, te va aparecer como que «se colgo»…. en fin tenes que salir y volver a entrar con la ip que asignaste.
  • Si la version de ubuntu es mas vieja tal vez gateway4 en vez de routes.

Esta accion la tenemos que repetir en cada maquina virtual y en mi caso me queda asi:

k8s-master = 192.168.0.160

k8s-node1 = 192.168.0.161

k8s-node2 = 192.168.0.162

Con toda esta preparación avanzamos! Ahora en tu notebook o desde la maquina que vas a usar para administrar tendremos que instalar ansible:

sudo apt update && sudo apt upgrade -y
sudo apt install software-properties-common -y
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible -y

y verificamos que haya quedado instalado:

ansible --version
verificamos que ansible quedo instalado
verificamos que ansible quedo instalado

Tenemos que generar un ssh-key y copiarlo en cada una de los servidores virtuales para justamente no tener que poner una clave cada vez que ejecutamos un comando. SI no sabes como se hace, en los tips de seguridad te lo deje explicado hace un tiempo:

Una vez que tengas generada la ssh-key la vas a copiar en cada maquina virtual:

ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

Por cada uno nos va a pedir la contraseña del servidor y va a agregar el ssh-key en cada servidor, con lo cual la proxima que hagas un ssh usuario@servidor no te va a pedir contraseña.

Ahora nos vamos a crear en nuestra compu (administradora) una carpeta que se llama Inventario y dentro un archivo que se llama hosts.ini que va a tener esta info:

Tendran que cambiar los nombres de maquinas, ip y usuario que utilicen.

La prueba de fuego es el «ping de ansible» y se hace con este comando:

ansible -i hosts.ini servidores -m ping

En la imagen anterior vemos dos cosas importantes:

1 – cada maquina respondio un SUCCESS y luego de ping dice PONG jajaja o sea que funciono correctamente.

2 – Hay un WARNING que nos dice que ahora esta usando la ubicación interprete de python, pero si se actualiza luego podria fallar. Es solo un aviso, no pasa nada, peroo si queremos hacer que funcione mejor. Vamos a agregar en cada host la linea ansible_python_interpreter=/usr/bin/python3 y nos quedaria de este modo:

editando hosts.ini

y volvemos a hacer la prueba de fuego:

Ahora ya no hay ningun aviso! Asi que todo bien y continuamos!

Ahora que tenemos todo andando se nos viene el concepto playbook. Un playbook vendria hacer como una «receta para hacer algo» con todas las acciones que queremos llevar a cabo. Esto es lo más lindo, por que son tareas que debieramos saber hacer maquina por maquina, pero que ahora las podemos automatizar.

Una tarea comun de un sysadmin es saber:

  • Uso de CPU
  • Uso de memoria
  • Espacio libre en disco
  • Los últimos 10 accesos de usuarios, incluyendo accesos físicos y SSH (last)

Vamos a crear dentro de Inventario el archivo reporte_sistema.yml

---
- name: Recolectar información del sistema
  hosts: all
  gather_facts: no
  become: true

  tasks:
    - name: Obtener información de CPU
      shell: lscpu
      register: cpu_info

    - name: Obtener uso de memoria
      shell: free -h
      register: memoria_info

    - name: Obtener uso de disco
      shell: df -h
      register: disco_info

    - name: Obtener últimos accesos SSH
      shell: last -n 5 -i
      register: ssh_info

    - name: Crear carpeta local de reportes si no existe
      file:
        path: "./reportes"
        state: directory
        mode: '0777'
      delegate_to: localhost
      run_once: true

    - name: Guardar datos en archivo JSON por host
      copy:
        content: |
          {{
            {
              "host": inventory_hostname,
              "cpu": cpu_info.stdout,
              "memoria": memoria_info.stdout,
              "disco": disco_info.stdout,
              "ssh": ssh_info.stdout
            } | to_nice_json
          }}
        dest: "./reportes/{{ inventory_hostname }}.json"
        mode: '0644'
      delegate_to: localhost

- name: Generar HTML final desde archivos JSON
  hosts: localhost
  tasks:
    - name: Ejecutar script Python generar_html.py
      command: python3 generar_html.py
      args:
        chdir: "{{ playbook_dir }}"

Vamos a crear en la misma carpeta Inventario otro archivo que se llama generar_html.py

import os
import json

carpeta_reportes = "reportes"
archivos = [f for f in os.listdir(carpeta_reportes) if f.endswith(".json")]

html = """
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Reporte de Sistema</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
  <style>
    body { padding: 2rem; background-color: #f8f9fa; }
    pre { white-space: pre-wrap; word-wrap: break-word; }
    .host-card { margin-bottom: 2rem; }
  </style>
</head>
<body>
  <div class="container">
    <h1 class="mb-4 text-center">Reporte del Sistema</h1>
"""

for archivo in archivos:
    ruta = os.path.join(carpeta_reportes, archivo)
    try:
        with open(ruta, "r", encoding="utf-8") as f:
            datos = json.load(f)

        html += (
            f'<div class="card host-card shadow">'
            f'<div class="card-header bg-primary text-white">'
            f'<h4 class="mb-0">Host: {datos.get("host", "Desconocido")}</h4>'
            f'</div>'
            f'<div class="card-body">'
            f'<h5>CPU</h5><pre>{datos.get("cpu", "No disponible")}</pre>'
            f'<h5>Memoria</h5><pre>{datos.get("memoria", "No disponible")}</pre>'
            f'<h5>Disco</h5><pre>{datos.get("disco", "No disponible")}</pre>'
            f'<h5>Últimos accesos SSH</h5><pre>{datos.get("ssh", "No disponible")}</pre>'
            f'</div>'
            f'</div>'
        )

    except json.JSONDecodeError as e:
        print(f"⚠️ Error al leer {archivo}: {e}")
    except Exception as e:
        print(f"❌ Error inesperado con {archivo}: {e}")

html += """
  </div>
</body>
</html>
"""

with open(os.path.join(carpeta_reportes, "reporte_sistema.html"), "w", encoding="utf-8") as f:
    f.write(html)

print("✅ Reporte generado: reportes/reporte_sistema.html")

y que cosa hace todoooooo esto?

Vamos a ejecutar el siguiente comando para verlo en acción y luego ver que hizo. El comando utiliza el playbook reporte_sistema.yml y lo ejecuta en el inventario hosts.ini que fue el que creamos con nuestros equipos.

ansible-playbook -i hosts.ini reporte_sistema.yml
ejecucion del playbook de ansible con reporte de sistema en html

Este resultado nos indica que las tareas fueron corrida en cada uno de los servidores y que todo estuvo bien. ¿Pero que hizo?

El archivo reporte_sistema.yml recorre cada servidor preguntando uso de memoria de disco y accesos ssh. Crea una carpeta con permisos 777 para adentro colorar un archivo json con el resultado. Luego ejecuta un archivo en python que genera un html más legible. Sino lo ubiera hecho en html el resultado era algo asi:

Un resultado poco atractivo a la vista!!!!!!

Al hacerlo en html ahora es asi:

resultado en html de playbook de ansible ejecutado

Ademas si hacemos un zoom sobre memoria y disco es super entendible:

Digimos que teniamos maquinas de 2gb de ram asi que esta perfecto!

Podemos armar playbooks con muchas cosas, pero ojo, a veces la automatización nos puede pasar una mala jugada. Intenten todo paso a paso, y si pueden probar en maquinas virtuales primero para no tener ningun tipo de problema mejor. Ensayar labotarios siempre hace a la practica!. En definitiva, con ansible logramos escribir nuestros propios archivos y que al ejecutarlos trabajen en multiples servidores a la vez con lo hemos logrado Paramatrizacion, documentacion y automatizacion!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *