Diferencia entre revisiones de «Ansible»

De MediaWiki
Ir a la navegación Ir a la búsqueda
 
(No se muestran 16 ediciones intermedias del mismo usuario)
Línea 1: Línea 1:
 +
 +
 +
[[File:Ansible-metodos-de-conexión-remota.png|thumb|right| Metodos de conexión remota en Ansible]]
  
 
= Introdución =
 
= Introdución =
  
−
Ansible é:
+
Ansible:
−
* unha plataforma de software libre para configurar e administrar ordenadores, permitindo a xestión da configuración e a orquestación de infraestruturas. Combina instalación multi-nodo (permite despregar configuracións de servidores e servicios por lotes), execucións de taefas ad hoc e administración de configuracións.
+
* é unha plataforma de software libre para configurar e administrar equipos, permitindo a xestión da configuración e a orquestación de infraestruturas.  
−
* un proxecto de '''código aberto''' implementado en Python e ten unha arquitectura con módulos que poden manexar prácticamente calquera sistema operativo, contorna de nube e ferramenta ou marco de administración do sistema.
+
* é un proxecto de '''código aberto''' implementado en Python e ten unha arquitectura con módulos que poden manexar prácticamente calquera sistema operativo, contorna de nube e ferramenta ou marco de administración do sistema.
 +
* é amplamente usada para xestionar a configuración de servidores, para tarefas de aprovisionamento de instancias cloud, operacións dev-ops, ...
 +
* ten unha filosofía que pode resumirse en que o estado de configuración final que queres que teña un equipo queda definido nun arquivo de texto, chamado ''playbook''
  
−
Máis datos;
+
Máis datos:
 
* Lanzamento inicial no 2012 (escrito orixialmente por Michael DeHaan, o creador da aplicación de aprovisionamento Cobbler) e posteriormente adquirido por Red Hat.
 
* Lanzamento inicial no 2012 (escrito orixialmente por Michael DeHaan, o creador da aplicación de aprovisionamento Cobbler) e posteriormente adquirido por Red Hat.
−
* Arquitectura ''agentless''. Non require un axente nos servidores cliente polo que optimiza o rendemento e evita abrir portos especiais, con utilizar só a conexión por SSH. O traballo envíaase aos ''hosts'' cando se executa Ansible. Os módulos son os programas que realizan o traballo real das tarefas dun ''play''.
+
* Combina instalación multi-nodo (permite despregar configuracións de servidores e servicios por lotes), execucións de taefas ad hoc e administración de configuracións.
 +
* Arquitectura ''agentless''. Non require un axente nos servidores cliente polo que optimiza o rendemento e evita abrir portos especiais, con utilizar só a conexión por SSH. O traballo envíaase aos ''hosts'' cando se executa Ansible. Os [https://docs.ansible.com/ansible/latest/collections/all_plugins.html#all-modules-and-plugins módulos] son os programas que realizan o traballo real das tarefas dun ''play''.
 
* Sintaxe moi sinxela con baixa curva de aprendizaxe e sen requirir coñecementos de programación
 
* Sintaxe moi sinxela con baixa curva de aprendizaxe e sen requirir coñecementos de programación
−
* Con máils de 1000 módulos disponibles. Asi para activos diferentes podemos falar a mesma lingua do dispositivo administrado; e tamén poderemos desenvolver módulos en python.
+
* Con máils de 1000 [https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html módulos] disponibles. Asi para activos diferentes podemos falar a mesma lingua do dispositivo administrado; e tamén poderemos desenvolver módulos en python.
 
* Con adoptación masiva por ser fácil de usar para os administradores de sistemas
 
* Con adoptación masiva por ser fácil de usar para os administradores de sistemas
 
* Compatible con ferramentas ''DevOps'' coma Vagrant e Jenkins.
 
* Compatible con ferramentas ''DevOps'' coma Vagrant e Jenkins.
Línea 27: Línea 33:
 
Resumindo, Ansible é unha utilidade de orquestación e administración de configuración de código aberto que pode automatizar e estandarizar a configuración de hosts remotos e máquinas virtuáis. A súa funcionalidade de orquestación permite a Ansible coordinar o lanzamento e o apagado seguro de aplicacións de varios niveles.
 
Resumindo, Ansible é unha utilidade de orquestación e administración de configuración de código aberto que pode automatizar e estandarizar a configuración de hosts remotos e máquinas virtuáis. A súa funcionalidade de orquestación permite a Ansible coordinar o lanzamento e o apagado seguro de aplicacións de varios niveles.
  
−
Así no canto de escribir ''scripts'' personalizados e individualizados, os administradores do sistema crean un ''play'' ou unha xogada de alto nivel en Ansible. Ese ''play'' realiza unha serie de tarefas no ''host'' ou grupo de ''hosts'' especificados no ''play''.
+
Así no canto de escribir ''scripts'' personalizados e individualizados, os administradores do sistema crean un ''play'' ou unha xogada de alto nivel en Ansible.  
 +
 
 +
Ese ''play'' realiza unha serie de tarefas no ''host'' ou grupo de ''hosts'' especificados no ''play''.
  
 
  Un ficheiro que contén un ou máis ''plays'' chámase ''Playbook''.
 
  Un ficheiro que contén un ou máis ''plays'' chámase ''Playbook''.
Línea 36: Línea 44:
 
* Pode modificar a configuración, pero '''NON''' a monitorea
 
* Pode modificar a configuración, pero '''NON''' a monitorea
 
* Non realiza un seguemento dos cambios realizados nos ficheiros do sistema, e de qué  usuario ou proceso realizou os cambios
 
* Non realiza un seguemento dos cambios realizados nos ficheiros do sistema, e de qué  usuario ou proceso realizou os cambios
 +
 +
== Arquitectura ==
 +
 +
[[File:Arquitectura-Cliente-Servidor-de-Ansible.png |thumb| Arquitectura Cliente Servidor de Ansible]]
 +
 +
[[File:Arquitectura-Cliente-Servidor-de-Ansible-nodos-e-plataformas.png |thumb| Arquitectura Cliente Servidor de Ansible. Nodos e plataformas xestionadas]]
 +
 +
Existen dous tipos de máquinas na arquitectura de Ansible:
 +
* o nodo de control
 +
* os hosts administrados
 +
 +
O software ansible está instalado no nodo de control e todos os seus compoñentes se manteñen nel.
 +
 +
Os hosts administrados enumeranse nun inventario de host ,un ficheirode texto no nodo de control que inclue unha lista de nomes de host administrados FQDN (''fully qualified domain name'') ou enderezos IP.
 +
 +
Ansible utiliza SSH coma protocolo de comuncación cos hosts administados. Os módul referenciados nos playbooks copianse nos hosts administrados. Despois se executan, en orde, cos argumentos especificados no playbook. Os usuarios de Ansible poden escribir os seus propios módulos personalizados se é preciso pero os módulo s principais que veñen con Ansible poden realizar a maioría das tarefas de administración do sistema.
 +
 +
== Primeiros pasos ==
 +
 +
Traballar con Ansible hai que comprender os seguintes termos:
 +
; Host Inventory
 +
: é unha descrición dos nodos (equipos a administrar) ós que poderemos acceder usando Ansible. O inventory máis básico contén ós nodos agrupados por grupos (ubicacións xeográficas, servizos ou calquera outro criterio que consideremos) e as direccións IP ou nomes.
 +
 +
Un exemplo de inventory podería ser:
 +
<pre>
 +
$ cat /etc/ansible/hosts
 +
[infor1]
 +
192.168.1.193
 +
192.168.1.194
 +
192.168.1.195
 +
 +
[profesores]
 +
192.168.1.201
 +
192.168.2.201
 +
192.168.3.201
 +
</pre>
 +
 +
; Playbooks
 +
: trátase de arquivos de texto onde se describen configuracións ou tarefas de despregue. Dentro dun playbook haberá 'xogadas' (plays) onde se indican unha serie de tarefas a executar; por exemplo, actualizar a lista de paquetes, instalar o servidor web apache, activar o módulo ssl, copiar os arquivos de configuración dos sitios web a aloxar, crear as carpetas dos DocumentRoot dos sitios e copiar os arquivos que forma os sitios, activar os sitios web, reiniciar o servidor Apache, ... Os playbooks poden verse como arquivos que describen a configuración desexada para un equipo ou conxunto de equipos.
 +
 +
No seguinte exemplo podemos ver un playbook que fixera no seu día para por en marcha e configurar os equipos Linux Lubuntu dunha clase de informática de ESO/Bach do centro. Podese ver como unha foto do estado que quería acadar nos equipos e que se resume en que:
 +
* Copiamos a todos os equipos da clase un arquivo sources.list para que todos teñan e usen os mesmos repositorios.
 +
* Copiamos a todos os equipos da clase o arquivo 01apt-cacherng-proxy para que usen o apt-cacher-ng e se aceleren os procesos de instalación/actualización de paquetes.
 +
* Copiamos en /etc/skel unha plantilla para que os usuarios do equipo partan da mesma configuración de escritorio (iconas, menús, ligazóns de favoritos, ...).
 +
* Creamos uns usuarios e configuramos o contrasinal de root.
 +
* Configuramos a sincronización de hora para que vaian a un servidor de hora interno no IES.
 +
* Borramos algúns programas que viñan coa instalación básica de Lubuntu (Abiword e gnumeric).
 +
* Engadimos algúns repositorios ppa para ter as últimas versións de Inkscape e LibreOffice.
 +
* Actualizamos os equipos e instalamos unha colección de paquetes indicada no arquivo paquetes_ESO1.yml (arandr, libreoffice, libreoffice-l10n-es, vlc, audacity, inkscape, ...).
 +
* Deshabilitamos a impresión nos equipos.
 +
 +
<pre>
 +
---
 +
- hosts: infor1
 +
  become: yes
 +
  remote_user: magasix
 +
  become_method: sudo
 +
  gather_facts: false
 +
  vars_files:
 +
  - /media/DATOS/Tutoriales/ansible/paquetes_ESO1.yml
 +
   
 +
  tasks:
 +
  - name: copiar fichero de repositorios
 +
    copy: src=/media/DATOS/Tutoriales/ansible/sources.list_ESO1.txt dest=/etc/apt/sources.list
 +
 +
  - name: copiar fichero de apt-cacherng-proxy
 +
    copy: src=/media/DATOS/Tutoriales/ansible/01apt-cacherng-proxy_ESO1.txt dest=/etc/apt/apt.conf.d/01apt-cacherng-proxy
 +
 +
  - name: crear grupo alumnos
 +
    group: name=alumnos state=present
 +
 +
  - name: copiar skel
 +
    copy: src=/media/DATOS/Tutoriales/ansible/skel/ dest=/etc/skel/
 +
 +
  - name: crear usuario alumno
 +
    user: name=alumno comment="Alumno IES" shell=/bin/bash groups=alumnos state=present
 +
 +
  - name: password en blanco
 +
    shell: passwd -d alumno
 +
 +
  - name: crear usuario alumno TICs abc123.
 +
    user: name=alumnotics comment="Alumno TICs" shell=/bin/bash groups=alumnos password=ylMqA85PRieLg state=present
 +
 +
  - name: password a root
 +
    user: name=root password=rDQVP5utaEC9E
 +
 +
  - name: desinstalar ntp
 +
    apt: name=ntp state=absent purge=yes
 +
 +
  - name: configurar ntpdate 
 +
    copy: src=/media/DATOS/Tutoriales/ansible/ntpdate.conf_ESO1.txt dest=/etc/default/ntpdate
 +
 +
  - name: fijar lubuntu-desktop
 +
    shell: apt-mark manual lubuntu-desktop
 +
 +
  - name: borrar abiword
 +
    apt: name=abiword state=absent purge=yes
 +
 +
  - name: borrar gnumeric
 +
    apt: name=gnumeric state=absent purge=yes
 +
 +
  - name: repositorio inkscape
 +
    apt_repository: repo='ppa:inkscape.dev/stable' update_cache=no
 +
 
 +
  - name: repositorio libreoffice 5
 +
    apt_repository: repo='ppa:libreoffice/ppa' update_cache=no
 +
   
 +
  - name: actualizar equipo
 +
    apt: upgrade=dist update_cache=yes
 +
 +
  - name: instalacion de paquetes
 +
    apt: pkg={{ item }} state=installed
 +
    with_items: '{{system_packages}}'
 +
 +
  - name: deshabilitar impresion
 +
    service: name=cups state=stopped enabled=no
 +
</pre>
 +
 +
No exemplo podemos ver que aparecen palabras como user, shell, apt,_repository, apt, service, ..., e que correspóndense con nomes de módulos de ansible. Os módulos permiten efectuar tarefas de configuración nos equipos a administrar; por exemplo, o módulo apt permite xestionar paquetes .deb en equipos Debian/Ubuntu.
 +
 +
Pódese ver na sección de documentación todos os módulos dos que dispón Ansible:
 +
 +
Módulos Packaging
 +
 +
Fig. Módulos para a xestión de paquetes en Ansible
 +
 +
Para traballar con Ansible únicamente precisamos o seguinte:
 +
* Un nodo de xestión con Ansible instalado (ten que ser unha máquina Linux).
 +
* Nodo/s a xestionar con ssh instalado e configurado para permitir as conexións dende o nodo xestor. A diferenza doutro software semellante, como Puppet, Chef ou Salt, non é preciso instalar ningún software axente nos nodos administrados. Os nodos a administrar poden ser Linux ou Windows.
 +
 +
Resumindo o funcionamento nunha imaxe: as tarefas/configuracións recollidas no Playbook realizaranse no equipo indicado no Host Inventory, usando unha canle ssh para comunicarse o nodo xestor co nodo administrado.
 +
 +
Administración con ansible
 +
 +
Fig. Administración con Ansible. Fonte: 19 Minutes with Ansible
 +
 +
Se en vez de lanzar o playbook contra un equipo lánzase contra un grupo de equipos, teremos un grupo de equipos que comparten a mesma configuración. No exemplo anterior, lanzar o playbook contra os 20 Lubuntus recén instalados na aula, implica que ó cabo dun rato teremos 20 equipos configurados exactamente igual. Traballar con playbooks que recollan os cambios de configuración/tarefas a realizar facilita o mantemento dos sistemas, permite incorporar novos equipos que teñan exactamente a mesma configuración que o resto, ... Case podemos pensar nos playbooks como a nosa infraestrutura documentada.
 +
 +
Administración con ansible
 +
 +
Fig. Lanzando un playbook contra un grupo de nodos. Fonte: 19 Minutes with Ansible
 +
 +
A modo de exemplo amoso a saída resultante de lanzar o playbook anterior contra 3 equipos e podemos observar como se van realizando as diferentes tarefas (''tasks''), levando a todos os equipos ó mesmo estado de configuración:
 +
$ ansible-playbook lubuntu_ies_alumnos_ntpdate_ESO1_casa.yml -K
 +
<pre>
 +
SUDO password:
 +
 +
PLAY ***************************************************************************
 +
 +
TASK [copiar fichero de repositorios] ******************************************
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.194]
 +
 +
