Playbooks, roles y nociones avanzadas
Objetivos del capítulo y requisitos
Después de haber visto el funcionamiento de los playbooks y los roles en Ansible, va a indagar un poco más en la investigación de los roles.
1. Contexto y requisitos
Este capítulo profundizará en los temas abordados anteriormente, el lector debe estar familiarizado con las nociones de roles y de playbooks así como con el uso de los inventarios.
Estudiará algunos problemas que podría encontrar como, por ejemplo, la gestión de los intérpretes Python locales o la noción de escalabilidad de servicio. Otra novedad, usará una máquina basada en la distribución Debian para el reparto de carga.
2. Archivos descargables
Puede encontrar los ejemplos en el archivo comprimido capitulo-08.tar.gz que se encuentra en la página del libro en el sitio de Ediciones ENI.
Gestión de Python en las máquinas remotas
1. Introducción
Antes de volver al wiki, estudiará la gestión de la configuración del intérprete de Python en las máquinas remotas. Para la mayoría de las operaciones, Ansible utiliza microprogramas Python que se encuentran en las máquinas que se van a administrar.
Ahora estudiará los métodos que tendrá que seguir en el caso de que el intérprete Python no exista o esté instalado en ubicaciones no estándares (ejemplo: Python 3).
El intérprete de Python 2 no recibe soporte desde el 1 de enero de 2020. Sin embargo, este último todavía sigue presente en los parques informáticos. Se trata del intérprete de Python por defecto de las distribuciones Red Hat Enterprise o CentOS 6 y 7.
2. Preparación del inventario
Primero, va a preparar su inventario y se va a asegurar de que la comunicación SSH funcione correctamente. Usará una nueva máquina llamada haproxy1 que añadirá en el inventario wiki.yml en un nuevo grupo llamado haproxy. Después de la modificación, el archivo debería tener el contenido siguiente:
1apache:
hosts:
apache1:
php_install: yes
mysql:
hosts:
mysql1: {}
haproxy:
hosts:
haproxy1: {}
Como se ha indicado anteriormente, para asegurarse de que la comunicación funciona correctamente, debe lanzar Ansible en modo ad hoc con el módulo ping. No olvide usar como opción el inventario y el nombre de la nueva máquina.
He aquí el comando correspondiente:
$ ansible -m ping -i wiki.yml haproxy1
Y aquí el resultado de este comando:
haproxy1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
Aquí Ansible le está indicando que se ha descubierto un intérprete de Python automáticamente en la ubicación /usr/bin/python3 (es el caso de los servidores Ubuntu, en versiones...
Escalabilidad y reparto de carga
1. Contexto
Antes de estudiar detenidamente el funcionamiento de los intérpretes de Python, vio en el capítulo anterior cómo instalar un wiki en un caso simple (una máquina para cada función). En las siguientes líneas verá la respuesta a una necesidad bastante corriente: aumentar la capacidad de recepción de conexiones en la aplicación MediaWiki, así como hacer que Apache sea redundante.
Usted estudiará las siguientes técnicas que le permitirán dar una respuesta a esta necesidad:
-
la incorporación de un servidor (escalabilidad);
-
la implementación de un repartidor de carga (para el reparto de carga y la tolerancia a fallos);
-
la realización de actualizaciones por oleadas (rolling update).
Para el repartidor de carga, usará haproxy que es una solución muy especializada para este tipo de acción. Esta le permitirá gestionar diferentes aspectos:
-
el reparto de carga;
-
la tolerancia a fallos;
-
la capacidad de crear una instancia de Apache para que intervenga cuando sea necesario;
-
la visualización de la actividad de los servidores.
No se verán todos los aspectos del programa haproxy. Este libro solamente presenta las funciones necesarias para llevar a cabo un ejemplo simple.
2. Origen de la necesidad
Pero ¿de dónde viene esta necesidad de escalabilidad y reparto de carga? Como se ha visto anteriormente, imagine que cada vez haya más personas que tengan que conectarse a ese wiki. El tráfico irá aumentando y podrá encontrarse con un servidor Apache que no podrá mantener todas estas conexiones. A eso se añade otro problema, no hay redundancia. Si el servidor se encontrara inaccesible, el wiki podría estar no disponible y los usuarios enfadados.
En los capítulos siguientes verá cómo Ansible puede dar una respuesta simple y eficaz a este problema.
3. Incorporación de nuevos servidores Apache
Para poder aumentar la capacidad de manejo de conexiones en una aplicación, dispone de dos técnicas:
-
Aumentar la capacidad de tratamiento de su máquina añadiendo procesadores y/o memoria.
-
Aumentar el número de máquinas que aseguren la misma función.
En las líneas siguientes, verá el uso de Ansible para gestionar la configuración de algunas...
Incorporación de un reparto de carga
1. ¿Por qué deberíamos incorporar un reparto de carga?
Su nuevo servidor Apache está listo, pero sus usuarios todavía no pueden beneficiarse de él. Los usuarios siguen usando la URL que conocen. En ese caso, hay que incorporar un mecanismo de reparto de carga e indicar a los usuarios que tienen que actualizar la entrada para este servidor en los favoritos de su navegador.
2. Diferencias entre Ubuntu/Debian y Centos/Red Hat
Ahora estudiará la instalación de un repartidor de carga en la máquina haproxy1. Esta última se encargará de enrutar el tráfico entre las dos máquinas Apache. Como se vio anteriormente, esta máquina no estará basada en una distribución CentOS sino en una Ubuntu Server versión 18.04 LTS.
El cambio principal, respecto al uso de una distribución derivada de Debian, es que en lugar de usar el módulo yum habrá que usar el módulo apt. Las opciones de esos dos módulos son idénticas.
Otra diferencia entre esas dos familias de distribuciones será el comportamiento por defecto del sistema de gestión de paquetes. En el caso de una Debian o derivada, la instalación del paquete de un servidor provocará el inicio automático del servicio asociado. En las derivadas de Red Hat, la tendencia es más bien de instalar el paquete servidor y de no iniciarlo.
Habrá que tener en cuenta este comportamiento en los siguientes playbooks. En Debian, los servicios estarán iniciados y listos para funcionar en cuanto los instale.
3. Instalación del servidor Haproxy
Utilizará el demonio Haproxy para gestionar el reparto de carga. Tendrá que lanzarlo y ejecutarlo. Deberá realizar las operaciones siguientes:
-
instalación del paquete haproxy con apt;
-
configuración del servidor Haproxy;
-
activación del servicio.
Igual que para el servidor Apache, la modificación de la configuración de Haproxy provocará una llamada a un handler. Este último gestionará el paro/marcha del demonio.
a. Configuración del servidor Haproxy
Como ha podido ver, la realización del playbook no es difícil en sí misma. Sin embargo, tendrá que concentrarse en la configuración de Haproxy.
La configuración por defecto...
Algunos consejos
El wiki ya se ha instalado y funciona correctamente. Pero siempre es posible hacerlo un poco mejor. Ahora va a profundizar en algunos puntos por los que antes ha pasado rápidamente.
1. Controlar la ejecución de los handlers
Uno de los primeros puntos que le propone este libro se centra en la gestión del lanzamiento de los handlers. De hecho, hasta ahora, estos últimos se ejecutaban cuando ellos querían. Sin embargo, en algunos casos, es preferible gestionar el momento de esa ejecución.
Si se fija con atención en el caso de la instalación y configuración de Haproxy, se dará cuenta de que es preferible controlar el momento de la ejecución de los handlers. Si echa un vistazo a las tareas desarrolladas durante la instalación, encontrará la realización de las operaciones siguientes:
-
Instalación del paquete haproxy.
-
Implementación de la configuración de Haproxy con la notificación del handler de reinicio.
-
Activación del servicio (sin cambios, ya que el servicio había sido iniciado automáticamente por la instalación del paquete).
-
Lanzamiento del reinicio de Haproxy.
Resumiendo, tiene que realizar primero la activación del servicio para después hacer un paro/marcha del mismo. Si hubiera tenido una máquina basada en Red Hat, ese reinicio no hubiera servido para nada.
Sin embargo...
Actualización y reentrada de script
1. Contexto
Ha realizado la instalación del MediaWiki pero, entre tanto, se ha publicado una nueva versión, la 1.34.1, y le gustaría instalarla. Va a estudiar un problema bastante común en este tipo de situaciones: la gestión de la actualización de la base de datos.
2. Gestión de la actualización de la versión del esquema
Para la actualización de los archivos estáticos de la aplicación, solamente tendrá que modificar el contenido del archivo mediawiki/configuration/defaults/main.yml para cambiar el valor de la variable mediawiki_archive_url para pasar a la versión 1.34.1.
He aquí la declaración correspondiente:
# archive of mediawiki to download
mediawiki_archive_url: "https://releases.wikimedia.org/mediawiki
1.34/mediawiki-1.34.1.tar.gz"
La ejecución del playbook de la instalación de MediaWiki no se verá de nuevo (playbook install-mediawiki.yml). De hecho, todo se desarrolla de la misma forma que las veces anteriores. Sin embargo tiene que saber que, de una versión a la otra, el esquema de la base de datos cambia.
Con respecto a MediaWiki, se trata de un caso simple ya que existe un script que permite gestionar esta actualización de versión. Se trata del script llamado update.php que se encuentra en el subdirectorio maintenance. La ejecución de esta operación...
Actualización continua (rolling update)
1. Contexto
Usted tiene un playbook que se ejecuta correctamente y tiene ahora que actualizar algunos servidores. En este contexto, quiere evitar tener problemas funcionales en todos los servidores a la vez. Ansible le ofrece un mecanismo simpe de ejecución por oleadas.
2. Presentación del mecanismo
Pongamos un caso simple: la actualización de veinte máquinas. Sin embargo, tendrá algunos imperativos: no puede haber ningún corte en la disponibilidad de más de tres máquinas a la vez y, sobre todo, la instalación debe pararse si se encuentrara la más mínima anomalía.
En este caso, la palabra clave será serial. Habrá que posicionarla a 3 en el playbook.
Si vuelve a tomar el playbook install-mediawiki.yml, el contenido del archivo debería ser:
- name: "MediaWiki db configuration"
hosts: mysql
gather_facts: no
tags: [ "mariadb", "mysql" ]
roles:
- role: "mediawiki/mariadb"
- name: "MediaWiki apache configuration"
hosts: apache
# 3 hosts at a time
serial: 3
tags: "apache"
gather_facts: no
roles:
- role: "mediawiki/configuration"
En el caso de que quisiera actualizar primero un servidor, después 3 y más adelante 10, podría usar la sintaxis siguiente:
# one, then 3, then 10 hosts at a time
serial: [ 1, 3, 10 ]
Otra manera de definir esta serie sería usando porcentajes:
# 1%, then 5%, then 10% of hosts at a time
serial: [ "1%", "5%", "10%" ]
El valor 1 % representará al menos un servidor, incluso en el caso de que tenga menos de cien máquinas.
Otro campo que debería conocer es el porcentaje máximo de errores tolerados. En el caso de que usted quiera tener como máximo 5 % de error en el conjunto de sus máquinas, añada la opción max_fail_percentage: 5.
Este valor tiene que ser sobrepasado. Si tiene 4 máquinas y no quiere tener más de dos máquinas en error, tendrá que usar el valor max_fail_percentage: 49.
3. Actualización continua en el MediaWiki
Tome el ejemplo...
Inclusión y reutilización
1. Contexto
La noción de rol es interesante para reutilizar el código Ansible que ya existe. En los capítulos anteriores, el lector ha estudiado las siguientes técnicas:
-
Aplicación de una lista de roles (gracias a la palabra clave roles en un playbook).
-
Uso de metadatos (contenido del archivo meta/main.yml).
-
Inclusión de código que ya existía (instrucción include).
Estos mecanismos, aunque son completos, a veces pueden ser limitados, sobre todo en un contexto complejo. Para responder a este tipo de problemas, Ansible ofrece los siguientes mecanismos:
-
Inclusión de rol (instrucción include_role).
-
Inclusión dinámica de código (instrucción include_tasks).
-
Inclusión estática de código (instrucción import_tasks).
El mecanismo de inclusión de rol se ha estudiado anteriormente con el fin de simplificar el orden de las tareas. Ahora verá las diferencias entre los modos de inclusión import_tasks y include_tasks.
2. Inclusión estática de tareas
Para los ejercicios siguientes, usted creará un playbook simple que mostrará un mensaje. He aquí la instrucción que le permitirá realizar esta operación:
- debug: msg="test"
Guarde esta instrucción en el archivo test.yml.
Además de este archivo, se va a crear un playbook. Éste incluirá de manera estática el archivo test.yml y se ejecutará en la máquina localhost.
He aquí el código correspondiente:
- name: "Include test"
hosts: localhost
gather_facts: no
tasks:
- import_tasks: "test.yml"
Guarde este playbook con el nombre debug-include.yml y ejecútelo con el comando siguiente:
$ ansible-playbook debug-include.yml
He aquí un extracto del resultado del comando:
PLAY [Include test]...
Ansible Galaxy
1. Presentación del sitio
Como ya ha visto, los roles son una manera de compartir código para la instalación de programas. Ansible Galaxy responde a otra necesidad: centralizar y encontrar roles Ansible que ya han sido escritos.
La primera etapa consistirá en visitar el sitio: https://galaxy.ansible.com/
Página principal del sitio web Ansible Galaxy
Este sitio ofrece un motor de búsqueda que le permite encontrar roles compartidos por la comunidad:
Motor de búsqueda del sitio Ansible Galaxy
El enlace Browse roles le permitirá hacer búsquedas en los roles existentes:
Búsqueda de un rol para instalar Apache en CentOS
2. Búsqueda de un rol
Otra manera de buscar un rol sería usando el comando ansible-galaxy con la opción search. También se puede filtrar por el nombre del autor.
Para ello, puede usar la opción --author seguida del nombre del autor.
Buscará un rol para instalar java publicado por el usuario viniciusfs.
He aquí el comando correspondiente:
$ ansible-galaxy search java --author viniciusfs
Y aquí su resultado:
Found 1 roles matching your search:
Name Description
---- ----------
viniciusfs.java Installs Java OpenJDK in CentOS/RHEL systems.
Antes de instalar un rol puede obtener información sobre él usando la opción info seguida del nombre del paquete que tendrá que instalar. He aquí la ejecución para obtener la información del rol viniciusfs.java:
$ ansible-galaxy info viniciusfs.java
Y aquí un extracto del resultado del comando:
Role: viniciusfs.java
description: Installs Java OpenJDK in CentOS/RHEL systems.
[...]
Role: viniciusfs.java
description: Installs Java OpenJDK in CentOS/RHEL systems.
[...]
Installs Java OpenJDK in CentOS/RHEL systems.
## Role Variables
* `java_version`:
- Description: OpenJDK version to install
- Default: `1.7.0`
## Example Playbook
- hosts: servers
roles:
- { role: viniciusfs.java }
[...]
3. Uso de un rol de Ansible Galaxy
Probará...