Primeros pasos con Ansible

Aquí estamos de nuevo, en este caso vamos a ver los primeros pasos con Ansible. Recordar que hasta ahora hemos respondido a las preguntas ¿Qué es Ansible y para qué sirve?, además de ver su instalación.

Vamos a detallar que podemos realizar para entender su funcionamiento y su conexión con los nodos que queremos administrar. Para esto debemos organizar un pequeño inventario, con los hosts clientes. La idea es listar en el fichero «/etc/ansible/hosts» todos los servidores que queramos gestionar.

Pero antes de nada debemos pasar por un paso fundamental. Debemos crear una clave pública SSH para nuestro servidor central. Una vez creada, la importaremos a los clientes. De esta manera nos conectaremos con estos sin tener que poner ninguna contraseña. Recordar que en su día ya hable de cómo generar una llave pública SSH, para nuestro host.

Primeros pasos con Ansible

Después de esta pequeña introducción, vamos a poner las manos en la masa. Un poco de harina, agua y sal, ya podemos empezar.

Crear fichero de inventario

Tal y como indicamos en los párrafos anteriores, debemos añadir los hosts en el fichero «/etc/ansible/hosts«, en mi caso son los siguientes:

  1. vi /etc/ansible/hosts

Con la lista de hosts:

  1. ## db-[99:101]-node.example.com
  2. servdns1.ochobits.local
  3. servdns2.ochobits.local
  4. servicinga.ochobits.local
  5. servlibrenms.ochobits.local

Para comprobar que efectivamente Ansible reconoce la información del fichero, podemos ejecutar el siguiente comando y parámetros:

  1. [root@servansible1 /]# ansible --list-hosts all
  2.   hosts (4):
  3.     servdns1.ochobits.local
  4.     servdns2.ochobits.local
  5.     servicinga.ochobits.local
  6.     servlibrenms.ochobits.local

Para poder interactuar con estos hosts, como hemos dicho antes, debemos exportar nuestra llave pública, utilizando el siguiente comando:

  1. root@servansible1 /]# ssh-copy-id root@servdns1.ochobits.local
  2. /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
  3. /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
  4. root@servdns1.ochobits.local's password:
  5. Number of key(s) added: 1

Debemos hacer estos con cada uno de los hosts con los que queramos trabajar.

Para comprobar que nos conectamos correctamente, sin contraseña, utilizando la llave público, vamos a realizar una prueba:

  1. [root@servansible1 /]# ansible servdns1.ochobits.local -m ping
  2. servdns1.ochobits.local | SUCCESS => {
  3.     "changed": false,
  4.     "ping": "pong"
  5. }

Si lo queremos realizar con todos los hosts, debemos sustituir el nombre del servidor por «all«, con esta respuesta:

  1. [root@servansible1 /]# ansible all -m ping
  2. servdns1.ochobits.local | SUCCESS => {
  3.     "changed": false,
  4.     "ping": "pong"
  5. }
  6. servdns2.ochobits.local | SUCCESS => {
  7.     "changed": false,
  8.     "ping": "pong"
  9. }
  10. servicinga.ochobits.local | SUCCESS => {
  11.     "changed": false,
  12.     "ping": "pong"
  13. }
  14. servlibrenms.ochobits.local | SUCCESS => {
  15.     "changed": false,
  16.     "ping": "pong"
  17. }

Si lo deseamos podemos conectarnos al cliente con usuario diferente de ‘root’, utilizando el parámetro «-u nombre-de-usuario»

Veamos un ejemplo de uso de Ansible, diferente de ping, por ejemplo el comando ‘uptime

  1. [root@servansible1 /]# ansible all -a "uptime"
  2. servdns2.ochobits.local | CHANGED | rc=0 >>
  3.  17:10:48 up  2:11,  1 user,  load average: 0,24, 0,06, 0,06
  4.  
  5. servdns1.ochobits.local | CHANGED | rc=0 >>
  6.  17:10:48 up  2:06,  1 user,  load average: 0,03, 0,07, 0,05
  7.  
  8. servicinga.ochobits.local | CHANGED | rc=0 >>
  9.  17:10:48 up  2:48,  1 user,  load average: 0,66, 0,44, 0,34
  10.  
  11. servlibrenms.ochobits.local | CHANGED | rc=0 >>
  12.  17:10:48 up  3:15,  1 user,  load average: 0,81, 0,46, 0,46

En el caso hemos utilizando el parámetro «-a«, para llamar al comando «uptime» en el host cliente.