TASK [copiar fichero de apt-cacherng-proxy] ************************************
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.194]
 +
 +
TASK [crear grupo alumnos] *****************************************************
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.195]
 +
 +
TASK [copiar skel] *************************************************************
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.194]
 +
 +
TASK [crear usuario alumno] ****************************************************
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.193]
 +
 +
TASK [password en blanco] ******************************************************
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.193]
 +
 +
TASK [crear usuario alumno TICs abc123.] ***************************************
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.195]
 +
 +
TASK [password a root] *********************************************************
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.195]
 +
 +
TASK [desinstalar ntp] *********************************************************
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.193]
 +
 +
TASK [configurar ntpdate] ******************************************************
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.195]
 +
 +
TASK [fijar lubuntu-desktop] ***************************************************
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.193]
 +
 +
TASK [borrar abiword] **********************************************************
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.193]
 +
 +
TASK [borrar gnumeric] *********************************************************
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.193]
 +
 +
TASK [repositorio inkscape] ****************************************************
 +
changed: [192.168.1.195]
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.193]
 +
 +
TASK [repositorio libreoffice 5] ***********************************************
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.195]
 +
 +
TASK [actualizar equipo] *******************************************************
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.195]
 +
 +
TASK [instalacion de paquetes] *************************************************
 +
ok: [192.168.1.194] => (item=[u'build-essential', u'arandr', u'libreoffice', u'libreoffice-l10n-es', u'lubuntu-restricted-addons', u'lubuntu-restricted-extras', u'ubuntu-restricted-extras', u'ubuntu-restricted-addons', u'icedtea-plugin', u'vlc', u'audacity', u'inkscape', u'openshot', u'sweethome3d', u'sweethome3d-furniture', u'sweethome3d-furniture-nonfree', u'gimp', u'gimp-data', u'gimp-data-extras', u'gimp-dcraw', u'gimp-gmic', u'gimp-help-es', u'gimp-plugin-registry', u'scribus', u'scribus-template', u'scribus-doc'])
 +
ok: [192.168.1.193] => (item=[u'build-essential', u'arandr', u'libreoffice', u'libreoffice-l10n-es', u'lubuntu-restricted-addons', u'lubuntu-restricted-extras', u'ubuntu-restricted-extras', u'ubuntu-restricted-addons', u'icedtea-plugin', u'vlc', u'audacity', u'inkscape', u'openshot', u'sweethome3d', u'sweethome3d-furniture', u'sweethome3d-furniture-nonfree', u'gimp', u'gimp-data', u'gimp-data-extras', u'gimp-dcraw', u'gimp-gmic', u'gimp-help-es', u'gimp-plugin-registry', u'scribus', u'scribus-template', u'scribus-doc'])
 +
ok: [192.168.1.195] => (item=[u'build-essential', u'arandr', u'libreoffice', u'libreoffice-l10n-es', u'lubuntu-restricted-addons', u'lubuntu-restricted-extras', u'ubuntu-restricted-extras', u'ubuntu-restricted-addons', u'icedtea-plugin', u'vlc', u'audacity', u'inkscape', u'openshot', u'sweethome3d', u'sweethome3d-furniture', u'sweethome3d-furniture-nonfree', u'gimp', u'gimp-data', u'gimp-data-extras', u'gimp-dcraw', u'gimp-gmic', u'gimp-help-es', u'gimp-plugin-registry', u'scribus', u'scribus-template', u'scribus-doc'])
 +
 +
TASK [deshabilitar impresion] **************************************************
 +
changed: [192.168.1.193]
 +
changed: [192.168.1.194]
 +
changed: [192.168.1.195]
 +
 +
PLAY RECAP *********************************************************************
 +
192.168.1.193              : ok=18  changed=18  unreachable=0    failed=0 
 +
192.168.1.194              : ok=18  changed=18  unreachable=0    failed=0 
 +
192.168.1.195              : ok=18  changed=18  unreachable=0    failed=0 
 +
</pre>
 +
 +
=== Modo ''ad-hoc'' ===
 +
 +
Aínda que traballar con playbooks é o recomendado, Ansible permite traballar en modo ad-hoc; é dicir, executar tarefas sen necesidade de crear e gardar un playbook. Por exemplo, comprobar o estado dos equipos, executar comandos do sistema, copias arquivos en calquera sentido, ...
 +
 +
A modo de exemplo:
 +
$ ansible infor1 -m ping -u magasix
 +
<pre>
 +
192.168.1.194 | SUCCESS => {
 +
    "changed": false,
 +
    "ping": "pong"
 +
}
 +
192.168.1.195 | SUCCESS => {
 +
    "changed": false,
 +
    "ping": "pong"
 +
}
 +
192.168.1.193 | SUCCESS => {
 +
    "changed": false,
 +
    "ping": "pong"
 +
}
 +
</pre>
 +
 +
$ ansible infor1 -m shell -a "shutdown -h now" -u magasix --sudo -K
 +
<pre>
 +
SUDO password:
 +
192.168.1.194 | SUCCESS | rc=0 >>
 +
192.168.1.195 | SUCCESS | rc=0 >>
 +
192.168.1.193 | SUCCESS | rc=0 >>
 +
</pre>
  
 
== Alternativas ==
 
== Alternativas ==
Línea 95: Línea 376:
 
| 2012
 
| 2012
 
|}
 
|}
 +
 +
= Escenario con Ansible =
 +
== Configuración do escenario ==
 +
 +
O obxectivo deste Escenario 8D é facer unha primeira aproximación a Ansible e ver as posibilidades que proporciona ós administradores de sistemas como ferramenta avanzada de configuración e automatización. O noso obxectivo será montar un sistema con tres servidores web idénticos que imos supoñer que forman parte dun backend e teñen as seguintes características:
 +
* Hai que instalar e configurar fail2ban para que no arquivo de configuración jail.local o tempo de búsqueda sexa de 10 minutos, o de baneo 20 minutos e o número máximo de intentos sexa 3.
 +
* Hai que configurar o syslog para que a reducción da repetición de mensaxes se desactive ( $RepeatedMsgReduction off )
 +
* Os servidores corren Apache e php 8.2
 +
* Responden a solicitudes por http e https (con certificado propio autofirmado) dirixidas a www.manuel2023.test
 +
* Teñen unha páxina web index.php co seguinte contido:
 +
<pre>
 +
<?php
 +
echo "
 +
<html>
 +
<head>
 +
<title>Sitio web en ${_SERVER["SERVER_ADDR"]}</title>
 +
</head>
 +
<body>
 +
<img src=”imaxes/logo.png” alt=”logotipo”>
 +
<h1>Sitio Web www.manuel2023.test</h1>
 +
Est&aacute;s en ${_SERVER["SERVER_ADDR"]}
 +
</body>
 +
</html>";
 +
?>
 +
</pre>
 +
* Non se permiten opcións como listado de directorios, seguir enlaces simbólicos, ...
 +
* Non se permite personalizar as opcións usando arquivos htaccess.
 +
* O sitio web ten os seus propios ficheros de log (o mesmo tanto para o acceso por http como https).
 +
 +
== Instalación e comandos ad-hoc ==
 +
 +
=== Instalación de Ansible ===
 +
 +
