Ejemplo: Automatización con ANSIBLEEntorno de pruebasRecursosFuncionamientoElementosEstructura de los Playbooks (sin roles)ComandosConfiguraciónUso básico de AnsiblePlaybooks sencillos: instalación de Apache2Playbooks sencillos: instalación de HAProxyUso de RolesEstructura de los RolesEjemplo de definición y uso de Roles
Script de instalación GNU/Linux: ejercicio-ansible.sh
bash ejercicio-ansible.sh
Script de instalación Windows: ejercicio-ansible.ps1 [aportado por Adrián Otero]
xxxxxxxxxxPowershell.exe -executionpolicy bypass -file ejercicio-ansible.ps1
Usuarios disponibles
| Login | Password | |
|---|---|---|
| root | purple | |
| usuario | purple | con acceso sudo |
Ansible es una herramienta de automatización de sistemas
facter pero no es imprescindible)El "nodo de control" Ansible es el único participante donde debe estar instalado Ansible (paquete ansible en Debian/Ubuntu) junto con la colección de módulos.
Desde el "nodo central" Ansible se conecta a los nodos administrados mediante SSH con un usuario existente en el host
Ejecuta sobre cada nodo las tareas correspondientes (instalar componentes, modificar ficheros, crear usuarios, etc) según indique el playbook
sudo, su o comandos similaresEsas tareas las implementan los módulos Ansible interactuando con el hosts destino mediante la conexión SSH
Módulos Implementan las tareas a realizar sobre los hosts administrados a través de la conexión SSH
/usr/lib/python3/dist-packages/ansible/modules/) Inventario Listado de hosts sobre los que se realizan las tareas automatizadas con Ansible
Playbooks Colección de Plays, cada una de estas Plays indican los hosts del Inventario sobre los que realizar una lista de tareas (Task)
Roles Son una abstracción de los Plays que permiten reutilizarlos.

