Preparando equipos para usar ansible... con ansible

Ansible para todo

Como ya vimos en Ansible desde Cero, Ansible nos permite realizar acciones gestionar recursos de forma eficiente rápida y ordenada, cuando comenzamos un nuevo entorno desde cero con Ansible, sobre todo en un entorno de máquinas virtuales en el que directamente podemos crear una plantilla con los usuarios ya creados para ejecutar ansible, todo es muy inmediato. En el caso de máquinas ya creadas, lo más sencillo sería reutilizar usuarios, pero siempre es más ordenado crear un usuario nuevo, o ir una por una creando un usuario que pudiera acceder por ssh, con un certificado y añadirlo a sudoers, pero claro, esto tiene dos pequeños inconvenientes:

  1. Ya de buenas a primeras estamos saltándonos todos los "principios" de ansible para usar ansible
  2. Cuando tienes un enorme montón de máquinas se convierte en trabajo de chinos.

Vamos a ver como mediante ansible podemos arreglar esto, sólo necesitamos un usuario con permiso de ssh y sudo (si gestionamos las máquinas tendremos uno, o un puñado de ellos repartidos por los servidores).

Playbooks

No me voy a extender acerca de qué son los playbooks porque en el sitio de ansible hay una documentación muy extensa al respecto, me voy a limitar a decir que, en el ejemplo anterior hemos estado utilizando comandos Ad-Hoc para los finos o A piñón para los no tan finos. Que es algo que está muy bien y que en vez de hacer ssh a veinte servidores para actualizar los paquetes, el hecho de hacerlo desde uno con una línea de comandos ya es razón más que suficiente para arrodillarse y dar gracias a Dios porque alguien haya hecho algo como Ansible. Ahora, la gran potencia de Ansible se empieza a desarrollar con los Playbooks, que no son más que libros de tareas, un libro de tareas nos puede servir para poner una tarea más ordenadita en vez de ponerla a piñón, o para automatizar el proceso de instalación de un servidor web, de manera que simplemente haciendo una instalación básica en un servidor nuevo y ejecutando el Playbook tengamos el servidor vivito y coleando.

Los playbooks están descritos en YAML, que viene a ser como el nuevo crecepelo de esta época, últimamente a todo el mundo le ha dado por YAML, así que por algo será, yo todavía estoy en proceso de aterrizaje. Tampoco me voy a liar a describir la sintaxis ya que también lo tenemos en la "muy extensa documentación al respecto", me voy a limitar a un par de avisos a navegantes para recien aterrizados (más que nada para que no os llevéis las mismas coces que yo.)

Un fichero YAML es como un esquema de esos que hacíamos para estudiar porque alguien nos había dicho que así se aprendía antes, mejor y más barato, esto es, todo tiene que ir indentado al nivel que le toca, de lo contrario el niño protesta, esto qué quiere decir, pues que el fichero YAML tiene que ser algo del estilo de:

---
-Afluentes del Sil
  Por la izquierda:
    Casoio
    Bibei
    Navea
    Mao
  Por la derecha:
    Soldón
    Lor
    Cabe

Si al Navea le quitamos espacios igual nos podemos pensar que el Sil tiene izquierda, derecha y Navea así que lo mejor es no jugar con los espacios y ser muy ordenado con los niveles.

Ahora que ya hemos repasado la geografía, podemos volver con nuestra instalación, lo que queremos es crear un grupo ansible, con un usuario ansrunner -los nombres son a gusto del artista- que nos permita acceder por ssh sin contraseña (con certificado, tampoco nos pongamos chulos) y que pueda usar sudo también sin contraseña, ya que, tanto con ansible como con ansible-playbook siempre podremos meter la contraseña de usuario y la de sudo, pero pierde un poco la gracia (y la utilidad).

Suponiendo que tenemos nuestro fichero hosts ya creado, lo primero que necesitamos es añadir las claves de los servidores en el fichero known_hosts de nuestro usuario en nuestro equipo(o servidor donde tengamos ansible) ya que, de lo contrario no nos dejará usar sshpass y nos dirá que:

fatal: [servidor1] => Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host.

Para añadir la clave de los equipos que nos interesen en nuestro known_hosts podemos hacer lo siguiente:

ssh-keyscan servidor1 > .ssh/known_hosts

Y ya lo tenemos todo listo, podemos editar nuestros playbook y nos quedará algo del estilo de:

---
- hosts: servidor1
  user: usuarioconacceso
  sudo: yes
  tasks:

  - name: Creamos el grupo 'ansible' si no existe
    group:
      name: ansible
      state: present

  - name: Añadimos el grupo 'ansible' a sudoers sin necesidad de contraseña
    lineinfile:
      dest: /etc/sudoers
      state: present
      regexp: '^%ansible'
      line: '%ansible ALL=(ALL) NOPASSWD: ALL'
      validate: 'visudo -cf %s'

  - name: Añadir usuario 'ansrunner' al grupo 'ansible'
    user: name=ansrunner groups=ansible append=yes state=present createhome=yes

  - name: Añadir la clave rsa al usuario 'ansrunner'

    authorized_key:
      user: ansrunner
      state: present
      key: "{{ lookup('file', '/home/miusuario/.ssh/id_rsa.pub') }}"

Este playbook ya lo podemos utilizar siempre que usuarioconacceso tenga acceso a servidor1 y pueda hacer sudo en servidor1:

miusuario@miservidor:~$ ansible-playbook playbooks/crear_usuario.yml -k -K
SSH password:
sudo password [defaults to SSH password]:

PLAY [local] ******************************************************************

GATHERING FACTS ***************************************************************
ok: [servidor1]

TASK: [Creamos el grupo 'ansible' si no existe] *******************************
changed: [servidor1]

TASK: [Añadimos el grupo 'ansible' a sudoers sin necesidad de contraseña] *****
changed: [servidor1]

TASK: [Añadir usuario 'ansrunner' al grupo 'ansible'] *************************
changed: [servidor1]

TASK: [Añadir la clave rsa al usuario 'ansrunner'] ****************************
changed: [servidor1]

PLAY RECAP ********************************************************************
servidor1                  : ok=5    changed=4    unreachable=0    failed=0

Y ahora viene lo bonito de la idempotencia, si volvemos a ejecutar el mismo Playbook ahora obtenemos:

PLAY [servidor1] ******************************************************************

GATHERING FACTS ***************************************************************
ok: [servidor1]

TASK: [Creamos el grupo 'ansible' si no existe] *******************************
ok: [servidor1]

TASK: [Añadimos el grupo 'ansible' a sudoers sin necesidad de contraseña] *****
ok: [servidor1]

TASK: [Añadir usuario 'ansrunner' al grupo 'ansible'] *************************
ok: [servidor1]

TASK: [Añadir la clave rsa al usuario 'ansrunner'] ****************************
ok: [servidor1]

PLAY RECAP ********************************************************************
servidor1                  : ok=5    changed=0    unreachable=0    failed=0

Si ahora intentamos usar ansible con ese equipo y el usuario remoto ansrunner:

miusuario@miservidor:~$ ansible servidor1 -m ping -u ansrunner
127.0.0.1 | success >> {
    "changed": false,
    "ping": "pong"
}

Ya tenemos ansible listo para hacer lo que queramos en servidor1, y lo que es más importante, cambiando los hosts - o mejor aún, añadiendo hosts o grupos - al playbook, podemos repetir las tareas en todos los equipos, o incluso con un simple all hacerlo en todos los equipos del inventario. Y es por esto, que una buena colección de Playbooks soluciona una gran parte del trabajo repetitivo de un administrador de sistemas.

Etiquetas