[https://docs.ansible.com/ansible/latest/installation_guide/installation_distros.html Instalaremos Ansible] nun equipo Linux que exercerá de nodo administrador e os pasos a seguir son:
 +
$ sudo apt update
 +
$ sudo apt install software-properties-common
 +
$ sudo apt-add-repository ppa:ansible/ansible
 +
$ sudo apt install ansible
 +
 +
=== Creación do inventory ===
 +
 +
Unha vez rematada a instalación temos que crear un inventory cos equipos que queremos administrar.
 +
 +
'''NOTA'''. No caso de non estar creado o directorio /etc/ansible, hai que proceder a crealo mediante:
 +
mkdir /etc/ansible
 +
 +
$ sudo nano /etc/ansible/hosts
 +
<pre>
 +
# grupo contedores
 +
[incus]
 +
192.0.2.191
 +
192.0.2.192
 +
192.0.2.193
 +
</pre>
 +
 +
No inventory pódese engadir máis información asociada ós nodos a administrar como o usuario co que Ansible iniciará sesión, que no noso caso pode ser o usuario ubuntu ou o usuario magasix creada no aprovisionamento dos contedores:
 +
$ sudo nano /etc/ansible/hosts
 +
<pre>
 +
# grupo contedores
 +
[incus]
 +
192.0.2.191
 +
192.0.2.192
 +
192.0.2.193
 +
 +
[incus:vars]
 +
ansible_user=ubuntu
 +
</pre>
 +
 +
=== Autenticación mediante identidades dixitais ===
 +
 +
Ansible usará ssh para entrar nos equipos a xestionar e unha práctica recomendada é [http://PENDIENTE autenticarse mediante identidades dixitais como se explicou PENDIENTE] polo que procedemos a autorizar unha clave dixital e a indicalo no inventory. Usamos o usuario ubuntu con contrasinal abc123.
 +
 +
$ ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@192.0.2.191
 +
$ ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@192.0.2.192
 +
$ ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@192.0.2.193
 +
 +
Despois de autorizar a clave, verificar que é posible conectarse.
 +
 +
$ sudo nano /etc/ansible/hosts
 +
<pre>
 +
# grupo contedores
 +
[incus]
 +
192.0.2.191
 +
192.0.2.192
 +
192.0.2.193
 +
 +
[incus:vars]
 +
ansible_ssh_user=ubuntu
 +
ansible_ssh_private_key_file=~/.ssh/id_rsa
 +
ansible_python_interpreter=/usr/bin/python3
 +
</pre>
 +
 +
Vemos que no inventory é posible engadir variables asociadas a equipos ou grupos de equipos como ansible_ssh_private_key_file e ansible_python_interpreter (permite indicar que intérprete de python hai nos hosts sen necesidade que o detecte ansible).
 +
 +
=== Verificación con ping ===
 +
 +
Agora podemos verificar que Ansible é capaz de conectarse cos servers executando un 'ping':
 +
 +
$ ansible incus -m ansible.builtin.ping
 +
<pre>
 +
192.0.2.191 | SUCCESS => {
 +
    "changed": false,
 +
    "ping": "pong"
 +
}
 +
192.0.2.193 | SUCCESS => {
 +
    "changed": false,
 +
    "ping": "pong"
 +
}
 +
192.0.2.192 | SUCCESS => {
 +
    "changed": false,
 +
    "ping": "pong"
 +
}
 +
</pre>
 +
 +
=== Comandos AD-HOC ===
 +
 +
Os comandos ad-hoc están para cando se quere facer algo pero non queremos gardarlo para outras ocasións ou non se considera necesario escribir un playbook.  Aínda que para aproveitar todo o potencial de Ansible están os playbooks, os comandos ad-hoc permiten facer cosas de forma rápida. Por exemplo, facemos un ss -ltnp:
 +
$ ansible incus -m ansible.builtin.shell -a 'ss -ltnp'
 +
<pre>
 +
192.0.2.193 | CHANGED | rc=0 >>
 +
State    Recv-Q  Send-Q    Local Address:Port    Peer Address:Port  Process 
 +
LISTEN  0        4096      127.0.0.53%lo:53            0.0.0.0:*             
 +
LISTEN  0        128              0.0.0.0:22            0.0.0.0:*             
 +
LISTEN  0        128                [::]:22              [::]:*             
 +
192.0.2.192 | CHANGED | rc=0 >>
 +
State    Recv-Q  Send-Q    Local Address:Port    Peer Address:Port  Process 
 +
LISTEN  0        4096      127.0.0.53%lo:53            0.0.0.0:*             
 +
LISTEN  0        128              0.0.0.0:22            0.0.0.0:*             
 +
LISTEN  0        128                [::]:22              [::]:*             
 +
192.0.2.191 | CHANGED | rc=0 >>
 +
State    Recv-Q  Send-Q    Local Address:Port    Peer Address:Port  Process 
 +
LISTEN  0        4096      127.0.0.53%lo:53            0.0.0.0:*             
 +
LISTEN  0        128              0.0.0.0:22            0.0.0.0:*             
 +
LISTEN  0        128                [::]:22              [::]:*
 +
</pre>
 +
 +
Hai que sinalar qué ansible.builtin.shell é o nome completo do módulo de Ansible e shell é a forma abreviada.
 +
 +
$  ansible incus -m shell -a 'ss -ltnp'
 +
<pre>
 +
192.0.2.191 | CHANGED | rc=0 >>
 +
State    Recv-Q  Send-Q    Local Address:Port    Peer Address:Port  Process 
 +
LISTEN  0        4096      127.0.0.53%lo:53            0.0.0.0:*             
 +
LISTEN  0        128              0.0.0.0:22            0.0.0.0:*             
 +
LISTEN  0        128                [::]:22              [::]:*             
 +
192.0.2.193 | CHANGED | rc=0 >>
 +
State    Recv-Q  Send-Q    Local Address:Port    Peer Address:Port  Process 
 +
LISTEN  0        4096      127.0.0.53%lo:53            0.0.0.0:*             
 +
LISTEN  0        128              0.0.0.0:22            0.0.0.0:*             
 +
LISTEN  0        128                [::]:22              [::]:*             
 +
192.0.2.192 | CHANGED | rc=0 >>
 +
State    Recv-Q  Send-Q    Local Address:Port    Peer Address:Port  Process 
 +
LISTEN  0        4096      127.0.0.53%lo:53            0.0.0.0:*             
 +
LISTEN  0        128              0.0.0.0:22            0.0.0.0:*             
 +
LISTEN  0        128                [::]:22              [::]:*
 +
</pre>
 +
 +
Aínda que en moitos titoriais de Ansible aparece a forma abreviada, os desenvolvedores de Ansible recomendan usar o nome completo en vez da abreviada para evitar posibles conflictos.
 +
 +
No caso de querer executar o comando nos hosts como administrador pódese empregar as opcións -b e -K:
 +
* -b (become): indica que se quere escalar privilexios nos hosts
 +
* -K: pregunta polo contrasinal para elevar os privilexios
 +
 +
$ ansible incus -m ansible.builtin.shell -a 'ss -ltnp' -b -K
 +
<pre>
 +
BECOME password:
 +
192.0.2.192 | CHANGED | rc=0 >>
 +
State    Recv-Q    Send-Q      Local Address:Port        Peer Address:Port    Process                                                                       
 +
LISTEN    0        4096        127.0.0.53%lo:53              0.0.0.0:*        users:(("systemd-resolve",pid=165,fd=13))                                     
 +
LISTEN    0        128                0.0.0.0:22              0.0.0.0:*        users:(("sshd",pid=220,fd=3))                                                 
 +
LISTEN    0        128                  [::]:22                  [::]:*        users:(("sshd",pid=220,fd=4))                                                 
 +
192.0.2.191 | CHANGED | rc=0 >>
 +
State    Recv-Q    Send-Q      Local Address:Port        Peer Address:Port    Process                                                                       
 +
LISTEN    0        4096        127.0.0.53%lo:53              0.0.0.0:*        users:(("systemd-resolve",pid=166,fd=13))                                     
 +
LISTEN    0        128                0.0.0.0:22              0.0.0.0:*        users:(("sshd",pid=229,fd=3))                                                 
 +
LISTEN    0        128                  [::]:22                  [::]:*        users:(("sshd",pid=229,fd=4))                                                 
 +
192.0.2.193 | CHANGED | rc=0 >>
 +
State    Recv-Q    Send-Q      Local Address:Port        Peer Address:Port    Process                                                                       
 +
LISTEN    0        4096        127.0.0.53%lo:53              0.0.0.0:*        users:(("systemd-resolve",pid=166,fd=13))                                     
 +
LISTEN    0        128                0.0.0.0:22              0.0.0.0:*        users:(("sshd",pid=211,fd=3))                                                 
 +
LISTEN    0        128                  [::]:22                  [::]:*        users:(("sshd",pid=211,fd=4)) 
 +
</pre>
 +
 +
O usuario ubuntu está autorizado para facer sudo sen necesidade de introducir o contrasinal, polo que no noso escenario o comando anterior podería executarse sen -K. Sinalar tamén que é posible gardar contrasinais cifradas empregando o concepto de vault.
 +
 +
=== Posibles operacións ===
 +
 +
Podemos copiar arquivos de local a remoto e viceversa, xestionar usuarios, servizos, paquetes, ...
 +
 +
Por exemplo, para copìar un arquivo local chamado backup.yml en todos os servidores podería executar:
 +
$ ansible incus -m ansible.builtin.copy -a "src=config_backup.yml dest=/home/ubuntu/config.yml"
 +
<pre>
 +
192.0.2.192 | CHANGED => {
 +
    "changed": true,
 +
    "checksum": "39244f4abbbb552d9d3e00eb27d05cfd6b8bfa44",
 +
    "dest": "/home/ubuntu/config.yml",
 +
    "gid": 1001,
 +
    "group": "ubuntu",
 +
    "md5sum": "1f5b15fb9e83f47d213637efe71f3d20",
 +
    "mode": "0664",
 +
    "owner": "ubuntu",
 +
    "size": 424,
 +
    "src": "/home/ubuntu/.ansible/tmp/ansible-tmp-1685284269.5834956-25446-44703324742452/source",
 +
    "state": "file",
 +
    "uid": 1001
 +
}
 +
192.0.2.191 | CHANGED => {
 +
    "changed": true,
 +
    "checksum": "39244f4abbbb552d9d3e00eb27d05cfd6b8bfa44",
 +
    "dest": "/home/ubuntu/config.yml",
 +
    "gid": 1001,
 +
    "group": "ubuntu",
 +
    "md5sum": "1f5b15fb9e83f47d213637efe71f3d20",
 +
    "mode": "0664",
 +
    "owner": "ubuntu",
 +
    "size": 424,
 +
    "src": "/home/ubuntu/.ansible/tmp/ansible-tmp-1685284269.628682-25444-43771047461490/source",
 +
    "state": "file",
 +
    "uid": 1001
 +
}
 +
192.0.2.193 | CHANGED => {
 +
    "changed": true,
 +
    "checksum": "39244f4abbbb552d9d3e00eb27d05cfd6b8bfa44",
 +
    "dest": "/home/ubuntu/config.yml",
 +
    "gid": 1001,
 +
    "group": "ubuntu",
 +
    "md5sum": "1f5b15fb9e83f47d213637efe71f3d20",
 +
    "mode": "0664",
 +
    "owner": "ubuntu",
 +
    "size": 424,
 +
    "src": "/home/ubuntu/.ansible/tmp/ansible-tmp-1685284269.6718416-25448-47330558216673/source",
 +
    "state": "file",
 +
    "uid": 1001
 +
}
 +
</pre>
 +
$ ansible incus -m ansible.builtin.shell -a 'ls -lhF'
 +
<pre>
 +
192.0.2.193 | CHANGED | rc=0 >>
 +
total 2,5K
 +
-rw-rw-r-- 1 ubuntu ubuntu 2,1K mar  1 17:10 config.yml
 +
192.0.2.192 | CHANGED | rc=0 >>
 +
total 2,5K
 +
-rw-rw-r-- 1 ubuntu ubuntu 2,1K mar  1 17:10 config.yml
 +
192.0.2.191 | CHANGED | rc=0 >>
 +
total 2,5K
 +
-rw-rw-r-- 1 ubuntu ubuntu 2,1K mar  1 17:10 config.yml
 +
</pre>
 +
 +
Na páxina [http://docs.ansible.com/ansible/latest/intro_adhoc.html Introduction To Ad-Hoc Commands] podemos ver máis exemplos desta forma de usar Ansible.
 +
 +
== Playbooks ==
 +
 +
Despois de revisar por riba o uso de ansible chegamos o punto forte que son os playbooks. Como primeira aproximación executaremos o playbook actualizar.yml que permitirá actualizar os equipo servidores e como pode verse é moi sinxelo de entender:
 +
* Aplícase os equipo incus definidos no inventory.
 +
* Execútase como administrador (become: yes)
 +
* Actualiza a lista de paquetes e fai unha actualización do sistema.
 +
 +
<pre>
 +
---
 +
- hosts: incus
 +
  become: yes
 +
  tasks:
 +
    - name: actualizar lista de paquetes y el sistema
 +
      apt:
 +
        update_cache: yes
 +
        cache_valid_time: 3600
 +
    - name: actualizar sistema       
 +
      apt: 
 +
        upgrade: dist
 +
</pre>
 +
 +
Para lanzalo imos a carpeta de devops e:
 +
$ ansible-playbook actualizar.yml -K
 +
<pre>
 +
SUDO password:
 +
 +
PLAY [incus] *************************************************************************************************************************************************************************************
 +
 +
TASK [Gathering Facts] *************************************************************************************************************************************************************************
 +
ok: [192.0.2.191]
 +
ok: [192.0.2.192]
 +
ok: [192.0.2.193]
 +
 +
TASK [actualizar lista de paquetes y el sistema] ***********************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.191]
 +
 +
TASK [actualizar sistema] **********************************************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.191]
 +
 +
PLAY RECAP *************************************************************************************************************************************************************************************
 +
192.0.2.191                : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
 +
192.0.2.192                : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
 +
192.0.2.193                : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
 +
</pre>
 +
 +
Todas as actuacións a realizar para levar ós servidores ó estado de configuración indicado no enunciado sabemos facelas a man como fixemos ó longo de diversos escenarios do curso; sen embargo, agora imos a recollelas nun playbook que permitirá automatizar a súa execución. Non é obxectivo deste apartado explicar exhaustivamente como facelo; xa que Ansible daría para un curso enteiro, pero si revisar o playbook server-apache.yml vendo que é moi sinxelo de entender e executalo para ver a súa potencialidade.
 +
 +
Definimos os equipos ós que se vai aplicar o playbook que executarase como administrador e usando as variables recollidas no arquivo vars.yml
 +
<pre>
 +
---
 +
- hosts: incus
 +
  become: yes
 +
  vars_files:
 +
    - vars.yml
 +
</pre>
 +
 +
Actualizamos a listaxe de paquetes e despois instalamos os seguintes:   
 +
<pre>
 +
    - name: instalar paquetes
 +
      ansible.builtin.apt:
 +
        name:
 +
          - curl
 +
          - unzip
 +
          - fail2ban
 +
          - apache2
 +
          - php
 +
          - php-cli
 +
          - php-common
 +
          - php-curl
 +
          - php-gd
 +
          - libapache2-mod-php
 +
        state: latest
 +
        update_cache: yes
 +
        cache_valid_time: 3600
 +
</pre>
 +
 +
Creamos o arquivo jail.local a partir do jail.conf e procedemos a reemprazar os valores por defecto dos parámetros de configuración polos pedidos:
 +
<pre>
 +
    - name: crear jail.local
 +
      ansible.builtin.copy:
 +
        src: /etc/fail2ban/jail.conf
 +
        dest: /etc/fail2ban/jail.local
 +
        owner: root
 +
        group: root
 +
        mode: 0644
 +
        remote_src: True
 +
 +
    - name: modificar parametro bantime en jail.local
 +
      ansible.builtin.lineinfile:
 +
        path: /etc/fail2ban/jail.local
 +
        regexp: '^bantime  = 10m'
 +
        line: 'bantime  = 1200'
 +
        state: present
 +
      notify: reiniciar fail2ban
 +
 +
    - name: modificar parametro findtime en jail.local
 +
      ansible.builtin.lineinfile:
 +
        path: /etc/fail2ban/jail.local
 +
        regexp: '^findtime  = 10m'
 +
        line: 'findtime = 300'
 +
        state: present
 +
      notify: reiniciar fail2ban
 +
 +
    - name: modificar parametro maxretry en jail.local
 +
      ansible.builtin.replace:
 +
        path: /etc/fail2ban/jail.local
 +
        regexp: '^maxretry = 5'
 +
        replace: 'maxretry = 3'
 +
      notify: reiniciar fail2ban
 +
Anulamos a reducción de mensaxe no rsyslog:
 +
    - name: anular reduccion mensajes rsyslog
 +
      ansible.builtin.lineinfile:
 +
        path: /etc/rsyslog.conf
 +
        regexp: '^\$RepeatedMsgReduction on'
 +
        line: '$RepeatedMsgReduction off'
 +
        state: present
 +
        backrefs: yes
 +
      notify: reiniciar syslog
 +
</pre>
 +
 +
Asegurámonos que Apache e fail2ban estén funcionando:
 +
<pre>
 +
    - name: Arrancar Apache y fail2ban
 +
      ansible.builtin.service: name={{ item }} state=started enabled=yes
 +
      with_items:
 +
        - apache2
 +
        - fail2ban
 +
</pre>
 +
Habilitamos o módulo ssl para poder configurar o https:
 +
<pre>
 +
    - name: habilitar módulo ssl
 +
      community.general.apache2_module:
 +
        state: present
 +
        name: ssl 
 +
      notify: reiniciar Apache
 +
</pre>
 +
 +
Engadimos o virtualhost http e https para o dominio:
 +
<pre>
 +
    - name: añadir virtualhost para el dominio
 +
      ansible.builtin.template:
 +
        src: templates/sitio_web.conf.j2
 +
        dest: /etc/apache2/sites-available/{{ nombre_dominio }}.conf
 +
        owner: root
 +
        group: root
 +
        mode: 0644
 +
 +
    - name: añadir virtualhost https para el dominio
 +
      ansible.builtin.template:
 +
        src: templates/sitio_web_https.conf.j2
 +
        dest: /etc/apache2/sites-available/{{ nombre_dominio }}_https.conf
 +
        owner: root
 +
        group: root
 +
        mode: 0644
 +
</pre>
 +
 +
Copiamos os certificados e as páxinas do sitio web:
 +
<pre>
 +
    - name: copiar certificados sitio web
 +
      ansible.builtin.copy:
 +
        src: '{{ item }}'
 +
        dest: /etc/apache2/certificados/
 +
        owner: root
 +
        group: root
 +
        mode: 0644
 +
      with_fileglob:
 +
      - '{{ nombre_dominio }}.*'
 +
 +
    - name: copiar sitio web
 +
      ansible.builtin.copy:
 +
        src: web/
 +
        dest: '{{ documentroot }}'
 +
        owner: root
 +
        group: root
 +
        mode: 0644
 +
</pre>
 +
 +
Habilitamos os sitios web http/https e deshabilitamos o sitio por defecto:
 +
<pre>
 +
    - name: habilitar sitio web
 +
      ansible.builtin.file:
 +
        src: /etc/apache2/sites-available/{{ nombre_dominio }}.conf
 +
        dest: /etc/apache2/sites-enabled/{{ nombre_dominio }}.conf
 +
        state: link
 +
      notify: reload Apache
 +
 +
    - name: habilitar sitio web https
 +
      ansible.builtin.file:
 +
        src: /etc/apache2/sites-available/{{ nombre_dominio }}_https.conf
 +
        dest: /etc/apache2/sites-enabled/{{ nombre_dominio }}_https.conf
 +
        state: link
 +
      notify: reload Apache
 +
 +
    - name: deshabilitar sitio por defecto
 +
      ansible.builtin.file:
 +
        path: /etc/apache2/sites-enabled/000-default.conf
 +
        state: absent
 +
      notify: reload Apache
 +
</pre>
 +
 +
Definimos os handler que encárganse de reiniciar os servizos cando haxa cambios na configuración:
 +
<pre>
 +
  handlers:
 +
    - name: reiniciar Apache
 +
      ansible.builtin.service:
 +
        name: apache2
 +
        state: restarted
 +
 +
    - name: reload Apache
 +
      ansible.builtin.service:
 +
        name: apache2
 +
        state: reloaded
 +
 +
    - name: reiniciar fail2ban
 +
      ansible.builtin.service:
 +
        name: fail2ban
 +
        state: restarted
 +
 +
    - name: reiniciar syslog
 +
      ansible.builtin.service:
 +
        name: rsyslog
 +
        state: restarted           
 +
</pre>
 +
 +
Lanzamos o playbook:
 +
$ ansible-playbook server-apache.yml -K
 +
<pre>
 +
BECOME password:
 +
 +
PLAY [incus] **************************************************************************************************************************************************************************************
 +
 +
TASK [Gathering Facts] **************************************************************************************************************************************************************************
 +
ok: [192.0.2.193]
 +
ok: [192.0.2.191]
 +
ok: [192.0.2.192]
 +
 +
TASK [instalar paquetes] ************************************************************************************************************************************************************************
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.192]
 +
 +
