Actividad: Ansible
Ansible es una herramienta de administración remota que permite permite definir estados (que esté instalada esta herramienta, o que exista aquella interfaz de red, ...) y llevar a los equipos hasta dicho estado realizando las operaciones que sean necesarias.
Toma su nombre de un dispositivo fictício que citó por primera vez Ursula K. Le Guin en su novela El mundo de Rocannon. En estas novelas el ansible permite la comunicación instantánea entre dos puntos cualquiera del universo. Y la verdad es que al verlo funcionar uno no puede más que pensar que se trata de un nombre apropiado.
Ansible es extremadamente ligero. Únicamente debe instalarse en la máquina que controla a las demás, y accede a los equipos remotos utilizando SSH.
Ansible cuenta con diferentes módulos para realizar operaciones de manera idempotente. Lo que realmente simplifica el uso de Ansible, pues no hay que pensar en condiciones. Se pueden listar todas las operaciones a realizar y únicamente producirán efecto aquellas que sean necesarias (por no estar el host de acuerdo al estado especificado).
Más información:
- Ansible.
- Documentación oficial de ansible.
- Ansible: Inventory, Playbooks, Module Index.
- Algunos playbooks de ejemplo utilizados en el centro.
Actividad 1: Preparación de Ansible. Uso de un playbook.
- A partir de la máquina virtual proporcionada por el profesor, realice dos clones enlazados: Dolly y Beorn.
- En Beorn genere un par de claves. Instale la clave pública de Beorn en Dolly, de manera que el usuario 'usuario' pueda hacer ssh root@ip_de_dolly.
- Apague Dolly, y a partir de Dolly clone Dolly1 y Dolly2.
- Utilice Ansible en Beorn para cambiar de modo automático el hostname (/etc/hosts y /etc/hostname) de Dolly1 y Dolly2 de manera que reciban como hostname Dolly-XXX. Siendo XXX el byte de menor peso de su IPv4.
Actividad 2: Módulo setup
Utilice el comando ansible con el módulo setup para obtener información de las máquinas Dolly1 y Dolly2.
Actividad 3: Corregir el destrozo de un usuario novel de Ansible.
Aunque lo primero que hace la documentación oficial de Ansible es advertir que se deben utilizar módulos específicos para que las tareas sean idempotentes. Un usuario novel de Ansible que no tenía ganas de leer la documentación decidió esciribir un script, que al ejecutarse en los hosts remotos mediante Ansible, declarara la lista de usuarios que está en un fichero de datos.
A continuación se muestra el script y el fichero de datos.
Script: crea_profesores
#!/bin/bash
# Este script lee el fichero profesores y define los usuarios en los ordenadores del profe.
# Ojo: restaura las contraseñas!
#
# El formato del fichero es login:password, una línea para cada usuario.
#target='profes'
target='192.168.16.124'
for x in `cat profesores`
do
login=`echo $x | cut -f1 -d':'`
ansible $target -u root -m user -a "name=$login append=yes groups=dialout,wireshark,lxd,libvirtd"
ansible $target -u root -m shell -a "echo $x | chpasswd"
done
Fichero: profesores
adria:1234
q2dg:1234
vcarceler:1234
rborrell:1234
jordifarrero:1234
jmonserrat:1234
jherna76:1234
mperram4:1234
ttejero:1234
jolluso:1234
salarnal:1234
daniel.martinez:1234
slopez:1234
amacias:1234
smart52:1234
joan:1234
tarek:1234
Escriba el playbook adecuado para realizar el trabajo equivalente tal y como lo haría un usuario experimentado de Ansible.
Actividad 4: Actualizar los parámetros de grub2 para evitar bloqueos
En un aula de un centro educativo existen equipos que se bloquean si no utilizan el parámetro intel_idle.max_cstate=1 al arrancar. Este parámetro se puede especificar en el fichero de configuración /etc/default/grub.
Mediante la directiva:
GRUB_CMDLINE_LINUX_DEFAULT="intel_idle.max_cstate=1"
Después será necesario instalar de nuevo grub con la nueva configuración:
sudo update-grub
Pero en este mismo aula hay otros equipos que no necesitan esta solución porque no tienen este problema. ¿Cómo se puede escribir un playbook de Ansible que únicamente aplique la solución en los equipos afectados por el problema (si es que no tienen ya la solución aplicada)?
Utilizando el módulo setup para obtener los detalles de un equipo afectado por el problema se obtiene:
vcarceler@baba-yaga:~$ ansible 192.168.14.181 -m setup -u root
192.168.14.181 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.14.181",
"192.168.122.1"
],
"ansible_all_ipv6_addresses": [
"fe80::6c7:f5cd:f790:2953"
],
"ansible_architecture": "x86_64",
"ansible_bios_date": "05/21/2014",
"ansible_bios_version": "P1.30",
"ansible_cmdline": {
"BOOT_IMAGE": "/boot/vmlinuz-4.4.0-53-generic",
"quiet": true,
"ro": true,
"root": "UUID=c8c6546a-4789-4227-a392-061182f2ed86",
"splash": true,
"vt.handoff": "7"
},
"ansible_date_time": {
"date": "2017-02-15",
"day": "15",
"epoch": "1487173912",
"hour": "16",
"iso8601": "2017-02-15T15:51:52Z",
"iso8601_basic": "20170215T165152993667",
"iso8601_basic_short": "20170215T165152",
"iso8601_micro": "2017-02-15T15:51:52.993863Z",
"minute": "51",
"month": "02",
"second": "52",
"time": "16:51:52",
"tz": "CET",
"tz_offset": "+0100",
"weekday": "Wednesday",
"weekday_number": "3",
"weeknumber": "07",
"year": "2017"
},
"ansible_default_ipv4": {
"address": "192.168.14.181",
"alias": "enp4s0",
"broadcast": "192.168.14.255",
"gateway": "192.168.14.10",
"interface": "enp4s0",
"macaddress": "d0:50:99:3d:10:38",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "192.168.14.0",
"type": "ether"
},
"ansible_default_ipv6": {},
"ansible_devices": {
"sda": {
"holders": [],
"host": "SATA controller: Intel Corporation Atom Processor E3800 Series SATA AHCI Controller (rev 0e)",
"model": "CT250BX100SSD1",
"partitions": {
"sda1": {
"sectors": "476076032",
"sectorsize": 512,
"size": "227.01 GB",
"start": "2048"
},
"sda2": {
"sectors": "2",
"sectorsize": 512,
"size": "1.00 KB",
"start": "476078080"
},
"sda5": {
"sectors": "12316672",
"sectorsize": 512,
"size": "5.87 GB",
"start": "476078082"
}
},
"removable": "0",
"rotational": "0",
"scheduler_mode": "deadline",
"sectors": "488397168",
"sectorsize": "512",
"size": "232.89 GB",
"support_discard": "512",
"vendor": "ATA"
}
},
"ansible_distribution": "Ubuntu",
"ansible_distribution_major_version": "16",
"ansible_distribution_release": "xenial",
"ansible_distribution_version": "16.04",
"ansible_dns": {
"nameservers": [
"127.0.1.1"
],
"search": [
"aif.elpuig.xeill.net"
]
},
"ansible_domain": "",
"ansible_enp4s0": {
"active": true,
"device": "enp4s0",
"ipv4": {
"address": "192.168.14.181",
"broadcast": "192.168.14.255",
"netmask": "255.255.255.0",
"network": "192.168.14.0"
},
"ipv6": [
{
"address": "fe80::6c7:f5cd:f790:2953",
"prefix": "64",
"scope": "link"
}
],
"macaddress": "d0:50:99:3d:10:38",
"module": "r8169",
"mtu": 1500,
"pciid": "0000:04:00.0",
"promisc": false,
"type": "ether"
},
"ansible_env": {
"HOME": "/root",
"LANG": "C",
"LC_ALL": "C",
"LC_MESSAGES": "C",
"LOGNAME": "root",
"MAIL": "/var/mail/root",
"PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games",
"PWD": "/root",
"SHELL": "/bin/bash",
"SHLVL": "1",
"SSH_CLIENT": "192.168.14.13 40820 22",
"SSH_CONNECTION": "192.168.14.13 40820 192.168.14.181 22",
"SSH_TTY": "/dev/pts/5",
"TERM": "xterm-256color",
"USER": "root",
"XDG_RUNTIME_DIR": "/run/user/0",
"XDG_SESSION_ID": "4",
"_": "/usr/bin/python"
},
"ansible_fips": false,
"ansible_form_factor": "Desktop",
"ansible_fqdn": "aig-181",
"ansible_hostname": "aig-181",
"ansible_interfaces": [
"lo",
"enp4s0",
"virbr0-nic",
"virbr0"
],
"ansible_kernel": "4.4.0-53-generic",
"ansible_lo": {
"active": true,
"device": "lo",
"ipv4": {
"address": "127.0.0.1",
"broadcast": "host",
"netmask": "255.0.0.0",
"network": "127.0.0.0"
},
"ipv6": [
{
"address": "::1",
"prefix": "128",
"scope": "host"
}
],
"mtu": 65536,
"promisc": false,
"type": "loopback"
},
"ansible_lsb": {
"codename": "xenial",
"description": "Ubuntu 16.04 LTS",
"id": "Ubuntu",
"major_release": "16",
"release": "16.04"
},
"ansible_machine": "x86_64",
"ansible_machine_id": "fe1932bff8ef420f9cbcfb7348c7d36b",
"ansible_memfree_mb": 5530,
"ansible_memory_mb": {
"nocache": {
"free": 6595,
"used": 1094
},
"real": {
"free": 5530,
"total": 7689,
"used": 2159
},
"swap": {
"cached": 0,
"free": 6013,
"total": 6013,
"used": 0
}
},
"ansible_memtotal_mb": 7689,
"ansible_mounts": [
{
"device": "/dev/sda1",
"fstype": "ext4",
"mount": "/",
"options": "rw,relatime,errors=remount-ro,data=ordered",
"size_available": 103209230336,
"size_total": 239790317568,
"uuid": "c8c6546a-4789-4227-a392-061182f2ed86"
}
],
"ansible_nodename": "aig-181",
"ansible_os_family": "Debian",
"ansible_pkg_mgr": "apt",
"ansible_processor": [
"GenuineIntel",
"Intel(R) Celeron(R) CPU J1900 @ 1.99GHz",
"GenuineIntel",
"Intel(R) Celeron(R) CPU J1900 @ 1.99GHz",
"GenuineIntel",
"Intel(R) Celeron(R) CPU J1900 @ 1.99GHz",
"GenuineIntel",
"Intel(R) Celeron(R) CPU J1900 @ 1.99GHz"
],
"ansible_processor_cores": 4,
"ansible_processor_count": 1,
"ansible_processor_threads_per_core": 1,
"ansible_processor_vcpus": 4,
"ansible_product_name": "To Be Filled By O.E.M.",
"ansible_product_serial": "To Be Filled By O.E.M.",
"ansible_product_uuid": "03000200-0400-0500-0006-000700080009",
"ansible_product_version": "To Be Filled By O.E.M.",
"ansible_python_version": "2.7.12",
"ansible_selinux": false,
"ansible_service_mgr": "systemd",
"ansible_ssh_host_key_dsa_public": "AAAAB3NzaC1kc3MAAACBALBtHUG2xGwZ9ZJXMeFgz9xNGghM7vhU9UeY767xiCwT+q3z9rNoYllqkSK2XYDZ+/miFKftnyxmmFqjVIWT7TNjIgeg4l1VIEQeV3rTl7YyN/nlEFOSqGR9i9XMeoAXuf6WgbWhzskvoxFM+rKtdtjTiauC9jsS6h+diPihaHi5AAAAFQDEzMZ7R75oHd6bWk2yR7M19FbnGwAAAIEAj0ZgXh2v+FzMUDPzFaJWDyvIvDB5L7h41m72xF/PcNhGN/rtm3idMsfJX2YSdTGIgNE3dHnp/0+G63U6fYJzlNvaPqyMgMxwrLx00Y5PVB14netJTfduMqqEyok+PjLeU2/cclTNVA62WalRtaKBpFlYvmacxrgZz/myYMP1CJQAAACAFN09FKoDRvMmZVcvhxrvEx7veQ7l02kYB/iUsmAaZM4X518JEcliN47myBltP21o0LTSuDue1IwIzcMTYLeGdA+bN7kXiIaBvx5yMKlaUAVcUVHsLtyB+rOtdboVdrtCEDI9nYn0zig/fvge5l+UvezNfYNdMllE+7LpqvDs97w=",
"ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ+7mzjgLa6WDepZuvmZWPohJYdAmL5MMZXgb7mCdyaAsNUOFPjjvdEnF3O8PHv5NTbxZFEYK+zq/ml9YZY83uc=",
"ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIOvlP+E+sMYdQXNtdEL0tZVOAr8xULXNpc2IKDonTVNq",
"ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQC1UV3BgYuodTJGEI2pHSXj2VGrj/WwzyhzHZ+qu8r6jQC184niAsFY6X3v7XK4vn/TJiGQ6i/StRmFvcz2QX/XeJRXJ6xn8BXxtLxiokZKirK0gcqiHo/QoO9dXEhW8aWswB+lx1tvPCl9/PKZdh5OS2WX3Qaij43iOFtZ5+jGTaxjvQPjwthC6/NMrwScZFR1iLZkXPuzX11Wzdsphg6tdmlRDBRztCYxssxMIhO3W8zxNxZGgcpHRBsgSWbxdSOdYfrGW0CMEj4/W/JoblxKTKXgb0haGZLvZ78LUNyMl06QveHAJ0jgPkGxg8qhqm3NbO+DW2F0Lr9116JVe+PN",
"ansible_swapfree_mb": 6013,
"ansible_swaptotal_mb": 6013,
"ansible_system": "Linux",
"ansible_system_vendor": "To Be Filled By O.E.M.",
"ansible_uptime_seconds": 2620,
"ansible_user_dir": "/root",
"ansible_user_gecos": "root",
"ansible_user_gid": 0,
"ansible_user_id": "root",
"ansible_user_shell": "/bin/bash",
"ansible_user_uid": 0,
"ansible_userspace_architecture": "x86_64",
"ansible_userspace_bits": "64",
"ansible_virbr0": {
"active": false,
"device": "virbr0",
"id": "8000.000000000000",
"interfaces": [],
"ipv4": {
"address": "192.168.122.1",
"broadcast": "192.168.122.255",
"netmask": "255.255.255.0",
"network": "192.168.122.0"
},
"mtu": 1500,
"promisc": false,
"stp": true,
"type": "bridge"
},
"ansible_virbr0_nic": {
"active": false,
"device": "virbr0-nic",
"macaddress": "52:54:00:a5:74:c1",
"mtu": 1500,
"promisc": false,
"type": "ether"
},
"ansible_virtualization_role": "host",
"ansible_virtualization_type": "kvm",
"module_setup": true
},
"changed": false
}
vcarceler@baba-yaga:~$