Cuando se trata de gestionar infraestructuras IT complejas, la automatización es clave para mantener la eficiencia, reducir los errores humanos y garantizar la coherencia entre los sistemas. En un entorno con cientos de servidores, como el que gestiono para una organización con 2.000 estaciones de trabajo y más de 300 VMs, la elección de la herramienta de automatización nunca es trivial. La decisión entre adoptar un framework consolidado como Ansible o confiar en scripts Bash/Python personalizados puede tener un impacto significativo en la productividad del equipo, la estabilidad de la infraestructura y, en última instancia, en los costos operativos. Mi experiencia me ha llevado a probar ambos enfoques a gran escala, evaluando no solo la velocidad de ejecución, sino también la mantenibilidad, la escalabilidad y la resiliencia. Los resultados de este test comparativo ofrecen una perspectiva clara sobre cuándo usar cada herramienta para maximizar la eficiencia operativa.
Tested on: Ubuntu 22.04 LTS · Ansible 2.15 · Python 3.10 · Agosto 2026
Contexto del Test
El test se llevó a cabo en un entorno de 200 servidores virtuales, replicando una configuración típica de una infraestructura de medianas a grandes dimensiones. Todos los servidores estaban basados en Ubuntu Server 22.04 LTS. Los objetivos principales eran: actualizar los paquetes del sistema, distribuir un archivo de configuración Nginx y reiniciar el servicio, y finalmente verificar el estado de un servicio crítico. Para cada tarea, medí el tiempo de ejecución promedio, el porcentaje de éxito y la facilidad de depuración en caso de fallo. Los resultados, como veremos, destacaron los puntos fuertes y débiles de ambos enfoques, proporcionando valiosas ideas para la definición de una estrategia de automatización efectiva.
Requisitos Previos / Entorno de Prueba
Para replicar el test, es necesario tener acceso a un entorno con al menos 200 hosts Linux. En mi caso, utilicé Proxmox para crear rápidamente las VMs, pero cualquier hypervisor o proveedor cloud sería adecuado. Es fundamental que todos los hosts sean accesibles vía SSH y que esté configurado el acceso sin contraseña mediante claves SSH. Lee también: SSH Linux sin Password: Configura Claves en 5 Minutos
Para Ansible, es necesario instalar el paquete ansible en el controlador y configurar un archivo de inventario. Para los scripts, es suficiente que Python 3 y Bash estén presentes en los hosts (generalmente preinstalados en Linux).
# Instalación Ansible en el controlador
sudo apt update
sudo apt install ansible -y
# Ejemplo de inventario Ansible (hosts.ini)
[webservers]
web[001:200] ansible_host=192.168.1.{{ (ansible_loop.index | int) + 100 }}
1. Ansible: el enfoque declarativo e idempotente
Ansible se basa en playbooks escritos en YAML, que describen el estado deseado de los sistemas. Su fuerza reside en la idempotencia: puedes ejecutar un playbook varias veces y el sistema alcanzará el mismo estado final sin efectos secundarios indeseados. Esto simplifica enormemente la gestión de las configuraciones y la resolución de problemas.
Aquí tienes un ejemplo del playbook utilizado para los tests:
---
- name: Gestión de servidores con Ansible
hosts: webservers
become: yes
gather_facts: no
tasks:
- name: Actualiza paquetes de sistema
ansible.builtin.apt:
update_cache: yes
upgrade: dist
register: apt_update_result
- name: Debug apt update result
ansible.builtin.debug:
var: apt_update_result
when: apt_update_result.changed or apt_update_result.failed
- name: Distribuye configuración Nginx
ansible.builtin.copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
mode: '0644'
notify: Reinicia Nginx
- name: Verifica estado servicio Nginx
ansible.builtin.service_facts:
- name: Asegúrate de que Nginx esté en ejecución y habilitado
ansible.builtin.service:
name: nginx
state: started
enabled: yes
handlers:
- name: Reinicia Nginx
ansible.builtin.service:
name: nginx
state: restarted
La ejecución de este playbook es sencilla:
ansible-playbook -i hosts.ini playbook.yml
Durante los tests, Ansible gestionó la actualización de los 200 servidores en aproximadamente 15-20 minutos, dependiendo de la carga de red y el número de paquetes a actualizar. La distribución del archivo de configuración y el reinicio de Nginx fueron casi instantáneos. La ventaja principal fue la claridad del log de salida y la facilidad para identificar cualquier host problemático. Lee también: Kubernetes Producción: Primer Deploy, Errores y Soluciones
2. Scripts Custom: flexibilidad y control granular
Los scripts Bash o Python ofrecen un control granular sobre cada operación. Son ideales para tareas muy específicas o para lógicas complejas que no se adaptan fácilmente a los módulos Ansible existentes. Sin embargo, la creación de scripts robustos que gestionen errores, idempotencia y logging requiere un esfuerzo de desarrollo y test significativamente mayor. Para nuestro test, creé un script Python que se conecta vía SSH a cada servidor y ejecuta los comandos necesarios.
# script_custom.py
import subprocess
import paramiko
import concurrent.futures
import time
hosts = [f'192.168.1.{i}' for i in range(101, 301)] # Ejemplo de 200 IP
SSH_USER = 'your_ssh_user'
def run_command_on_host(host, command):
try:
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect(host, username=SSH_USER, timeout=10)
stdin, stdout, stderr = client.exec_command(command, get_pty=True)
output = stdout.read().decode().strip()
error = stderr.read().decode().strip()
client.close()
return host, 'SUCCESS', output, error
except Exception as e:
return host, 'FAILED', '', str(e)
def main():
print("Iniciando script custom para 200 servidores...")
start_time = time.time()
commands_to_run = [
"sudo apt update && sudo apt upgrade -y",
"echo 'server { listen 80; root /var/www/html; index index.html; }' | sudo tee /etc/nginx/nginx.conf > /dev/null",
"sudo systemctl restart nginx",
"sudo systemctl is-active nginx"
]
with concurrent.futures.ThreadPoolExecutor(max_workers=50) as executor:
future_to_host = {
executor.submit(run_command_on_host, host, cmd): (host, cmd)
for host in hosts for cmd in commands_to_run
}
for future in concurrent.futures.as_completed(future_to_host):
host, cmd = future_to_host[future]
try:
result_host, status, output, error = future.result()
if status == 'SUCCESS':
print(f"[{result_host}] {cmd} -> {status}")
else:
print(f"[{result_host}] {cmd} -> {status}: {error}")
except Exception as exc:
print(f"[{host}] Generado una excepción: {exc}")
end_time = time.time()
print(f"Script completado en {end_time - start_time:.2f} segundos.")
if __name__ == '__main__':
main()
La ejecución de este script, incluso con ThreadPoolExecutor para la paralelización, requirió un tiempo similar o ligeramente superior a Ansible para la actualización de paquetes (aproximadamente 20-25 minutos). La gestión de la configuración y el reinicio de Nginx fue rápida, pero el logging y la gestión de errores eran mucho más rudimentarios en comparación con Ansible. Cualquier error en un solo host requería un análisis manual del log del script, sin el contexto rico proporcionado por Ansible.
Errores Comunes y Resolución de Problemas
Ansible:
- Problemas de conexión SSH: A menudo debido a claves SSH no configuradas correctamente o a firewalls que bloquean el puerto 22. Verificar la conectividad manual
ssh user@hosty los logs de Ansible para mensajes específicos (unreachable). - Idempotencia no respetada: Si un módulo no es idempotente (o si un comando
shell/commandse usa de forma inapropiada), se pueden producir efectos secundarios. Asegurarse de usar módulos específicos cuando estén disponibles. - Performance lentas:
gather_facts: noes esencial en grandes inventarios. Utilizarforksadecuados en el archivoansible.cfgpara paralelizar las operaciones.
Scripts Custom:
- Gestión de errores: Ignorar los códigos de salida de los comandos (
$?en Bash) puede llevar a errores no detectados. Cada comando debe ser controlado. - Idempotencia: Debe implementarse manualmente, por ejemplo, verificando la existencia de un archivo antes de copiarlo, o controlando el estado de un servicio antes de reiniciarlo.
- Paralelización: Sin una correcta gestión de los hilos/procesos, los scripts pueden ser muy lentos en muchos hosts. Paramiko, si no se gestiona con un pool de conexiones, puede ser ineficiente. Lee también: Python Automation: Gestionar Servidores Remotos con Paramiko
FAQ — Preguntas Frecuentes
¿Cuál es el impacto de las performance de red?
Las performance de red son un factor crítico para ambos enfoques. Un cuello de botella en la red puede ralentizar significativamente la ejecución, especialmente durante la actualización de paquetes o la distribución de archivos de gran tamaño. Es esencial que el controlador Ansible o el servidor que ejecuta el script tenga una conectividad adecuada a todos los 200 hosts.
¿Ansible es siempre más lento que los scripts Python?
No necesariamente. Aunque hay un overhead inicial para la interpretación de los playbooks y la gestión del inventario, Ansible está altamente optimizado para la paralelización y el uso eficiente de los módulos. Para tareas complejas y bien definidas, Ansible puede ser más rápido porque sus módulos suelen estar escritos en Python optimizado o llaman a binarios eficientes. Los scripts custom, si no se escriben con atención a la paralelización y la eficiencia, pueden ser más lentos.
¿Puedo combinar los dos enfoques?
Absolutamente sí. Un enfoque híbrido es a menudo el más eficaz. Puedes usar Ansible para la gestión general de las configuraciones y la orquestación, y llamar a scripts custom (Bash o Python) a través del módulo ansible.builtin.script o ansible.builtin.command para tareas muy específicas o complejas que requieren una lógica particular no fácilmente expresable en YAML. Esto te permite aprovechar los puntos fuertes de ambas herramientas. Lee también: Ansible: Ejecutar Scripts Remotos con el Módulo Command
¿Cómo gestiono las credenciales de forma segura con ambos?
Para Ansible, se recomienda encarecidamente usar Ansible Vault para cifrar los datos sensibles como contraseñas o claves API. Para los scripts Python, es buena práctica utilizar variables de entorno, un gestor de secretos como HashiCorp Vault, o un sistema de gestión de configuraciones que inyecte las credenciales de forma segura al inicio del script, evitando codificarlas directamente en el código.
Conclusiones con Puntos Clave Operativos
La comparación entre Ansible y scripts custom en 200 servidores ha dejado claro que ambos tienen su lugar en una estrategia de automatización. Ansible destaca en la mantenibilidad, la idempotencia y la gestión de configuraciones complejas a gran escala, ofreciendo una experiencia de depuración superior. Los scripts custom, por otro lado, proporcionan la máxima flexibilidad y son insustituibles para lógicas altamente específicas o para la integración con sistemas no estandarizados. Mi recomendación operativa es adoptar un enfoque híbrido: utilizar Ansible como framework principal para la mayoría de las operaciones de gestión y despliegue, y reservar los scripts Python para los casos excepcionales que requieran un control más granular o lógicas de negocio complejas. Lo importante es invertir tiempo en la optimización y el testing, independientemente de la herramienta elegida, para garantizar que la automatización sea un activo y no una fuente de nuevos problemas.
Fuentes
Actualizado: Agosto 2026