TASK [crear jail.local] *************************************************************************************************************************************************************************
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.192]
 +
 +
TASK [modificar parametro bantime en jail.local] ************************************************************************************************************************************************
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.192]
 +
 +
TASK [modificar parametro findtime en jail.local] ***********************************************************************************************************************************************
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.193]
 +
 +
TASK [modificar parametro maxretry en jail.local] ***********************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
 +
TASK [anular reduccion mensajes rsyslog] ********************************************************************************************************************************************************
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.192]
 +
 +
TASK [Arrancar Apache y fail2ban] ***************************************************************************************************************************************************************
 +
ok: [192.0.2.191] => (item=apache2)
 +
ok: [192.0.2.193] => (item=apache2)
 +
ok: [192.0.2.192] => (item=apache2)
 +
ok: [192.0.2.193] => (item=fail2ban)
 +
ok: [192.0.2.191] => (item=fail2ban)
 +
ok: [192.0.2.192] => (item=fail2ban)
 +
 +
TASK [habilitar módulo ssl] *********************************************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.191]
 +
 +
TASK [añadir virtualhost para el dominio] *******************************************************************************************************************************************************
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.192]
 +
 +
TASK [añadir virtualhost https para el dominio] *************************************************************************************************************************************************
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.192]
 +
 +
TASK [copiar certificados sitio web] ************************************************************************************************************************************************************
 +
changed: [192.0.2.191] => (item=/home/manuel/devops/www.manuel2023.test.key)
 +
changed: [192.0.2.192] => (item=/home/manuel/devops/www.manuel2023.test.key)
 +
changed: [192.0.2.193] => (item=/home/manuel/devops/www.manuel2023.test.key)
 +
changed: [192.0.2.191] => (item=/home/manuel/devops/www.manuel2023.test.crt)
 +
changed: [192.0.2.192] => (item=/home/manuel/devops/www.manuel2023.test.crt)
 +
changed: [192.0.2.193] => (item=/home/manuel/devops/www.manuel2023.test.crt)
 +
 +
TASK [copiar sitio web] *************************************************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
 +
TASK [habilitar sitio web] **********************************************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
 +
TASK [habilitar sitio web https] ****************************************************************************************************************************************************************
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.193]
 +
 +
TASK [deshabilitar sitio por defecto] ***********************************************************************************************************************************************************
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.193]
 +
 +
RUNNING HANDLER [reiniciar Apache] **************************************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
 +
RUNNING HANDLER [reload Apache] *****************************************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.191]
 +
 +
RUNNING HANDLER [reiniciar fail2ban] ************************************************************************************************************************************************************
 +
changed: [192.0.2.191]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.192]
 +
 +
RUNNING HANDLER [reiniciar syslog] **************************************************************************************************************************************************************
 +
changed: [192.0.2.192]
 +
changed: [192.0.2.193]
 +
changed: [192.0.2.191]
 +
 +
PLAY RECAP **************************************************************************************************************************************************************************************
 +
192.0.2.191                : ok=20  changed=19  unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
 +
192.0.2.192                : ok=20  changed=19  unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
 +
192.0.2.193                : ok=20  changed=19  unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
 +
</pre>
 +
 +
Uns comentarios sobre a saída:
 +
* No caso de erro na execución dunha tarefa párase a execución do playbook.
 +
* Lanzar repetidas veces o playbook non fará que cambie o estado final dos equipos. Este concepto é coñecido por 'idempotencia'.
 +
 +
O resultado é que nos tres servidores temos a configuración desexada (lembrar que para acceder usando www.manuel2023.test hai que configurar a resolución dns no equipo, por exemplo, a través do arquivo /etc/hosts):
 +
 +
Acceso por https ó servidor web
 +
 +
Fig. Acceso por http e https a www.manuel2023.com en server01
 +
 +
$ ansible incus -m ansible.builtin.shell -a 'ss -ltnp' -b -K
 +
<pre>
 +
BECOME password:
 +
192.0.2.192 | CHANGED | rc=0 >>
 +
State    Recv-Q    Send-Q      Local Address:Port        Peer Address:Port    Process                                                                       
 +
LISTEN    0        4096        127.0.0.53%lo:53              0.0.0.0:*        users:(("systemd-resolve",pid=301,fd=13))                                     
 +
LISTEN    0        128                0.0.0.0:22              0.0.0.0:*        users:(("sshd",pid=986,fd=3))                                                 
 +
LISTEN    0        511                      *:80                    *:*        users:(("apache2",pid=17251,fd=4),("apache2",pid=17250,fd=4),("apache2",pid=17249,fd=4),("apache2",pid=17248,fd=4),("apache2",pid=17247,fd=4),("apache2",pid=17211,fd=4))
 +
LISTEN    0        128                  [::]:22                  [::]:*        users:(("sshd",pid=986,fd=4))                                                 
 +
LISTEN    0        511                      *:443                    *:*        users:(("apache2",pid=17251,fd=6),("apache2",pid=17250,fd=6),("apache2",pid=17249,fd=6),("apache2",pid=17248,fd=6),("apache2",pid=17247,fd=6),("apache2",pid=17211,fd=6))
 +
192.0.2.191 | CHANGED | rc=0 >>
 +
State    Recv-Q    Send-Q      Local Address:Port        Peer Address:Port    Process                                                                       
 +
LISTEN    0        128                0.0.0.0:22              0.0.0.0:*        users:(("sshd",pid=987,fd=3))                                                 
 +
LISTEN    0        4096        127.0.0.53%lo:53              0.0.0.0:*        users:(("systemd-resolve",pid=301,fd=13))                                     
 +
LISTEN    0        128                  [::]:22                  [::]:*        users:(("sshd",pid=987,fd=4))                                                 
 +
LISTEN    0        511                      *:443                    *:*        users:(("apache2",pid=17073,fd=6),("apache2",pid=16965,fd=6),("apache2",pid=16964,fd=6),("apache2",pid=16963,fd=6),("apache2",pid=16962,fd=6),("apache2",pid=16961,fd=6),("apache2",pid=16925,fd=6))
 +
LISTEN    0        511                      *:80                    *:*        users:(("apache2",pid=17073,fd=4),("apache2",pid=16965,fd=4),("apache2",pid=16964,fd=4),("apache2",pid=16963,fd=4),("apache2",pid=16962,fd=4),("apache2",pid=16961,fd=4),("apache2",pid=16925,fd=4))
 +
192.0.2.193 | CHANGED | rc=0 >>
 +
State    Recv-Q    Send-Q      Local Address:Port        Peer Address:Port    Process                                                                       
 +
LISTEN    0        4096        127.0.0.53%lo:53              0.0.0.0:*        users:(("systemd-resolve",pid=301,fd=13))                                     
 +
LISTEN    0        128                0.0.0.0:22              0.0.0.0:*        users:(("sshd",pid=988,fd=3))                                                 
 +
LISTEN    0        128                  [::]:22                  [::]:*        users:(("sshd",pid=988,fd=4))                                                 
 +
LISTEN    0        511                      *:443                    *:*        users:(("apache2",pid=17244,fd=6),("apache2",pid=17243,fd=6),("apache2",pid=17242,fd=6),("apache2",pid=17241,fd=6),("apache2",pid=17240,fd=6),("apache2",pid=17204,fd=6))
 +
LISTEN    0        511                      *:80                    *:*        users:(("apache2",pid=17244,fd=4),("apache2",pid=17243,fd=4),("apache2",pid=17242,fd=4),("apache2",pid=17241,fd=4),("apache2",pid=17240,fd=4),("apache2",pid=17204,fd=4))
 +
</pre>
 +
 +
$ ansible incus -m ansible.builtin.shell -a 'apache2ctl -S' -b -K
 +
<pre>
 +
BECOME password:
 +
192.0.2.191 | CHANGED | rc=0 >>
 +
VirtualHost configuration:
 +
*:80                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test.conf:1)
 +
*:443                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test_https.conf:1)
 +
ServerRoot: "/etc/apache2"
 +
Main DocumentRoot: "/var/www/html"
 +
Main ErrorLog: "/var/log/apache2/error.log"
 +
Mutex ssl-stapling: using_defaults
 +
Mutex ssl-cache: using_defaults
 +
Mutex default: dir="/var/run/apache2/" mechanism=default
 +
Mutex mpm-accept: using_defaults
 +
Mutex watchdog-callback: using_defaults
 +
Mutex ssl-stapling-refresh: using_defaults
 +
PidFile: "/var/run/apache2/apache2.pid"
 +
Define: DUMP_VHOSTS
 +
Define: DUMP_RUN_CFG
 +
User: name="www-data" id=33
 +
Group: name="www-data" id=33
 +
192.0.2.193 | CHANGED | rc=0 >>
 +
VirtualHost configuration:
 +
*:80                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test.conf:1)
 +
*:443                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test_https.conf:1)
 +
ServerRoot: "/etc/apache2"
 +
Main DocumentRoot: "/var/www/html"
 +
Main ErrorLog: "/var/log/apache2/error.log"
 +
Mutex watchdog-callback: using_defaults
 +
Mutex ssl-stapling-refresh: using_defaults
 +
Mutex ssl-stapling: using_defaults
 +
Mutex ssl-cache: using_defaults
 +
Mutex default: dir="/var/run/apache2/" mechanism=default
 +
Mutex mpm-accept: using_defaults
 +
PidFile: "/var/run/apache2/apache2.pid"
 +
Define: DUMP_VHOSTS
 +
Define: DUMP_RUN_CFG
 +
User: name="www-data" id=33
 +
Group: name="www-data" id=33
 +
192.0.2.192 | CHANGED | rc=0 >>
 +
VirtualHost configuration:
 +
*:80                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test.conf:1)
 +
*:443                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test_https.conf:1)
 +
ServerRoot: "/etc/apache2"
 +
Main DocumentRoot: "/var/www/html"
 +
Main ErrorLog: "/var/log/apache2/error.log"
 +
Mutex ssl-stapling-refresh: using_defaults
 +
Mutex ssl-stapling: using_defaults
 +
Mutex ssl-cache: using_defaults
 +
Mutex default: dir="/var/run/apache2/" mechanism=default
 +
Mutex mpm-accept: using_defaults
 +
Mutex watchdog-callback: using_defaults
 +
PidFile: "/var/run/apache2/apache2.pid"
 +
Define: DUMP_VHOSTS
 +
Define: DUMP_RUN_CFG
 +