Nota: Listado de elementos de configuración en Playbooks
ansible Ejecución de tareas aisladasansible-playbook Ejecución de playbooksansible-galaxy Instalación (ansible-galaxy install <nombre>) y gestión de roles (por defecto se almacenan en $HOME/.ansible/roles)La configuración global de Ansible está en /etc/ansible
ansible.cfg Configuración por defectohosts Inventario de hosts por defectoroles Directorio con los roles disponibles (también /usr/share/ansible/roles)En el directorio $HOME/.ansible está la configuración de usuario (con los correspondientes ansible.cfg, hosts, roles, etc)
Es posible "sobreescribir" la configuración por defecto (global o de usuario) mediante ficheros ansible.cfg y hosts en el directorio de trabajo.
roles local para los roles particulares usados en cada caso.Nota: Detalles sobre configuración
(a) Desde la máquina ansible (logueado como usuario/purple), crear el directorio de trabajo ejemplo_ansible y fichero con el inventario de los equipos.
xxxxxxxxxxusuario@ansible:~/$ mkdir ejemplo_ansibleusuario@ansible:~/$ cd ejemplo_ansibleusuario@ansible:~/ejemplo_ansible$ nano inventarioxxxxxxxxxx[web]web1.cda.netweb2.cda.netweb3.cda.netweb4.cda.net[haproxy]haproxy.cda.net[bd]bd.cda.net
Nota En lugar de enumerar los hosts web1 web2 web3 y web4 , otra alternativa al ternativa sería usar la notación web[1:4].cda.net
(b) Crear par de claves RSA para SSH (con passphrase vacía) y propogarlas a las máquinas del ejercicio (pedirá la contraseña de usuario [purple]).
xxxxxxxxxxusuario@ansible:~/ejemplo_ansible$ ssh-keygenGenerating public/private rsa key pair.Enter file in which to save the key (/root/.ssh/id_rsa): Created directory '/root/.ssh'.Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa.Your public key has been saved in /root/.ssh/id_rsa.pub.The key fingerprint is:9a:a0:d0:cc:b9:78:a8:24:15:ce:58:49:0f:5c:c8:33 usuario@ansibleThe key's randomart image is:+---[RSA 2048]----+| ooo. || .E+ || +o. || O o ||o O . S || = o . o ||+.+ o ||+. ||. |+-----------------+
usuario@ansible:~/ejemplo_ansible$ ssh-copy-id usuario@web1.cda.netusuario@ansible:~/ejemplo_ansible$ ssh-copy-id usuario@web2.cda.netusuario@ansible:~/ejemplo_ansible$ ssh-copy-id usuario@web3.cda.netusuario@ansible:~/ejemplo_ansible$ ssh-copy-id usuario@web4.cda.netusuario@ansible:~/ejemplo_ansible$ ssh-copy-id usuario@haproxy.cda.netusuario@ansible:~/ejemplo_ansible$ ssh-copy-id usuario@bd.cda.net(c) Comprobar la accesibilidad al usuario1 de esas máquinas con el módulo ping de Ansible.
xxxxxxxxxxusuario@ansible:~/ejemplo_ansible$ ansible all -i inventario -u usuario -m pinghaproxy.cda.net | success >> { "changed": false, "ping": "pong"}
bd.cda.net | success >> { "changed": false, "ping": "pong"}
web1.cda.net | success >> { "changed": false, "ping": "pong"}
web3.cda.net | success >> { "changed": false, "ping": "pong"}
web4.cda.net | success >> { "changed": false, "ping": "pong"}
web2.cda.net | success >> { "changed": false, "ping": "pong"}
(d) Para evitar indicar el inventario y el usuario en cada invocación, declarar esos datos en el fichero ansible.cfg.
xxxxxxxxxxusuario@ansible:~/ejemplo_ansible$ nano ansible.cfgxxxxxxxxxx[defaults]inventory = inventarioremote_user = usuario
(e) Ejecución de comandos en las máquinas administradas (módulo command)
xxxxxxxxxxusuario@ansible:~/ejemplo_ansible$ ansible all -m command -a "/usr/bin/free"usuario@ansible:~/ejemplo_ansible$ ansible all -m command -a "/bin/df"(f) Consulta de información en las máquinas administradas (serán las variables disponibles en los playbooks) (módulo setup)
xxxxxxxxxxusuario@ansible:~/ejemplo_ansible$ ansible all -m setupfacter en las máquinas administradas.
(a) Crear el fichero playbook_apache.yml y lanzarlos sobre los servidores web con el comando ansible-playbook (pedirá la contraseña de usuario: purple).
xxxxxxxxxxusuario@ansible:~/ejemplo_ansible$ nano playbook_apache.ymlxxxxxxxxxx---nameinstalacion de apache2 y php hostsweb becomeyes tasksnameinstalar apache2 aptname=apache2 update_cache=yes state=latest
xusuario@ansible:~/ejemplo_ansible$ ansible-playbook playbook_apache.yml --ask-become-pass
purple) para que mediante sudo el módulo apt instale el paquete apache2.(b) Crear los directorios plantillas y ficheros.
x
usuario@ansible:~/ejemplo_ansible$ mkdir plantillasusuario@ansible:~/ejemplo_ansible$ mkdir ficheros(c) Crear el fichero index.html.j2 con la plantilla parametrizable del home por defecto.
xxxxxxxxxxusuario@ansible:~/ejemplo_ansible$ nano plantillas/index.html.j2x
<html><body><h1>Pagina por defecto de apache</h1>
<p>Contenido estático, contenido estático</p>
<h1>Servido por {{ansible_hostname}} </h2></body></html>Nota Sintaxis del lenguaje de plantillas Jinja2
(d) Crear el fichero phpinfo.php con un ejemplo de página PHP.
xxxxxxxxxxusuario@ansible:~/ejemplo_ansible$ nano ficheros/phpinfo.phpx
<?phpphpinfo();phpinfo(INFO_MODULES);?>(d) Completar el playbook de Apache con las siguientes tareas.
El fichero playbook_apache.yml resultante debe de quedar como:
x
---nameinstalacion de apache2 y php hostsweb becomeyes tasksnameinstalar apache2 aptname=apache2 update_cache=yes state=latest
nameinstalar php apt namelibapache2-mod-phpphp-mysqlphp-pear statelatest notifyrestart apache2
namecrear index.html templatesrc=plantillas/index.html.j2 dest=/var/www/html/index.html backup=yes
namecopiar phpinfo.php copysrc=ficheros/phpinfo.php dest=/var/www/html/phpinfo.php
handlersnamerestart apache2 servicename=apache2 state=restarted(e) Volver a lanzar el playbook y comprobar con un navegador web desde la máquina ansible que se accede a los ficheros index.html y phpinfo.php.
x
usuario@ansible:~/ejemplo_ansible$ ansible-playbook playbook_apache.yml --ask-become-passDesde la máquina ansible, comprobar con el comando lynx el acceso a las páginas web de web1.cda.net, web2.cda.net,web3.cda.net y web4.cda.net
x
usuario@ansible:~/ejemplo$ lynx web1.cda.netusuario@ansible:~/ejemplo$ lynx web1.cda.net/phpinfo.php
usuario@ansible:~/ejemplo$ lynx web2.cda.netusuario@ansible:~/ejemplo$ lynx web2.cda.net/phpinfo.php
usuario@ansible:~/ejemplo$ lynx web3.cda.netusuario@ansible:~/ejemplo$ lynx web3.cda.net/phpinfo.php
usuario@ansible:~/ejemplo$ lynx web4.cda.netusuario@ansible:~/ejemplo$ lynx web4.cda.net/phpinfo.php
(a) Crear el fichero playbook_haproxy.yml
x
---nameinstalacion y configuracion de haproxy hostshaproxy becomeyes vars haproxy_bind_address10.10.10.10 haproxy_bind_port80 haproxy_balanceroundrobin haproxy_cluster_namecluster_ansible haproxy_serversnameweb1 addressweb1.cda.net80nameweb2 addressweb2.cda.net80nameweb3 addressweb3.cda.net80nameweb4 addressweb4.cda.net80 tasksnameinstalar paquete haproxy aptname=haproxy state=present namehabilitar arranque haproxy lineinfile dest/etc/default/haproxy regexp"^ENABLED.+$" line"ENABLED=1" statepresent
namecrear fichero configuracion template srcplantillas/haproxy.cfg.j2 dest/etc/haproxy/haproxy.cfg mode0644 notifyrestart haproxy
handlersnamerestart haproxy servicename=haproxy state=restarted
nameajuste de KeepAlive hostsweb becomeyes tasksnamedeshabilitar KeepAlive replacedest='/etc/apache2/apache2.conf' regexp='KeepAlive On' replace='KeepAlive Off' notifyrestart apache2 handlersnamerestart apache2 servicename=apache2 state=restarted(b) Crear el fichero plantillas/haproxy.cfg.j2
xglobaldaemonuser haproxygroup haproxydefaultsmode httplog globaltimeout connect 10000mstimeout client 50000mstimeout server 50000msfrontend {{haproxy_cluster_name}}bind {{haproxy_bind_address}}:{{haproxy_bind_port}}mode httpstats enablestats auth cda:cdadefault_backend {{haproxy_cluster_name}}_serversbackend {{haproxy_cluster_name}}_serversbalance {{haproxy_balance}}cookie PHPSESSID prefix{% for backend in haproxy_servers %}server {{ backend.name }} {{ backend.address }} cookie {{ backend.name }} check{% endfor %}
(c) Lanzar el playbook (pedirá la contraseña de SUDO para usuario [purple])
x
usuario@ansible:~/ejemplo# ansible-playbook playbook_haproxy.yml --ask-become-pass(d) Desde un navegador web comprobar el funcionamiento del balanceador de carga accediendo a la URL haproxy.cda.net (comprobar la página de estadísticas en la URL http://haproxy.cda.net/haproxy?stats)
xxxxxxxxxxusuario@ansible:~/ejemplo$ lynx haproxy.cda.net< recarga con [CTRL]+R >Comprobar en la máquina haproxy la configuración de HAProxy creada.
Los Roles son un mecanismo que permite reutilizar Plays (tareas, variables, handler, etc).
Los Roles "empaquetan" en un directorio los elementos de un Play (tasks, handlers, variables, etc) de modo que puedan ser reutilizados en diferentes Playbooks
/etc/ansible/roles), la ubicación por defecto del usuario ($HOME/.ansible/roles) o en el directorio roles del directorio de trabajo del Playbook.Nota: Documentación Roles
Para invocar los Roles disponibles desde un Playbook, se enumeran sus nombres dentro de la sección roles
Es posible instalar nuevos Roles usando el comando ansible-galaxy install <nombre>, seleccionando uno de los Roles disponibles en Ansible Galaxy
Nota: Otro mecanismo (menos potente) para reutilizar "código" Ansible son las sentencias include. Por ejemplo:
xxxxxxxxxx---nameun play hoststodos tasksnameinstalar cosas aptname=cosas statelatestinclueotro_fichero.ymlxxxxxxxxxxroles├── rol_ejemplo1│ ├── defaults│ │ └── main.yml│ ├── files│ ├── handlers│ │ └── main.yml│ ├── meta│ │ └── main.yml│ ├── tasks│ │ └── main.yml│ ├── templates│ └── vars│ └── main.yml├── rol_ejemplo2│ ├── defaults│ │ └── main.yml... ...
Para utilizar los roles en el Playbook se vincula en la sección roles de cada Play la lista con los nombre de los roles a aplicar en dicha Play.
main.yml de las diferentes secciones del directorio de cada role (si está presente) como contenido de las secciones tasks, handlers, vars etc<pendiente>