Si el usuario con el que nos conectamos tiene «sudo» configurado, podemos utilizar el parámetro «–become (-b)«, para cambiar del usuario con el que nos conectamos.

Por ejemplo:

  1. [root@servansible1 /]# ansible servicinga.ochobits.local -u davidochobits --ask-pass -a "id"
  2. SSH password:
  3. servicinga.ochobits.local | CHANGED | rc=0 >>
  4. uid=1000(davidochobits) gid=1000(davidochobits) grupos=1000(davidochobits),10(wheel)

Si en cambio utilizamos el parámetro «-b»

  1. [root@servansible1 /]# ansible servicinga.ochobits.local -u davidochobits -a "id" -b
  2. servicinga.ochobits.local | CHANGED | rc=0 >>
  3. uid=0(root) gid=0(root) grupos=0(root)

Eso sí, para que esto funcione, esto es, la llamada a «sudo«, en el host cliente, debemos habilitar ‘sudo’ sin contraseña. En el caso de un servidor Centos 7, utilizando el comando «visudo«, descomentamos esta línea:

  1. %wheel ALL=(ALL)       NOPASSWD: ALL

También hemos utilizado en el ejemplo anterior el parámetro «—ask-pass«. Esto es porque con el usuario no hemos realizado el intercambio de llave pública. Por lo que nos pedirá la contraseña para poder conectarnos.

Hasta el momento, el uso de Ansible es muy similar al de PSSH

Inventario avanzado

Hasta ahora hemos visto que Ansible utiliza por defecto el fichero «/etc/ansible/hosts«, aún así, si queremos utilizar otro fichero en otra ruta, también lo podemos hacer, utilizando el parámetro «–inventory» o «-i»

Además, podemos organizar los hosts en grupos y subgrupos. Incluso un único host puede pertenecer a distintos grupos. Por ejemplo:

  1. [dns-servers]
  2. servdns1.ochobits.local
  3. servdns2.ochobits.local
  4. [servweb]
  5. servlibrenms.ochobits.local
  6. servicinga.ochobits.local
  7. [centos7]
  8. servdns1.ochobits.local
  9. servdns2.ochobits.local
  10. servlibrenms.ochobits.local
  11. servicinga.ochobits.local

Tal y como se observa, los grupos se definen entre corchetes. Podemos definir grupos, según su sistema operativo, ubicación geográfica, aplicación, entorno, etcétera.

Incluso le podemos indicar que usuario queremos utilizar por defecto en el host, que puerto o que entorno.

  1. servlibrenms.ochobits.local ansible_user=librenms ansible_port=22343 entorno=PRD

Un resumen de dichas variables:

  • ansible_user: Definición del usuario del cliente que vamos a utilizar.
  • ansible_port: Puerto que vamos a utilizar en la conexión.
  • ansible_host: Definimos la IP para conectar al nodo.
  • ansible_become: Si queremos utilizar sudo.
  • ansible_become_method: Metodo a utilizar para escalar los permisos, como sudo, su, pbrun, etc
  • ansible_become_user: Usuario a utilizar para escalar los permisos.
  • ansible_ssh_pass: Definimos la contraseña para la conexión, esto es necesario si no hemos realizado el intercambio de llaves.

Podemos listar los nodos que hemos agrupado anteriormente:

  1. [root@servansible1 ~]# ansible dns-servers --list-hosts
  2.   hosts (2):
  3.     servdns1.ochobits.local
  4.     servdns2.ochobits.local

También es posible definir la configuración de cada host por separado, definida en fichero individuales. En este caso estos ficheros irán en formato YAML

Definición de patrones en el inventario

En la mayoría de empresas, sobre todo las que tienen un parque de centenares o miles de hosts, no tiene sentido ir uno por uno añadiendo los hosts. Para ello podemos utilizar el uso de patrones.

Os pondré un pequeño ejemplo. En mi caso tengo los servidores «servdns1» y «servdns2». Para listarlos en el fichero de inventario, puerto utilizar esta manera:

  1. servdns[01:02]

Si tuviese hasta veinte servidores con esa numeración, los podría añadir así:

  1. servdns[01:20]

También podemos utilizar patrones alfabéticos, por ejemplo:

  1. copia-seguridad-[a:z]

Y aquí lo dejamos por hoy. En la próxima entrada hablaremos de los ficheros YAML y del inventario dinámico.

Estad atentos.

Fuentes consultadas:

Code-maven.com – Enable passwordless sudo for ansible