User: name="www-data" id=33
 +
Group: name="www-data" id=33
 +
</pre>
  
 
= Instalación =
 
= Instalación =
Línea 202: Línea 1174:
 
</pre>
 
</pre>
  
−
= Primeiras probas con ansible =
+
== Primeiras probas con ansible ==
  
 
Empregamos o módulo ping de ansible para comprobar a conexión cos nodos clientes (Importante: asegúrate que estén arrancados!!)
 
Empregamos o módulo ping de ansible para comprobar a conexión cos nodos clientes (Importante: asegúrate que estén arrancados!!)
Línea 209: Línea 1181:
 
: ansible aula1 -m ping
 
: ansible aula1 -m ping
  
−
Inicialmente, teremos erro: Ansible emprega ssh para conectarse co cliente, como é a primiera vez que se conecta con ese cliente pídenos confirmación  
+
Inicialmente, teremos erro: Ansible emprega ssh para conectarse co cliente, como é a primeira vez que se conecta con ese cliente pídenos confirmación  
  
 
<pre>
 
<pre>
Línea 247: Línea 1219:
  
 
Instalamos sshpass:
 
Instalamos sshpass:
−
<pre>
 
 
  root@servidorAnsible:/etc/ansible# apt install sshpass
 
  root@servidorAnsible:/etc/ansible# apt install sshpass
−
</pre>
 
  
 
Ahora sí devolverá en cor verde (os erros estaban amosándose en vermello) indicando éxito.  O equipo 10.0.2.10 respondeu o móudlo ping correctamente. A resposta é un JSON que pode conter moita información:
 
Ahora sí devolverá en cor verde (os erros estaban amosándose en vermello) indicando éxito.  O equipo 10.0.2.10 respondeu o móudlo ping correctamente. A resposta é un JSON que pode conter moita información:
Línea 282: Línea 1252:
  
 
Con isto so fixemos un ping a un equipo mais se tivésemos dados de alta 100 equipos dentro da categoría aula1 con  un só comando, veríamos cales responden e polo tanto saberíamos cales están acendidos
 
Con isto so fixemos un ping a un equipo mais se tivésemos dados de alta 100 equipos dentro da categoría aula1 con  un só comando, veríamos cales responden e polo tanto saberíamos cales están acendidos
 +
 +
= Ampliación =
 +
* [[Módulos de ansible]]
 +
* [[Ansible nunha contorna DevOps]]
 +
 +
= Tarefas =
 +
# [[Tarefa 1 - Creación do Servidor Ansible]]
  
 
= Referencias =
 
= Referencias =
Línea 288: Línea 1265:
 
