¿Cómo administrar exitosamente un centenar de servidores? El problema de todo SysAdmin. Afortunadamente existen herramientas de administración masiva y centralizada como Ansible. A través de las cuales un administrador puede ejecutar un simple comando en muchos sistemas remotos heterogéneos al mismo tiempo. Ansible es un sistema de automatización open source que simplifica las tareas de instalación y provisión de software, gestión de configuración, y despliegue de aplicaciones. Es uno de los sistemas de gestión de configuración (orchestration) más utilizados junto con Puppet, Chef y Salt.

¿Por qué elegí Ansible y no otro? Básicamente por los argumentos a favor y en contra presentes en el artículo Review: Puppet vs. Chef vs. Ansible vs. Salt publicado por Paul Venezia para InfoWorld. Pero principalmente porque es un sistema de configuración que no requiere la instalación de ningún agente o software en los sistemas a administrar de manera remota (más allá del intérprete de Python, claro está, que de todas formas se encuentra presente por defecto en la mayoría de las distribuciones GNU/Linux).

Los sistemas de administración y gestión de configuración están diseñados para controlar de manera centralizada y automatizada un gran número de servidores, simplificando el trabajo de administradores y operadores. A pesar de que existe un puñado de sistemas de gestión de configuración disponibles para sistemas GNU/Linux como Puppet, Chef y Salt, éstos en general son más complejos de lo que el administrador de sistemas promedio quiere o necesita. Ansible es una gran alternativa a estas opciones, pues tiene una curva de instalación y aprendizaje mucho menor para comenzar a utilizarla y operar a diario. Sin contar con el hecho de que Ansible no requiere instalar un agente o cliente en cada sistema a administrar (destino o target) y opera completamente sobre SSH. Una gran ventaja sin dudas, pues además de no sobrecargar los sistemas con agentes, servicios y plataformas de software, no requiere la apertura de puertos adicionales. Esto contrasta con otras soluciones como Puppet y Chef, basadas completamente en Ruby, que requieren un agente, servicios y demonios escuchando en puertos TCP/IP adicionales, y toda una instalación de Ruby en cada servidor. Ansible, por otro lado, está basado completamente en Python, disponible por defecto en casi toda instalación de GNU/Linux.

El funcionamiento de Ansible implica gestionar y administrar máquinas remotas (clientes) desde una computadora con los componentes de Ansible instalados y configurados. Se comunica sobre SSH para obtener información, ejecutar comandos, y copiar archivos desde/hacia las máquinas cliente. De esta forma no se requiere de agentes ni software adicional en los clientes, y cualquier servidor con SSH abierto puede ser controlado por Ansible en cualquier momento.

Por otro lado, Ansible tiene un diseño modular que hace simple extender su funcionalidad para gestionar escenarios específicos. Es posible escribir módulos en cualquier lenguaje y comunicarse en formato JSON. A su vez, los archivos de configuración se escriben principalmente en el formato serializable YAML.

Ansible puede interactuar con los clientes a través de herramientas de línea de comandos o a través de sus scripts de configuración, llamados Playbooks.

Este artículo explica cómo instalar Ansible desde sus fuentes y cómo verificar su funcionamiento básico.

Manos a la obra

En este artículo voy a utilizar un sistema FreeBSD como centro de comando donde instalar Ansible. Sin embargo, como se trata de una instalación desde los fuentes, los pasos son exactamente iguales para cualquier distribución GNU/Linux. Sin embargo, cabe destacar que se encuentran paquetes disponibles en la mayoría de las distribuciones GNU/Linux. En mi caso prefiero la instalación desde los fuentes para disponer de la última versión disponible en el repositorio.

Cambiar al directorio /opt o a cualquier directorio donde se desee instalar Ansible. En caso de ser necesario, crearlo (FreeBSD por defecto no incluye un directorio /opt):

root@hal9000:/usr/home/emi # mkdir -p /opt && cd /opt/

Descargar la última versión de desarrollo de Ansible:

root@hal9000:/opt # git clone git://github.com/ansible/ansible.git --recursive
root@hal9000:/opt # cd ansible/

Abrir una terminal Bash:

root@hal9000:/opt/ansible # bash

Cabe recordar que la shell por defecto de FreeBSD es CSH, con lo cual es necesario instalar Bash para que Ansible funcione. En los sistemas GNU/Linux no es problema pues Bash es la shell por defecto en la mayoría de las distribuciones. Para instalar Bash en FreeBSD, simplemente ejecutar: pkg install bash.

Levantar el entorno de Python:

[root@hal9000 /opt/ansible]# source ./hacking/env-setup

Instalar pip, el popular gestor de paquetes de Python:

[root@hal9000 /opt/ansible]# easy_install pip

Instalar las dependencias de Python que requiere Ansible, utilizando pip:

[root@hal9000 /opt/ansible]# pip install -r ./requirements.txt

Crear e inicializar el inventario:

[root@hal9000 /opt/ansible]# echo "127.0.0.1" > ~/ansible_hosts
[root@hal9000 /opt/ansible]# export ANSIBLE_INVENTORY=~/ansible_hosts