* [https://www.youtube.com/watch?v=9L3iVo40ja4 Seminario Ferramentas DevOps para Sysadmin con Vagrant, Packer e Terraform]. Alberto García.
 
* [https://www.youtube.com/watch?v=9L3iVo40ja4 Seminario Ferramentas DevOps para Sysadmin con Vagrant, Packer e Terraform]. Alberto García.
 
* [https://www.youtube.com/watch?v=u94MSkitqug Herramientas Devops: Docker y Vagrant]
 
* [https://www.youtube.com/watch?v=u94MSkitqug Herramientas Devops: Docker y Vagrant]
 +
* [https://docs.ansible.com/ansible/latest/getting_started/index.html Documentation - Getting started with Ansible]

Revisión actual del 20:23 4 mar 2026


Metodos de conexión remota en Ansible

Introdución

Ansible:

  • é unha plataforma de software libre para configurar e administrar equipos, permitindo a xestión da configuración e a orquestación de infraestruturas.
  • é un proxecto de código aberto implementado en Python e ten unha arquitectura con módulos que poden manexar prácticamente calquera sistema operativo, contorna de nube e ferramenta ou marco de administración do sistema.
  • é amplamente usada para xestionar a configuración de servidores, para tarefas de aprovisionamento de instancias cloud, operacións dev-ops, ...
  • ten unha filosofía que pode resumirse en que o estado de configuración final que queres que teña un equipo queda definido nun arquivo de texto, chamado playbook

Máis datos:

  • Lanzamento inicial no 2012 (escrito orixialmente por Michael DeHaan, o creador da aplicación de aprovisionamento Cobbler) e posteriormente adquirido por Red Hat.
  • Combina instalación multi-nodo (permite despregar configuracións de servidores e servicios por lotes), execucións de taefas ad hoc e administración de configuracións.
  • Arquitectura agentless. Non require un axente nos servidores cliente polo que optimiza o rendemento e evita abrir portos especiais, con utilizar só a conexión por SSH. O traballo envíaase aos hosts cando se executa Ansible. Os módulos son os programas que realizan o traballo real das tarefas dun play.
  • Sintaxe moi sinxela con baixa curva de aprendizaxe e sen requirir coñecementos de programación
  • Con máils de 1000 módulos disponibles. Asi para activos diferentes podemos falar a mesma lingua do dispositivo administrado; e tamén poderemos desenvolver módulos en python.
  • Con adoptación masiva por ser fácil de usar para os administradores de sistemas
  • Compatible con ferramentas DevOps coma Vagrant e Jenkins.

O deseño de Ansible contempla:

Mínimo por natureza
Os sistemas de administración non deben impoñer dependencias adicionais.
Consistente
Seguro
Ansible non instala axentes vulnerables nos nodos. Manexa as máquinas remotamente a través de SSH, que é o seu único requisito xunto con Python
Alta confiabilidade
O modelo de idempotencia é aplicado para as instalacións e configuracións, para previr efectos secundarios na execución repetitiva de guións (scripts)
Suave curva de aprendizaxe
Os playbooks ou libretos usan unha linguaxe descriptiva simple baseada en YAML.

Resumindo, Ansible é unha utilidade de orquestación e administración de configuración de código aberto que pode automatizar e estandarizar a configuración de hosts remotos e máquinas virtuáis. A súa funcionalidade de orquestación permite a Ansible coordinar o lanzamento e o apagado seguro de aplicacións de varios niveles.

Así no canto de escribir scripts personalizados e individualizados, os administradores do sistema crean un play ou unha xogada de alto nivel en Ansible.

Ese play realiza unha serie de tarefas no host ou grupo de hosts especificados no play.

Un ficheiro que contén un ou máis plays chámase Playbook.

Qué non pode facer ansible?

  • Non pode auditar os cambios realizados localmente por outros usuarios no sistema
  • Pode agregar paquetes a unha instalación, pero NON realizar a instalación mínima inicial do sistema
  • Pode modificar a configuración, pero NON a monitorea
  • Non realiza un seguemento dos cambios realizados nos ficheiros do sistema, e de qué usuario ou proceso realizou os cambios

Arquitectura

Arquitectura Cliente Servidor de Ansible
Arquitectura Cliente Servidor de Ansible. Nodos e plataformas xestionadas

Existen dous tipos de máquinas na arquitectura de Ansible:

  • o nodo de control
  • os hosts administrados

O software ansible está instalado no nodo de control e todos os seus compoñentes se manteñen nel.

Os hosts administrados enumeranse nun inventario de host ,un ficheirode texto no nodo de control que inclue unha lista de nomes de host administrados FQDN (fully qualified domain name) ou enderezos IP.

Ansible utiliza SSH coma protocolo de comuncación cos hosts administados. Os módul referenciados nos playbooks copianse nos hosts administrados. Despois se executan, en orde, cos argumentos especificados no playbook. Os usuarios de Ansible poden escribir os seus propios módulos personalizados se é preciso pero os módulo s principais que veñen con Ansible poden realizar a maioría das tarefas de administración do sistema.

Primeiros pasos

Traballar con Ansible hai que comprender os seguintes termos:

Host Inventory
é unha descrición dos nodos (equipos a administrar) ós que poderemos acceder usando Ansible. O inventory máis básico contén ós nodos agrupados por grupos (ubicacións xeográficas, servizos ou calquera outro criterio que consideremos) e as direccións IP ou nomes.

Un exemplo de inventory podería ser:

$ cat /etc/ansible/hosts
[infor1]
192.168.1.193
192.168.1.194
192.168.1.195

[profesores]
192.168.1.201
192.168.2.201
192.168.3.201
Playbooks
trátase de arquivos de texto onde se describen configuracións ou tarefas de despregue. Dentro dun playbook haberá 'xogadas' (plays) onde se indican unha serie de tarefas a executar; por exemplo, actualizar a lista de paquetes, instalar o servidor web apache, activar o módulo ssl, copiar os arquivos de configuración dos sitios web a aloxar, crear as carpetas dos DocumentRoot dos sitios e copiar os arquivos que forma os sitios, activar os sitios web, reiniciar o servidor Apache, ... Os playbooks poden verse como arquivos que describen a configuración desexada para un equipo ou conxunto de equipos.

No seguinte exemplo podemos ver un playbook que fixera no seu día para por en marcha e configurar os equipos Linux Lubuntu dunha clase de informática de ESO/Bach do centro. Podese ver como unha foto do estado que quería acadar nos equipos e que se resume en que:

  • Copiamos a todos os equipos da clase un arquivo sources.list para que todos teñan e usen os mesmos repositorios.
  • Copiamos a todos os equipos da clase o arquivo 01apt-cacherng-proxy para que usen o apt-cacher-ng e se aceleren os procesos de instalación/actualización de paquetes.
  • Copiamos en /etc/skel unha plantilla para que os usuarios do equipo partan da mesma configuración de escritorio (iconas, menús, ligazóns de favoritos, ...).
  • Creamos uns usuarios e configuramos o contrasinal de root.
  • Configuramos a sincronización de hora para que vaian a un servidor de hora interno no IES.
  • Borramos algúns programas que viñan coa instalación básica de Lubuntu (Abiword e gnumeric).
  • Engadimos algúns repositorios ppa para ter as últimas versións de Inkscape e LibreOffice.
  • Actualizamos os equipos e instalamos unha colección de paquetes indicada no arquivo paquetes_ESO1.yml (arandr, libreoffice, libreoffice-l10n-es, vlc, audacity, inkscape, ...).
  • Deshabilitamos a impresión nos equipos.
---
- hosts: infor1
  become: yes
  remote_user: magasix
  become_method: sudo
  gather_facts: false
  vars_files:
  - /media/DATOS/Tutoriales/ansible/paquetes_ESO1.yml
    
  tasks:
  - name: copiar fichero de repositorios
    copy: src=/media/DATOS/Tutoriales/ansible/sources.list_ESO1.txt dest=/etc/apt/sources.list

  - name: copiar fichero de apt-cacherng-proxy
    copy: src=/media/DATOS/Tutoriales/ansible/01apt-cacherng-proxy_ESO1.txt dest=/etc/apt/apt.conf.d/01apt-cacherng-proxy

  - name: crear grupo alumnos
    group: name=alumnos state=present

  - name: copiar skel
    copy: src=/media/DATOS/Tutoriales/ansible/skel/ dest=/etc/skel/

  - name: crear usuario alumno
    user: name=alumno comment="Alumno IES" shell=/bin/bash groups=alumnos state=present

  - name: password en blanco
    shell: passwd -d alumno

  - name: crear usuario alumno TICs abc123.
    user: name=alumnotics comment="Alumno TICs" shell=/bin/bash groups=alumnos password=ylMqA85PRieLg state=present

  - name: password a root
    user: name=root password=rDQVP5utaEC9E

  - name: desinstalar ntp
    apt: name=ntp state=absent purge=yes

  - name: configurar ntpdate   
    copy: src=/media/DATOS/Tutoriales/ansible/ntpdate.conf_ESO1.txt dest=/etc/default/ntpdate

  - name: fijar lubuntu-desktop
    shell: apt-mark manual lubuntu-desktop

  - name: borrar abiword
    apt: name=abiword state=absent purge=yes

  - name: borrar gnumeric
    apt: name=gnumeric state=absent purge=yes

  - name: repositorio inkscape
    apt_repository: repo='ppa:inkscape.dev/stable' update_cache=no
  
  - name: repositorio libreoffice 5
    apt_repository: repo='ppa:libreoffice/ppa' update_cache=no
    
  - name: actualizar equipo
    apt: upgrade=dist update_cache=yes 

  - name: instalacion de paquetes
    apt: pkg={{ item }} state=installed
    with_items: '{{system_packages}}'

  - name: deshabilitar impresion
    service: name=cups state=stopped enabled=no 

No exemplo podemos ver que aparecen palabras como user, shell, apt,_repository, apt, service, ..., e que correspóndense con nomes de módulos de ansible. Os módulos permiten efectuar tarefas de configuración nos equipos a administrar; por exemplo, o módulo apt permite xestionar paquetes .deb en equipos Debian/Ubuntu.

Pódese ver na sección de documentación todos os módulos dos que dispón Ansible:

Módulos Packaging

Fig. Módulos para a xestión de paquetes en Ansible

Para traballar con Ansible únicamente precisamos o seguinte:

  • Un nodo de xestión con Ansible instalado (ten que ser unha máquina Linux).
  • Nodo/s a xestionar con ssh instalado e configurado para permitir as conexións dende o nodo xestor. A diferenza doutro software semellante, como Puppet, Chef ou Salt, non é preciso instalar ningún software axente nos nodos administrados. Os nodos a administrar poden ser Linux ou Windows.

Resumindo o funcionamento nunha imaxe: as tarefas/configuracións recollidas no Playbook realizaranse no equipo indicado no Host Inventory, usando unha canle ssh para comunicarse o nodo xestor co nodo administrado.

Administración con ansible

Fig. Administración con Ansible. Fonte: 19 Minutes with Ansible

Se en vez de lanzar o playbook contra un equipo lánzase contra un grupo de equipos, teremos un grupo de equipos que comparten a mesma configuración. No exemplo anterior, lanzar o playbook contra os 20 Lubuntus recén instalados na aula, implica que ó cabo dun rato teremos 20 equipos configurados exactamente igual. Traballar con playbooks que recollan os cambios de configuración/tarefas a realizar facilita o mantemento dos sistemas, permite incorporar novos equipos que teñan exactamente a mesma configuración que o resto, ... Case podemos pensar nos playbooks como a nosa infraestrutura documentada.

Administración con ansible

Fig. Lanzando un playbook contra un grupo de nodos. Fonte: 19 Minutes with Ansible

A modo de exemplo amoso a saída resultante de lanzar o playbook anterior contra 3 equipos e podemos observar como se van realizando as diferentes tarefas (tasks), levando a todos os equipos ó mesmo estado de configuración:

$ ansible-playbook lubuntu_ies_alumnos_ntpdate_ESO1_casa.yml -K
SUDO password: 

PLAY ***************************************************************************

TASK [copiar fichero de repositorios] ******************************************
changed: [192.168.1.195]
changed: [192.168.1.193]
changed: [192.168.1.194]

TASK [copiar fichero de apt-cacherng-proxy] ************************************
changed: [192.168.1.193]
changed: [192.168.1.195]
changed: [192.168.1.194]

TASK [crear grupo alumnos] *****************************************************
changed: [192.168.1.193]
changed: [192.168.1.194]
changed: [192.168.1.195]

TASK [copiar skel] *************************************************************
changed: [192.168.1.195]
changed: [192.168.1.193]
changed: [192.168.1.194]

TASK [crear usuario alumno] ****************************************************
changed: [192.168.1.195]
changed: [192.168.1.194]
changed: [192.168.1.193]

TASK [password en blanco] ******************************************************
changed: [192.168.1.194]
changed: [192.168.1.195]
changed: [192.168.1.193]

TASK [crear usuario alumno TICs abc123.] ***************************************
changed: [192.168.1.193]
changed: [192.168.1.194]
changed: [192.168.1.195]

TASK [password a root] *********************************************************
changed: [192.168.1.194]
changed: [192.168.1.193]
changed: [192.168.1.195]

TASK [desinstalar ntp] *********************************************************
changed: [192.168.1.195]
changed: [192.168.1.194]
changed: [192.168.1.193]

TASK [configurar ntpdate] ******************************************************
changed: [192.168.1.194]
changed: [192.168.1.193]
changed: [192.168.1.195]

TASK [fijar lubuntu-desktop] ***************************************************
changed: [192.168.1.194]
changed: [192.168.1.195]
changed: [192.168.1.193]

TASK [borrar abiword] **********************************************************
changed: [192.168.1.194]
changed: [192.168.1.195]
changed: [192.168.1.193]

TASK [borrar gnumeric] *********************************************************
changed: [192.168.1.195]
changed: [192.168.1.194]
changed: [192.168.1.193]

TASK [repositorio inkscape] ****************************************************
changed: [192.168.1.195]
changed: [192.168.1.194]
changed: [192.168.1.193]

TASK [repositorio libreoffice 5] ***********************************************
changed: [192.168.1.193]
changed: [192.168.1.194]
changed: [192.168.1.195]

TASK [actualizar equipo] *******************************************************
changed: [192.168.1.194]
changed: [192.168.1.193]
changed: [192.168.1.195]

TASK [instalacion de paquetes] *************************************************
ok: [192.168.1.194] => (item=[u'build-essential', u'arandr', u'libreoffice', u'libreoffice-l10n-es', u'lubuntu-restricted-addons', u'lubuntu-restricted-extras', u'ubuntu-restricted-extras', u'ubuntu-restricted-addons', u'icedtea-plugin', u'vlc', u'audacity', u'inkscape', u'openshot', u'sweethome3d', u'sweethome3d-furniture', u'sweethome3d-furniture-nonfree', u'gimp', u'gimp-data', u'gimp-data-extras', u'gimp-dcraw', u'gimp-gmic', u'gimp-help-es', u'gimp-plugin-registry', u'scribus', u'scribus-template', u'scribus-doc'])
ok: [192.168.1.193] => (item=[u'build-essential', u'arandr', u'libreoffice', u'libreoffice-l10n-es', u'lubuntu-restricted-addons', u'lubuntu-restricted-extras', u'ubuntu-restricted-extras', u'ubuntu-restricted-addons', u'icedtea-plugin', u'vlc', u'audacity', u'inkscape', u'openshot', u'sweethome3d', u'sweethome3d-furniture', u'sweethome3d-furniture-nonfree', u'gimp', u'gimp-data', u'gimp-data-extras', u'gimp-dcraw', u'gimp-gmic', u'gimp-help-es', u'gimp-plugin-registry', u'scribus', u'scribus-template', u'scribus-doc'])
ok: [192.168.1.195] => (item=[u'build-essential', u'arandr', u'libreoffice', u'libreoffice-l10n-es', u'lubuntu-restricted-addons', u'lubuntu-restricted-extras', u'ubuntu-restricted-extras', u'ubuntu-restricted-addons', u'icedtea-plugin', u'vlc', u'audacity', u'inkscape', u'openshot', u'sweethome3d', u'sweethome3d-furniture', u'sweethome3d-furniture-nonfree', u'gimp', u'gimp-data', u'gimp-data-extras', u'gimp-dcraw', u'gimp-gmic', u'gimp-help-es', u'gimp-plugin-registry', u'scribus', u'scribus-template', u'scribus-doc'])

TASK [deshabilitar impresion] **************************************************
changed: [192.168.1.193]
changed: [192.168.1.194]
changed: [192.168.1.195]

PLAY RECAP *********************************************************************
192.168.1.193              : ok=18   changed=18   unreachable=0    failed=0   
192.168.1.194              : ok=18   changed=18   unreachable=0    failed=0   
192.168.1.195              : ok=18   changed=18   unreachable=0    failed=0   

Modo ad-hoc

Aínda que traballar con playbooks é o recomendado, Ansible permite traballar en modo ad-hoc; é dicir, executar tarefas sen necesidade de crear e gardar un playbook. Por exemplo, comprobar o estado dos equipos, executar comandos do sistema, copias arquivos en calquera sentido, ...

A modo de exemplo:

$ ansible infor1 -m ping -u magasix
192.168.1.194 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.1.195 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
192.168.1.193 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
$ ansible infor1 -m shell -a "shutdown -h now" -u magasix --sudo -K
SUDO password: 
192.168.1.194 | SUCCESS | rc=0 >>
192.168.1.195 | SUCCESS | rc=0 >>
192.168.1.193 | SUCCESS | rc=0 >>

Alternativas

Puppet Chef Salt Ansible
Soporte Puppet Labs Opscode SaltStack Ansible Works
Control da interface Manifest (DSL) Recipes (DSL:Ruby) SLS (SoLt Sate/YAML) Playbook (YAML,JSON)
Axente Master/Axente (Standalone) Servidor/Cliente
Chef-solo (Standalone)
Master/Axente (minions)
Standalone (masterless)
Standalone (masterless)
Tecnoloxía core Ruby Ruby Python Python
Comunicación http, ssh / SSL STOMP, rest/SSL ZeroMQ SSH / JSON
Execución remota Mcollective, complexa Coitelo, complexa Integrada por defecto, sinxela Integrada por defecto, sinxela
Apoiado/usado por Google, eBay, Twitter Facebook, Ancestry, Splunk Linkedin, HP Cloud Rackspace, Evernote
Data de lanzamento 2005 2009 2011 2012

Escenario con Ansible

Configuración do escenario

O obxectivo deste Escenario 8D é facer unha primeira aproximación a Ansible e ver as posibilidades que proporciona ós administradores de sistemas como ferramenta avanzada de configuración e automatización. O noso obxectivo será montar un sistema con tres servidores web idénticos que imos supoñer que forman parte dun backend e teñen as seguintes características:

  • Hai que instalar e configurar fail2ban para que no arquivo de configuración jail.local o tempo de búsqueda sexa de 10 minutos, o de baneo 20 minutos e o número máximo de intentos sexa 3.
  • Hai que configurar o syslog para que a reducción da repetición de mensaxes se desactive ( $RepeatedMsgReduction off )
  • Os servidores corren Apache e php 8.2
  • Responden a solicitudes por http e https (con certificado propio autofirmado) dirixidas a www.manuel2023.test
  • Teñen unha páxina web index.php co seguinte contido:
<?php
echo "
<html>
<head>
<title>Sitio web en ${_SERVER["SERVER_ADDR"]}</title>
</head>
<body>
<img src=”imaxes/logo.png” alt=”logotipo”>
<h1>Sitio Web www.manuel2023.test</h1>
Estás en ${_SERVER["SERVER_ADDR"]}
</body>
</html>";
?>
  • Non se permiten opcións como listado de directorios, seguir enlaces simbólicos, ...
  • Non se permite personalizar as opcións usando arquivos htaccess.
  • O sitio web ten os seus propios ficheros de log (o mesmo tanto para o acceso por http como https).

Instalación e comandos ad-hoc

Instalación de Ansible

Instalaremos Ansible nun equipo Linux que exercerá de nodo administrador e os pasos a seguir son:

$ sudo apt update
$ sudo apt install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt install ansible

Creación do inventory

Unha vez rematada a instalación temos que crear un inventory cos equipos que queremos administrar.

NOTA. No caso de non estar creado o directorio /etc/ansible, hai que proceder a crealo mediante:
mkdir /etc/ansible
$ sudo nano /etc/ansible/hosts 
# grupo contedores 
[incus]
192.0.2.191 
192.0.2.192
192.0.2.193

No inventory pódese engadir máis información asociada ós nodos a administrar como o usuario co que Ansible iniciará sesión, que no noso caso pode ser o usuario ubuntu ou o usuario magasix creada no aprovisionamento dos contedores:

$ sudo nano /etc/ansible/hosts 
# grupo contedores 
[incus]
192.0.2.191 
192.0.2.192
192.0.2.193

[incus:vars]
ansible_user=ubuntu

Autenticación mediante identidades dixitais

Ansible usará ssh para entrar nos equipos a xestionar e unha práctica recomendada é autenticarse mediante identidades dixitais como se explicou PENDIENTE polo que procedemos a autorizar unha clave dixital e a indicalo no inventory. Usamos o usuario ubuntu con contrasinal abc123.

$ ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@192.0.2.191
$ ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@192.0.2.192
$ ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@192.0.2.193

Despois de autorizar a clave, verificar que é posible conectarse.

$ sudo nano /etc/ansible/hosts 
# grupo contedores 
[incus]
192.0.2.191 
192.0.2.192
192.0.2.193

[incus:vars]
ansible_ssh_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_python_interpreter=/usr/bin/python3

Vemos que no inventory é posible engadir variables asociadas a equipos ou grupos de equipos como ansible_ssh_private_key_file e ansible_python_interpreter (permite indicar que intérprete de python hai nos hosts sen necesidade que o detecte ansible).

Verificación con ping

Agora podemos verificar que Ansible é capaz de conectarse cos servers executando un 'ping':

$ ansible incus -m ansible.builtin.ping
192.0.2.191 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.0.2.193 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.0.2.192 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Comandos AD-HOC

Os comandos ad-hoc están para cando se quere facer algo pero non queremos gardarlo para outras ocasións ou non se considera necesario escribir un playbook. Aínda que para aproveitar todo o potencial de Ansible están os playbooks, os comandos ad-hoc permiten facer cosas de forma rápida. Por exemplo, facemos un ss -ltnp:

$ ansible incus -m ansible.builtin.shell -a 'ss -ltnp'
192.0.2.193 | CHANGED | rc=0 >>
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   0        4096       127.0.0.53%lo:53            0.0.0.0:*              
LISTEN   0        128              0.0.0.0:22            0.0.0.0:*              
LISTEN   0        128                 [::]:22               [::]:*              
192.0.2.192 | CHANGED | rc=0 >>
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   0        4096       127.0.0.53%lo:53            0.0.0.0:*              
LISTEN   0        128              0.0.0.0:22            0.0.0.0:*              
LISTEN   0        128                 [::]:22               [::]:*              
192.0.2.191 | CHANGED | rc=0 >>
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   0        4096       127.0.0.53%lo:53            0.0.0.0:*              
LISTEN   0        128              0.0.0.0:22            0.0.0.0:*              
LISTEN   0        128                 [::]:22               [::]:*

Hai que sinalar qué ansible.builtin.shell é o nome completo do módulo de Ansible e shell é a forma abreviada.

$  ansible incus -m shell -a 'ss -ltnp'
192.0.2.191 | CHANGED | rc=0 >>
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   0        4096       127.0.0.53%lo:53            0.0.0.0:*              
LISTEN   0        128              0.0.0.0:22            0.0.0.0:*              
LISTEN   0        128                 [::]:22               [::]:*              
192.0.2.193 | CHANGED | rc=0 >>
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   0        4096       127.0.0.53%lo:53            0.0.0.0:*              
LISTEN   0        128              0.0.0.0:22            0.0.0.0:*              
LISTEN   0        128                 [::]:22               [::]:*              
192.0.2.192 | CHANGED | rc=0 >>
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   0        4096       127.0.0.53%lo:53            0.0.0.0:*              
LISTEN   0        128              0.0.0.0:22            0.0.0.0:*              
LISTEN   0        128                 [::]:22               [::]:* 

Aínda que en moitos titoriais de Ansible aparece a forma abreviada, os desenvolvedores de Ansible recomendan usar o nome completo en vez da abreviada para evitar posibles conflictos.

No caso de querer executar o comando nos hosts como administrador pódese empregar as opcións -b e -K:

  • -b (become): indica que se quere escalar privilexios nos hosts
  • -K: pregunta polo contrasinal para elevar os privilexios
$ ansible incus -m ansible.builtin.shell -a 'ss -ltnp' -b -K
BECOME password: 
192.0.2.192 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    Process                                                                         
LISTEN    0         4096         127.0.0.53%lo:53               0.0.0.0:*        users:(("systemd-resolve",pid=165,fd=13))                                      
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*        users:(("sshd",pid=220,fd=3))                                                  
LISTEN    0         128                   [::]:22                  [::]:*        users:(("sshd",pid=220,fd=4))                                                  
192.0.2.191 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    Process                                                                         
LISTEN    0         4096         127.0.0.53%lo:53               0.0.0.0:*        users:(("systemd-resolve",pid=166,fd=13))                                      
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*        users:(("sshd",pid=229,fd=3))                                                  
LISTEN    0         128                   [::]:22                  [::]:*        users:(("sshd",pid=229,fd=4))                                                  
192.0.2.193 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    Process                                                                         
LISTEN    0         4096         127.0.0.53%lo:53               0.0.0.0:*        users:(("systemd-resolve",pid=166,fd=13))                                      
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*        users:(("sshd",pid=211,fd=3))                                                  
LISTEN    0         128                   [::]:22                  [::]:*        users:(("sshd",pid=211,fd=4))  

O usuario ubuntu está autorizado para facer sudo sen necesidade de introducir o contrasinal, polo que no noso escenario o comando anterior podería executarse sen -K. Sinalar tamén que é posible gardar contrasinais cifradas empregando o concepto de vault.

Posibles operacións

Podemos copiar arquivos de local a remoto e viceversa, xestionar usuarios, servizos, paquetes, ...

Por exemplo, para copìar un arquivo local chamado backup.yml en todos os servidores podería executar:

$ ansible incus -m ansible.builtin.copy -a "src=config_backup.yml dest=/home/ubuntu/config.yml"
192.0.2.192 | CHANGED => {
    "changed": true,
    "checksum": "39244f4abbbb552d9d3e00eb27d05cfd6b8bfa44",
    "dest": "/home/ubuntu/config.yml",
    "gid": 1001,
    "group": "ubuntu",
    "md5sum": "1f5b15fb9e83f47d213637efe71f3d20",
    "mode": "0664",
    "owner": "ubuntu",
    "size": 424,
    "src": "/home/ubuntu/.ansible/tmp/ansible-tmp-1685284269.5834956-25446-44703324742452/source",
    "state": "file",
    "uid": 1001
}
192.0.2.191 | CHANGED => {
    "changed": true,
    "checksum": "39244f4abbbb552d9d3e00eb27d05cfd6b8bfa44",
    "dest": "/home/ubuntu/config.yml",
    "gid": 1001,
    "group": "ubuntu",
    "md5sum": "1f5b15fb9e83f47d213637efe71f3d20",
    "mode": "0664",
    "owner": "ubuntu",
    "size": 424,
    "src": "/home/ubuntu/.ansible/tmp/ansible-tmp-1685284269.628682-25444-43771047461490/source",
    "state": "file",
    "uid": 1001
}
192.0.2.193 | CHANGED => {
    "changed": true,
    "checksum": "39244f4abbbb552d9d3e00eb27d05cfd6b8bfa44",
    "dest": "/home/ubuntu/config.yml",
    "gid": 1001,
    "group": "ubuntu",
    "md5sum": "1f5b15fb9e83f47d213637efe71f3d20",
    "mode": "0664",
    "owner": "ubuntu",
    "size": 424,
    "src": "/home/ubuntu/.ansible/tmp/ansible-tmp-1685284269.6718416-25448-47330558216673/source",
    "state": "file",
    "uid": 1001
}
$ ansible incus -m ansible.builtin.shell -a 'ls -lhF'
192.0.2.193 | CHANGED | rc=0 >>
total 2,5K
-rw-rw-r-- 1 ubuntu ubuntu 2,1K mar  1 17:10 config.yml
192.0.2.192 | CHANGED | rc=0 >>
total 2,5K
-rw-rw-r-- 1 ubuntu ubuntu 2,1K mar  1 17:10 config.yml
192.0.2.191 | CHANGED | rc=0 >>
total 2,5K
-rw-rw-r-- 1 ubuntu ubuntu 2,1K mar  1 17:10 config.yml

Na páxina Introduction To Ad-Hoc Commands podemos ver máis exemplos desta forma de usar Ansible.

Playbooks

Despois de revisar por riba o uso de ansible chegamos o punto forte que son os playbooks. Como primeira aproximación executaremos o playbook actualizar.yml que permitirá actualizar os equipo servidores e como pode verse é moi sinxelo de entender:

  • Aplícase os equipo incus definidos no inventory.
  • Execútase como administrador (become: yes)
  • Actualiza a lista de paquetes e fai unha actualización do sistema.
---
- hosts: incus
  become: yes
  tasks:
    - name: actualizar lista de paquetes y el sistema
      apt: 
        update_cache: yes
        cache_valid_time: 3600
    - name: actualizar sistema        
      apt:  
        upgrade: dist

Para lanzalo imos a carpeta de devops e:

$ ansible-playbook actualizar.yml -K
SUDO password: 

PLAY [incus] *************************************************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************************************
ok: [192.0.2.191]
ok: [192.0.2.192]
ok: [192.0.2.193]

TASK [actualizar lista de paquetes y el sistema] ***********************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.193]
changed: [192.0.2.191]

TASK [actualizar sistema] **********************************************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.193]
changed: [192.0.2.191]

PLAY RECAP *************************************************************************************************************************************************************************************
192.0.2.191                : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.0.2.192                : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.0.2.193                : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

Todas as actuacións a realizar para levar ós servidores ó estado de configuración indicado no enunciado sabemos facelas a man como fixemos ó longo de diversos escenarios do curso; sen embargo, agora imos a recollelas nun playbook que permitirá automatizar a súa execución. Non é obxectivo deste apartado explicar exhaustivamente como facelo; xa que Ansible daría para un curso enteiro, pero si revisar o playbook server-apache.yml vendo que é moi sinxelo de entender e executalo para ver a súa potencialidade.

Definimos os equipos ós que se vai aplicar o playbook que executarase como administrador e usando as variables recollidas no arquivo vars.yml

---
- hosts: incus
  become: yes
  vars_files:
    - vars.yml

Actualizamos a listaxe de paquetes e despois instalamos os seguintes:

    - name: instalar paquetes
      ansible.builtin.apt: 
        name:
          - curl
          - unzip
          - fail2ban
          - apache2
          - php
          - php-cli
          - php-common
          - php-curl
          - php-gd
          - libapache2-mod-php
        state: latest
        update_cache: yes
        cache_valid_time: 3600

Creamos o arquivo jail.local a partir do jail.conf e procedemos a reemprazar os valores por defecto dos parámetros de configuración polos pedidos:

    - name: crear jail.local
      ansible.builtin.copy:
        src: /etc/fail2ban/jail.conf
        dest: /etc/fail2ban/jail.local
        owner: root
        group: root
        mode: 0644
        remote_src: True

    - name: modificar parametro bantime en jail.local
      ansible.builtin.lineinfile:
        path: /etc/fail2ban/jail.local
        regexp: '^bantime  = 10m'
        line: 'bantime  = 1200'
        state: present
      notify: reiniciar fail2ban

    - name: modificar parametro findtime en jail.local
      ansible.builtin.lineinfile:
        path: /etc/fail2ban/jail.local
        regexp: '^findtime  = 10m'
        line: 'findtime = 300'
        state: present
      notify: reiniciar fail2ban

    - name: modificar parametro maxretry en jail.local
      ansible.builtin.replace:
        path: /etc/fail2ban/jail.local
        regexp: '^maxretry = 5'
        replace: 'maxretry = 3'
      notify: reiniciar fail2ban
Anulamos a reducción de mensaxe no rsyslog:
    - name: anular reduccion mensajes rsyslog
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        regexp: '^\$RepeatedMsgReduction on'
        line: '$RepeatedMsgReduction off'
        state: present
        backrefs: yes
      notify: reiniciar syslog

Asegurámonos que Apache e fail2ban estén funcionando:

    - name: Arrancar Apache y fail2ban
      ansible.builtin.service: name={{ item }} state=started enabled=yes
      with_items:
        - apache2
        - fail2ban

Habilitamos o módulo ssl para poder configurar o https:

    - name: habilitar módulo ssl 
      community.general.apache2_module:
        state: present
        name: ssl  
      notify: reiniciar Apache

Engadimos o virtualhost http e https para o dominio:

    - name: añadir virtualhost para el dominio
      ansible.builtin.template:
        src: templates/sitio_web.conf.j2
        dest: /etc/apache2/sites-available/{{ nombre_dominio }}.conf
        owner: root
        group: root
        mode: 0644

    - name: añadir virtualhost https para el dominio
      ansible.builtin.template:
        src: templates/sitio_web_https.conf.j2
        dest: /etc/apache2/sites-available/{{ nombre_dominio }}_https.conf
        owner: root
        group: root
        mode: 0644

Copiamos os certificados e as páxinas do sitio web:

    - name: copiar certificados sitio web
      ansible.builtin.copy:
        src: '{{ item }}'
        dest: /etc/apache2/certificados/
        owner: root
        group: root
        mode: 0644
      with_fileglob:
      - '{{ nombre_dominio }}.*'

    - name: copiar sitio web
      ansible.builtin.copy:
        src: web/
        dest: '{{ documentroot }}'
        owner: root
        group: root
        mode: 0644

Habilitamos os sitios web http/https e deshabilitamos o sitio por defecto:

    - name: habilitar sitio web 
      ansible.builtin.file:
        src: /etc/apache2/sites-available/{{ nombre_dominio }}.conf
        dest: /etc/apache2/sites-enabled/{{ nombre_dominio }}.conf
        state: link
      notify: reload Apache

    - name: habilitar sitio web https
      ansible.builtin.file:
        src: /etc/apache2/sites-available/{{ nombre_dominio }}_https.conf
        dest: /etc/apache2/sites-enabled/{{ nombre_dominio }}_https.conf
        state: link
      notify: reload Apache

    - name: deshabilitar sitio por defecto
      ansible.builtin.file:
        path: /etc/apache2/sites-enabled/000-default.conf
        state: absent
      notify: reload Apache

Definimos os handler que encárganse de reiniciar os servizos cando haxa cambios na configuración:

  handlers:
    - name: reiniciar Apache
      ansible.builtin.service:
        name: apache2
        state: restarted

    - name: reload Apache
      ansible.builtin.service:
        name: apache2
        state: reloaded

    - name: reiniciar fail2ban
      ansible.builtin.service:
        name: fail2ban
        state: restarted

    - name: reiniciar syslog
      ansible.builtin.service:
        name: rsyslog
        state: restarted            

Lanzamos o playbook:

$ ansible-playbook server-apache.yml -K
BECOME password: 

PLAY [incus] **************************************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************************
ok: [192.0.2.193]
ok: [192.0.2.191]
ok: [192.0.2.192]

TASK [instalar paquetes] ************************************************************************************************************************************************************************
changed: [192.0.2.191]
changed: [192.0.2.193]
changed: [192.0.2.192]

TASK [crear jail.local] *************************************************************************************************************************************************************************
changed: [192.0.2.193]
changed: [192.0.2.191]
changed: [192.0.2.192]

TASK [modificar parametro bantime en jail.local] ************************************************************************************************************************************************
changed: [192.0.2.193]
changed: [192.0.2.191]
changed: [192.0.2.192]

TASK [modificar parametro findtime en jail.local] ***********************************************************************************************************************************************
changed: [192.0.2.191]
changed: [192.0.2.192]
changed: [192.0.2.193]

TASK [modificar parametro maxretry en jail.local] ***********************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.191]
changed: [192.0.2.193]

TASK [anular reduccion mensajes rsyslog] ********************************************************************************************************************************************************
changed: [192.0.2.191]
changed: [192.0.2.193]
changed: [192.0.2.192]

TASK [Arrancar Apache y fail2ban] ***************************************************************************************************************************************************************
ok: [192.0.2.191] => (item=apache2)
ok: [192.0.2.193] => (item=apache2)
ok: [192.0.2.192] => (item=apache2)
ok: [192.0.2.193] => (item=fail2ban)
ok: [192.0.2.191] => (item=fail2ban)
ok: [192.0.2.192] => (item=fail2ban)

TASK [habilitar módulo ssl] *********************************************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.193]
changed: [192.0.2.191]

TASK [añadir virtualhost para el dominio] *******************************************************************************************************************************************************
changed: [192.0.2.191]
changed: [192.0.2.193]
changed: [192.0.2.192]

TASK [añadir virtualhost https para el dominio] *************************************************************************************************************************************************
changed: [192.0.2.191]
changed: [192.0.2.193]
changed: [192.0.2.192]

TASK [copiar certificados sitio web] ************************************************************************************************************************************************************
changed: [192.0.2.191] => (item=/home/manuel/devops/www.manuel2023.test.key)
changed: [192.0.2.192] => (item=/home/manuel/devops/www.manuel2023.test.key)
changed: [192.0.2.193] => (item=/home/manuel/devops/www.manuel2023.test.key)
changed: [192.0.2.191] => (item=/home/manuel/devops/www.manuel2023.test.crt)
changed: [192.0.2.192] => (item=/home/manuel/devops/www.manuel2023.test.crt)
changed: [192.0.2.193] => (item=/home/manuel/devops/www.manuel2023.test.crt)

TASK [copiar sitio web] *************************************************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.191]
changed: [192.0.2.193]

TASK [habilitar sitio web] **********************************************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.191]
changed: [192.0.2.193]

TASK [habilitar sitio web https] ****************************************************************************************************************************************************************
changed: [192.0.2.191]
changed: [192.0.2.192]
changed: [192.0.2.193]

TASK [deshabilitar sitio por defecto] ***********************************************************************************************************************************************************
changed: [192.0.2.191]
changed: [192.0.2.192]
changed: [192.0.2.193]

RUNNING HANDLER [reiniciar Apache] **************************************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.191]
changed: [192.0.2.193]

RUNNING HANDLER [reload Apache] *****************************************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.193]
changed: [192.0.2.191]

RUNNING HANDLER [reiniciar fail2ban] ************************************************************************************************************************************************************
changed: [192.0.2.191]
changed: [192.0.2.193]
changed: [192.0.2.192]

RUNNING HANDLER [reiniciar syslog] **************************************************************************************************************************************************************
changed: [192.0.2.192]
changed: [192.0.2.193]
changed: [192.0.2.191]

PLAY RECAP **************************************************************************************************************************************************************************************
192.0.2.191                : ok=20   changed=19   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.0.2.192                : ok=20   changed=19   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.0.2.193                : ok=20   changed=19   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

Uns comentarios sobre a saída:

  • No caso de erro na execución dunha tarefa párase a execución do playbook.
  • Lanzar repetidas veces o playbook non fará que cambie o estado final dos equipos. Este concepto é coñecido por 'idempotencia'.