El inventario es la base de datos de hosts (sistemas que serán gestionados remotamente utilizando Ansible). El inventario inicialmente sólo contendrá localhost, únicamente para verificar el funcionamiento de la herramienta.

Luego, cada vez que se desee ejecutar Ansible será necesario abrir Bash, levantar el entorno y configurar la variable ANSIBLE_INVENTORY. Es por ello que lo recomendable tal vez sea agregar esta configuración al archivo de inicialización de Bash (.bashrc, si no existe crearlo):

[root@hal9000 /opt/ansible]# nano ~/.bashrc

Agregar las siguientes líneas:

source /opt/ansible/hacking/env-setup -q
export ANSIBLE_INVENTORY=~/ansible_hosts

A través de la opción -q se suprimen los mensajes de advertencia y errores.

En este caso se trabaja con el usuario root. Según mi punto de vista creo que es lo más recomendable ya que, una vez configurado, desde este host se podrá administrar remotamente un gran conjunto de servidores. Será indispensable entonces endurecer al máximo la seguridad de nuestro "centro de comando".

Luego es necesario instalar sshpass para poder autenticar a través de SSH utilizando contraseñas:

[root@hal9000 /opt/ansible]# pkg install sshpass

Provisoriamente es necesario permitir autenticar como root en la configuración del demonio SSH (/etc/ssh/sshd_config):

PermitRootLogin yes

Esto si se utiliza el usuario root para hacer pruebas. Reiniciar el demonio sshd:

[root@hal9000 /opt/ansible]# service sshd restart

Iniciar una sesión SSH contra localhost para que se guarde el fingerprint en el archivo known_hosts:

[root@hal9000 /opt/ansible]# ssh root@127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:saraza1234.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)? yes

Cerrar la sesión y continuar:

root@hal9000:~ # exit
logout
Connection to 127.0.0.1 closed.
[root@hal9000 /opt/ansible]#

En este punto ya es posible verificar el funcionamiento de Ansible utilizando el módulo ping:

[root@hal9000 /opt/ansible]# ansible all -m ping --ask-pass
SSH password: 
127.0.0.1 | FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Shared connection to 127.0.0.1 closed.\r\n", 
    "module_stdout": "/bin/sh: /usr/bin/python: not found\r\n", 
    "msg": "MODULE FAILURE", 
    "rc": 0
}

Este es un módulo de pruebas trivial que responde "pong" en caso de que la conexión se haya establecido con éxito. Se observa que en el ejemplo anterior falló por no encontrar el intérprete de Python en la ruta /usr/bin/. Esto se debe a que en los sistemas FreeBSD el intérprete se encuentra en /usr/local/bin (por ser proveniente de un port). Solucionarlo temporalmente con un link simbólico ("lo atamo' con alambre"):

[root@hal9000 /opt/ansible]# ln -s /usr/local/bin/python /usr/bin/python

Ahora funciona correctamente:

[root@hal9000 /opt/ansible]# ansible all -m ping --ask-pass
SSH password: 
127.0.0.1 | SUCCESS => {
    "changed": false, 
    "failed": false, 
    "ping": "pong"
}

La sintaxis básica del comando ansible requiere especificar un target (lista de hosts sobre los que se ejecutará un módulo), un módulo (a través de la opción -m, y los parámetros o argumentos del módulo en caso de que sea necesario (mediante -a).

Además de ping, es posible ejecutar cualquier comando aleatorio mediante el módulo shell:

[root@hal9000 /opt/ansible]# ansible all -m shell -a 'df -h' --ask-pass 
SSH password: 
127.0.0.1 | SUCCESS | rc=0 >>
Filesystem      Size    Used   Avail Capacity  Mounted on
/dev/ada0s1a     39G     35G    945M    97%    /
devfs           1.0K    1.0K      0B   100%    /dev
procfs          4.0K    4.0K      0B   100%    /proc
/dev/ada0s2     326G    235G     65G    78%    /data
/dev/ada0s3      66G     39G     21G    64%    /vault
linprocfs       4.0K    4.0K      0B   100%    /usr/compat/linux/proc
/dev/fuse         0B      0B      0B   100%    /usr/home/emi/.gvfs

Ansible posee un archivo de configuración, mediante el cual es posible personalizar su funcionamiento y características. Este se debe guardar en el $HOME del usuario con el nombre .ansible.cfg. El paquete incluye un archivo de configuración de ejemplo dentro del directorio examples/:

[root@hal9000 /opt/ansible]# cp /opt/ansible/examples/ansible.cfg ~/.ansible.cfg

Examinar detenidamente cada variable y personalizar su valor se acuerdo a nuestras necesidades. Para el funcionamiento básico, los valores por defecto son los más adecuados.

Para habilitar el log de Ansible, configurar adecuadamente la variable log_path.

Próximamente explicaré cómo agregar hosts al inventario y cómo configurar los usuarios remotos para autenticar sin contraseña. Sin dudas esperen más artículos acerca de Ansible.

Referencias


Tal vez pueda interesarte


Compartí este artículo