O resultado é que nos tres servidores temos a configuración desexada (lembrar que para acceder usando www.manuel2023.test hai que configurar a resolución dns no equipo, por exemplo, a través do arquivo /etc/hosts):

Acceso por https ó servidor web

Fig. Acceso por http e https a www.manuel2023.com en server01

$ ansible incus -m ansible.builtin.shell -a 'ss -ltnp' -b -K
BECOME password: 
192.0.2.192 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    Process                                                                         
LISTEN    0         4096         127.0.0.53%lo:53               0.0.0.0:*        users:(("systemd-resolve",pid=301,fd=13))                                      
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*        users:(("sshd",pid=986,fd=3))                                                  
LISTEN    0         511                      *:80                     *:*        users:(("apache2",pid=17251,fd=4),("apache2",pid=17250,fd=4),("apache2",pid=17249,fd=4),("apache2",pid=17248,fd=4),("apache2",pid=17247,fd=4),("apache2",pid=17211,fd=4))
LISTEN    0         128                   [::]:22                  [::]:*        users:(("sshd",pid=986,fd=4))                                                  
LISTEN    0         511                      *:443                    *:*        users:(("apache2",pid=17251,fd=6),("apache2",pid=17250,fd=6),("apache2",pid=17249,fd=6),("apache2",pid=17248,fd=6),("apache2",pid=17247,fd=6),("apache2",pid=17211,fd=6))
192.0.2.191 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    Process                                                                         
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*        users:(("sshd",pid=987,fd=3))                                                  
LISTEN    0         4096         127.0.0.53%lo:53               0.0.0.0:*        users:(("systemd-resolve",pid=301,fd=13))                                      
LISTEN    0         128                   [::]:22                  [::]:*        users:(("sshd",pid=987,fd=4))                                                  
LISTEN    0         511                      *:443                    *:*        users:(("apache2",pid=17073,fd=6),("apache2",pid=16965,fd=6),("apache2",pid=16964,fd=6),("apache2",pid=16963,fd=6),("apache2",pid=16962,fd=6),("apache2",pid=16961,fd=6),("apache2",pid=16925,fd=6))
LISTEN    0         511                      *:80                     *:*        users:(("apache2",pid=17073,fd=4),("apache2",pid=16965,fd=4),("apache2",pid=16964,fd=4),("apache2",pid=16963,fd=4),("apache2",pid=16962,fd=4),("apache2",pid=16961,fd=4),("apache2",pid=16925,fd=4))
192.0.2.193 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    Process                                                                         
LISTEN    0         4096         127.0.0.53%lo:53               0.0.0.0:*        users:(("systemd-resolve",pid=301,fd=13))                                      
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*        users:(("sshd",pid=988,fd=3))                                                  
LISTEN    0         128                   [::]:22                  [::]:*        users:(("sshd",pid=988,fd=4))                                                  
LISTEN    0         511                      *:443                    *:*        users:(("apache2",pid=17244,fd=6),("apache2",pid=17243,fd=6),("apache2",pid=17242,fd=6),("apache2",pid=17241,fd=6),("apache2",pid=17240,fd=6),("apache2",pid=17204,fd=6))
LISTEN    0         511                      *:80                     *:*        users:(("apache2",pid=17244,fd=4),("apache2",pid=17243,fd=4),("apache2",pid=17242,fd=4),("apache2",pid=17241,fd=4),("apache2",pid=17240,fd=4),("apache2",pid=17204,fd=4))
$ ansible incus -m ansible.builtin.shell -a 'apache2ctl -S' -b -K
BECOME password: 
192.0.2.191 | CHANGED | rc=0 >>
VirtualHost configuration:
*:80                   www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test.conf:1)
*:443                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test_https.conf:1)
ServerRoot: "/etc/apache2"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/var/log/apache2/error.log"
Mutex ssl-stapling: using_defaults
Mutex ssl-cache: using_defaults
Mutex default: dir="/var/run/apache2/" mechanism=default 
Mutex mpm-accept: using_defaults
Mutex watchdog-callback: using_defaults
Mutex ssl-stapling-refresh: using_defaults
PidFile: "/var/run/apache2/apache2.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="www-data" id=33
Group: name="www-data" id=33
192.0.2.193 | CHANGED | rc=0 >>
VirtualHost configuration:
*:80                   www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test.conf:1)
*:443                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test_https.conf:1)
ServerRoot: "/etc/apache2"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/var/log/apache2/error.log"
Mutex watchdog-callback: using_defaults
Mutex ssl-stapling-refresh: using_defaults
Mutex ssl-stapling: using_defaults
Mutex ssl-cache: using_defaults
Mutex default: dir="/var/run/apache2/" mechanism=default 
Mutex mpm-accept: using_defaults
PidFile: "/var/run/apache2/apache2.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="www-data" id=33
Group: name="www-data" id=33
192.0.2.192 | CHANGED | rc=0 >>
VirtualHost configuration:
*:80                   www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test.conf:1)
*:443                  www.manuel2023.test (/etc/apache2/sites-enabled/www.manuel2023.test_https.conf:1)
ServerRoot: "/etc/apache2"
Main DocumentRoot: "/var/www/html"
Main ErrorLog: "/var/log/apache2/error.log"
Mutex ssl-stapling-refresh: using_defaults
Mutex ssl-stapling: using_defaults
Mutex ssl-cache: using_defaults
Mutex default: dir="/var/run/apache2/" mechanism=default 
Mutex mpm-accept: using_defaults
Mutex watchdog-callback: using_defaults
PidFile: "/var/run/apache2/apache2.pid"
Define: DUMP_VHOSTS
Define: DUMP_RUN_CFG
User: name="www-data" id=33
Group: name="www-data" id=33

Instalación

Python

Na máquina servidora e cliente require Python (no momento actual v2.6 ou superior):

usuario@servidorAnsible:~$ python3 -V
Python 3.12.1

Dependencias

Para as dependencias:

apt install software-properties-common

Ansible

Para instalar Ansible:

root@servidorAnsible:~# apt install ansible

Comprobamos que queda instalado:

root@servidorAnsible:~# ansible --version
ansible [core 2.14.3]
 config file = None
 configured module search path = ['/root/.ansible/plugins/modules',
'/usr/share/ansible/plugins/modules']
 ansible python module location =
/usr/lib/python3/dist-packages/ansible

Configuración

Non xerou ficheiro de configuración, e precisamos dous:

 config file = None
/etc/ansible/ansible.cfg
Configuración de ansible
/etc/ansible/hosts
Inventario de equipos
Especificamos os equipos que serán administrados por ansible
Podemos especificalos empregando FQDN ou IP’s
Para empregar FQDN precisamos ter un servidor DNS na nosa rede
Permite agrupar os equipos en aulas ou departamentos

Configuración de Ansible - ansible.cfg

Creamos o arquivo de configuración a man na ruta por defecto:

root@servidorAnsible:~# mkdir /etc/ansible/
root@servidorAnsible:~# cd /etc/ansible/
root@servidorAnsible:/etc/ansible# vi ansible.cfg
[defaults]
inventory=/etc/ansible/hosts

Comprobamos como xa emprega o noso arquivo de configuración:

root@servidorAnsible:/etc/ansible# ansible --version
ansible [core 2.14.3]
 config file = /etc/ansible/ansible.cfg
 configured module search path = ['/root/.ansible/plugins/modules',
'/usr/share/ansible/plugins/modules']

Configuración de Ansible - inventario

Crearemos os arquivos de configuración en /etc/ansible

Temos que engadir os clientes en /etc/ansible/hosts. Este é un arquivo moi importante no que seDefine o inventario de equipos a xestionar mediante ansible
Definimos dous grupos de clientes correspondentes a dúas aulas ficticias
Poderemos xestionalos de xeito individual ou de xeito conxunto
Se tivésemos un Servidor DNS poderíamos empregar nomes de equipos, de momento só IP’s
[aula1]
10.0.2.10
[aula2]
10.0.2.20

Para crear o arquivo de inventario (aínda que só temos dous equipos clientes, damos de alta outros dous ficticios):

root@servidorAnsible:/etc/ansible# vi hosts
#Definimos os equipos da Aula1
[aula1]
10.0.2.10
Definimos os equipos da Aula2
[aula2]
10.0.2.20

Para comprobar que o inventario está correctamente configurado:

root@servidorAnsible:/etc/ansible# ansible all --list-hosts
 hosts (2):
 10.0.2.10
 10.0.2.20

Primeiras probas con ansible

Empregamos o módulo ping de ansible para comprobar a conexión cos nodos clientes (Importante: asegúrate que estén arrancados!!)

Sintaxe: ansible Equipos -m módulo
Se queremos saber se os equipos da Aula1 están acendidos
ansible aula1 -m ping

Inicialmente, teremos erro: Ansible emprega ssh para conectarse co cliente, como é a primeira vez que se conecta con ese cliente pídenos confirmación

root@servidorAnsible:/etc/ansible# ansible aula1 -m ping
The authenticity of host '10.0.2.10 (10.0.2.10)' can't be established.
ED25519 key fingerprint is SHA256:/E+kj4vt6mKk2ud2cbKew2816I0ZwmM2I8RMhXefUQM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
10.0.2.10 | UNREACHABLE! => {
 "changed": false,
 "msg": "Failed to connect to the host via ssh: Warning: Permanently added '10.0.2.10'
(ED25519) to the list of known hosts.\r\nroot@10.0.2.10: Permission denied
(publickey,password).",
 "unreachable": true
}

Con -u indicamos usuario, pero falla novamente porque non sabe o contrasinal dese usuario para realizar a conexión por ssh:

root@servidorAnsible:/etc/ansible# ansible aula1 -m ping -u usuario 10.0.2.10 | UNREACHABLE! => {

"changed": false,
"msg": "Failed to connect to the host via ssh: usuario@10.0.2.10: Permission denied

(publickey,password).",

"unreachable": true

}

Con -k contrasinal, pero falla unha vez máis porque é necesario ter instalado sshpass no servidor ansible

root@servidorAnsible:/etc/ansible# ansible aula1 -m ping -u usuario -k
SSH password:
10.0.2.10 | FAILED! => {
 "msg": "to use the 'ssh' connection type with passwords or pkcs11_provider, you must
install the sshpass program"

Instalamos sshpass:

root@servidorAnsible:/etc/ansible# apt install sshpass

Ahora sí devolverá en cor verde (os erros estaban amosándose en vermello) indicando éxito. O equipo 10.0.2.10 respondeu o móudlo ping correctamente. A resposta é un JSON que pode conter moita información:

root@servidorAnsible:/etc/ansible# ansible aula1 -m ping -u usuario -k
SSH password:
10.0.2.10 | SUCCESS => {
 "ansible_facts": {
 "discovered_interpreter_python": "/usr/bin/python3"
 },
 "changed": false,
 "ping": "pong"

De non estar acendido, a resposta sería:

root@servidorAnsible:/etc/ansible# ansible aula1 -m ping -u usuario -k
SSH password:
10.0.2.10 | SUCCESS => {
 "ansible_facts": {
 "discovered_interpreter_python": "/usr/bin/python3"
 },
 "changed": false,
 "ping": "pong"
10.0.2.11 | UNREACHABLE! => {
 "changed": false,
 "msg": "Failed to connect to the host via ssh: ssh: connect to host 10.0.2.11 port
22: No route to host",
 "unreachable": true

Con isto so fixemos un ping a un equipo mais se tivésemos dados de alta 100 equipos dentro da categoría aula1 con un só comando, veríamos cales responden e polo tanto saberíamos cales están acendidos

Ampliación

Tarefas

  1. Tarefa 1 - Creación do Servidor Ansible

Referencias