Trabajando con ansible

Hola a todos,

Este post va basado en mis experiencias actuales usando Ansible para entornos Cloud.
Comenzaré el post explicando como hago el deploy de 1 máquina virtual hasta terminar en servicios solamente automatizando con ansible, siendo un poco largo al inicio y ya luego acortando el contenido porque cada uno debe leer/estudiar por su parte la documentación que dejaré en los links mientras explico.

Por tanto este contenido es mas para sysadmin ya de nivel medio, no para los que comienzan a usar linux/redes. Para eso pueden ver otros tutoriales más simples sobre ansible que hay montones de cursos al respecto. Solo veremos las cosas prácticas.

Los posts, serán de alguna manera: “lo más masticado posible” para los que no saben usar esta herramienta aún, vean de donde salen las cosas y porqué?.

En mi trabajo se usa VMware, por tanto demostraré el uso para los que ya esten sobre este hypervisor.

Se que muchos usan Proxmox, no obstante estoy intentando instalarlo en mi laptop para poder hacer las mismas cosas que verán con VMware. El caso es ver como funciona ansible así que concentrémonos en eso. No obstante solo será este post para el despliegue con vmware porque el resto son específicamente ya para los Linux y Windows. Sí! por que ansible también funciona con Windows

Situación inicial en el cloud:
– Como desplegar una o varias máquinas virtuales rápidamente?

Un sysadmin cuando va a instalar una VM nueva, sea en cualquier hypervisor siempre haría por lo general.

  1. Descargar la image ISO y copiarla por la red al storage del hypervisor (5/10 minutos?)
  2. Darles parámetros como CPU, RAM, HDD a la VM (1 min)
  3. Seguir los pasos de instalación seteando la partición del HDD, nombre del host, IP etc. (1 min total de toda la información)
  4. Instalar el OS (el resto del tiempo hasta que reinicia y te da login: otros 7/15 min dependencia del hardware)
  5. Hacer update/upgrade desde repositorios de seguridad nuevamente del OS apenas instalado para tenerlo al día junto con sus parches (2/10 minutos en dependencia del ancho de banda)

Entonces contando desde el 1er paso digamos que como promedio:  ~ 40/45min.

Mucho tiempo!, y si a eso, se le agrega que debemos hacer por ejemplo otras 4 VM porque son para diferentes cosas, sería este proceso inicial de nuevo y repetirlo por otros 40/45 min.
En fin, te hechas el día solo instalando sin contar que te llamen por teléfono, o te interrumpa algún usuario en tu red.

Aquí es donde entraría a trabajar ansible.

En mi opinión creo, para usar esta herramienta hay tener en consideración 4 cosas:

  1. Ansible siendo orquestador “como un framework” para gestionar algunas cosas de infrastructura, servers y/o servicios esta basado en Python por tanto hay que conocer un poco del lenguaje en el caso de crear algun módulo propio de ansible y para eso, siguiendo su documentación en este enlace.
  2. Usar el concepto de “Infrastructura como Código” (Infrastucture as Code o IaC como se le conoce) debes o es MUY recomendado trabajar con sistemas de control de versiones para usarlos como repositorios de tus configuraciones, por ende hay que saber Git, SVN o mercurial.
  3. Ansible usa en las configuraciones un formato YAML que explican en su documentación oficial, por tanto hay que conocer de YAML,
    De donde sale este YAML?, Pues aqui  en la documentación oficial encontraran todo lo relacionado con el tema.
  4. Por otra parte para los templates usan el formato Jinja2 que python utiliza mucho en su framework Django.
    Donde leo sobre Jinja2? , pues a la hora de hacer algun template en ansible te servira su documentación oficial.
  5. Una cosa muy importante que debes conocer es:  “Tus configuraciones deberían ser lo mas idempotente posible.”

Que es idempotente?

Pues es el resultado de seguir una operación una sola vez, y dando el mismo resultado tantas veces se repita sin ningun intervento.

No entiendo! dame un ejemplo rápido.

Muy sencillo, creas una configuración para cambiar un .conf dentro de uno o algunos servers, esto ocurre una sola vez, pero si repites de nuevo esa accion, Ansible compara y “ve” que eso esta hecho y te dira que no hará falta pasando para el proximo paso. Solamente cambiara una vez cuando en su configuración se vuelve a modificar.

Para que serviría?

Pues mantener toda la configuración de los servicios siempre escritos en un file donde Ansible lee esta informacion, que usara para ser desplegada en los servidores y que tendra el mismo resultado SIEMPRE, y si alguien toca a mano una configuración directamente en el servidor y Ansible vuelve a ser ejecutado, volvera a poner la configuración que esta leyendo donde tiene los valores asignados en cada playbook regresando a lo que tenia antes. Garantizando evitar errores humanos.

Teniendo esto en cuenta, lo siguiente que haríamos es hacer el proceso del inicio pero, “una última vez.”

Porque?

Pues prepararás una imagen que usarás como template donde ya estaria todo listo.

Me quedé por el paso 5 al inicio ?

6- Instalamos el paquete “sudo
7- Creamos un user por ejemplo: “ansible” -> useradd ansible
8- Generamos una clave aleatoria bien fuerte por seguridad, (hay muchas maneras de hacerla, puedes usar esta: date +%s | sha256sum | base64 | head -c 32 ; echo
9- Escribimos dentro de “/etc/sudoers” que el user “ansible” haga todo como si fuera root agregando la línea al final del fichero.

ansible ALL=(ALL:ALL) NOPASSWD: ALL

10- Instalas los paquetes necesarios: “python, sshpass”
11- Apagas la VM
12- Haces clic derecho en la VM dentro del VMware y seleccionas Template y le das convertir en Template.

En mi caso usamos como distro template, CentOS quedando esto en VMWare

Teniendo ya esto preparado entonces iremos a nuestra pc y de acuerdo a la distro usando su documentación oficial instalamos ansible.
Luego, nos haremos una carpeta donde tendremos nuestros despliegues con la siguiente estructura

$ mkdir -p ~/deploys/{files,roles,inventories,inventories/group_vars,vault,templates}
$ cd ~/deploys/
$ git init .
(Uso git en mi caso como control de versiones)

en “/etc/ansible/ansible.cfg” luego de estar instalado encontraran el fichero de configuración que tendra un contenido extenso pero de momento solo usaremos 3 líneas fundamentales.

  • Definir el fichero del inventario que usando la estructura que creamos quedaria en “/home/mi_user/deploys/inventories/inventory”
  • Decir que el user con el que me trabajaria seria “ansible” que especificamos arriba “que esta creado dentro del template.”
  • Y que se haga “root usando sudo” para seguir los comandos administrativos. (gracias a que en el sudoers ya definimos anteriormente en el template)

Como nota aparte: Aqui en realidad personalmente para mi, esta bien porque yo usaria un user del sistema solo para hacer despliegues, y que este se convierte en root cuando lo necesite, porque asi continuo a mantener seguro por ssh que  “root” no se conecte directamente definiendolo en “/etc/ssh/sshd_config” con la línea “PermitRootLogin no”.
Y no entraria aunque pongas la clave de root correctamente por definición.

Creamos un fichero “linux.yml” dentro de la carpeta “inventary/group_vars/” y dentro escribimos estas líneas para poder conectarnos con el user ansible y su clave que generamos anteriormente.

$ cat >~/deploys/group_vars/linux.yml << EOF
# Ansible connection
ansible_user: ansible
ansible_password: (la password que generamos en el paso 8)
EOF

Aqui hay que hacer una cosa, meter en seguridad estas credenciales, porque si!, es verdad que fue generada aleatoriamente!,que es fuerte por la complejidad que tiene!, pero sigue estando en “texto plano” por tanto hay que cifrar esta variable.

Como hacemos esto?

Pues ansible tiene uno de sus comandos que se llama ansible-vault donde esta bien documentado en el sitio de ellos

ejecutamos esta línea:

echo "la_clave_que_generastes_para_el_user_ansible" | ansible-vault encrypt_string
New Vault password: <- DEFINES UNA CLAVE PARA TI QUE NO SALVARAS EN NINGUN LADO Y SOLO SABRAS
Confirm New Vault password: <- CONFIRMAS
Reading plaintext input from stdin. (ctrl-d to end input)
!vault |
$ANSIBLE_VAULT;1.1;AES256
11111111111111111111111111111111111111111111111111111111111111111111111111111111
22222222222222222222222222222222222222222222222222222222222222222222222222222222
11111111111111111111111111111111111111111111111111111111111111111111111111111111
22222222222222222222222222222222222222222222222222222222222222222222222222222222
3333333333333333333333333
Encryption successful

El resultado que genera sera “el string que pusistes (en este caso la clave de texto plano generada aleatoreamente)” para el user “ansible” cuando se conecte a los servidores.
Copias esa salida al fichero sustiyendo “la de texto plano” por esa salida cifrada quedando asi.

ansible_user: 'ansible'
ansible_password: !vault |
$ANSIBLE_VAULT;1.2;AES256;prod
11111111111111111111111111111111111111111111111111111111111111111111111111111111
22222222222222222222222222222222222222222222222222222222222222222222222222222222
11111111111111111111111111111111111111111111111111111111111111111111111111111111
22222222222222222222222222222222222222222222222222222222222222222222222222222222
3333333333333333333333333

Porque hacemos esto?

Pues por seguridad!,… porque había dicho que usariamos un control de versiones y además para mantener los despliegues que quizas trabajando en team se vean en claro en el repositorio de códigos.

Sin embargo existen en otros lugares que, aunque las otras personas del equipo ayuden a hacer playbooks PERO, que NO están autorizado a hacer los despliegues en producción, por tanto, no tienen porque saber la clave de los servidores. Entonces esta seccion va cifrada!, y en los trackings de historiales del control de versiones solo se ve lo anterior y no la clave en claro.

Como todo, depende de que si trabajas solo, no te hace falta, o si comparten en el mismo team la clave la saben todos pero igual como seguridad esta fuera del git, o pueden optar por este tipo de jerarquia visto que en los servicios cloud si algo no va responde el responsable del servicio quien seguro evitara tomando este tipo de medidas.

Hacemos lo mismo para cualquier tipo de credenciales, por ejemplo, como me conectaré a un hypervisor de VMware pues pondremos también la autenticación ya cifrada en otro fichero para vmware y repetimos el paso anteior para cifrar la password, incluso el user si quieren.

A este punto ahora si podríamos hacer un "git commit-a"  Y seguir con el repositorio de versiones sin el problema de que las credenciales sean visibles.

Ansible tiene en su Core muchísimos modulos creado por el Team de Ansible, y otros creados por la comunidad..

En el caso que nos ocurre para generar la VM es vmware-guest.

Como se cual es el módulo que necesito y no otro?

Bueno una de las maneras es ver lista completa de los modulos en su sitio oficial, y la otra es directamente por el shell con el comando “ansible-doc -l”. 
Y siendo tan larga la lista, usando un filtro podremos ver en la descripcion:

$ ansible-doc -l | egrep 'vmware' | egrep 'virtual machines'
vmware_guest Manages virtual machines in vCenter

Por tanto crearemos un playbook que nos ayudara a generar la vm en el cluster de VMware atravez del vCenter usando este módulo.

Entramos a nuestra carpeta deploys y creamos el despliegue para la VM que al interno del fichero estarán todas las especificaciones como mismo habías hecho anteriormente de manera manual salvando este contenido en un fichero con terminación “.yml o .yaml” (linux asocia qualquiera de los 2).

Este ejemplo también lo encontramos en la documentación del módulo vmware_guest

Creo que es bastante claro cada opción que se esta definiendo como para que sea explicada. Para entender los playbooks basta leer la documentación

En este caso quiero aclarar que usamos en el template la instalacion con LVM, porque gracias a su versatilidad con el hecho de mover particiones de manera lógica sin tener que apagar las VM es mas comodo también para luego poder usar el módulo de ansible con LVM y gestionar esto de manera facil.

Otra cosa que se ve en el playbook para que se entienda mejor es que el se conecta a “localhost”. Cuando lean la documentación de ansible, verán que en otras condiciones siempre usarás ahi las variables que escribiras en el inventario para especificar a cuales servers mandaras la accion a desplegar, pero en el caso de vmware, o cualquier proveedor de servicio cloud, es mas común que veas localhost.

Porque ?

Pues normalmente este módulo usa la API de vmware, como usara con la API de los otros proveedores Cloud a la hora de crear una infrastructura. Ya luego creando la VM entonces si accederemos al ssh de cada linux donde si en la variables “hosts” definiremos en el inventario el server que usaremos para desplegar cualquier servicio.

A este punto podemos desplegar la VM usando el comando:

ansible-playbook provision-infra-test-centos.yml --vault-id @prompt

Qué hará ansible?

“–vault-id @prompt” es la opción que se le pasará a ansible para cuando ejecute el playbook y te pregunte “la clave” que pusistes para generar el cifrado del user ansible al server linux que esta convertido en template. Y también para poder decifrar las credenciales de vmware que las buscará en el playbook donde dice “vars_files” localizado dentro de la carpeta vault.

Logrando esto ansible podrá usarlo cuando despliega, de otra manera verá que hay algo cifrado y dará error.

Ansible, con las credenciales de VMWare usará la API y podrá conectarse al vCenter, creará una vm nueva con el nombre definido en el fichero del playbook, junto a los demás datos, cpu, ram, disco, etc, etc.

Entonces ansible le dira a VMware que “clone” desde el template a esta nueva máquina, por tanto ya tendremos el sistema listo,

Para esto el también mandara a instalar usando la API el vmware-tools, asi cuando termina el mismo reinicia la vm nueva dejandola lista con el estado definido en el playbook que en este caso es “encendido” (Poweredon).

Y lo mejor de todo es que de los 40/45 min que nos demorabamos simplemente con el comando ahora bajastes ese tiempo a (en mi caso)  5 min! y esto es usando discos normales de prueba con 7200RPM imagínense si usaramos SSD.

En el trabajo he llegado a ver hasta < 1min por cada vm, porque justamente hemos dado en este caso poco hardware y storage lento.

Se acuerdan de lo que era idempotente ? 

Pues ejecutando de nuevo el playbook, ansible nos responderá que no hará falta, porque ya esta hecha la VM.

Quedando en el vCenter ya la vm lista, (una aclaración en el playbook puse 2 Gb de ram
y luego ven la VM con 1 Gb, es que hice esto en varios dias y cambie esto mientras también hacia los screenshots)

Como haríamos mas de 1, por ejemplo 4+ ?

Pues de la siguiente manera, creamos un inventario para vmware y dentro creamos nuestro grupo para las vms de vmware

$ vim ~/deploys/inventory/vms-deploy

[vms]
ansi1vm guest_custom_ip='192.168.100.1'
ansi2vm guest_custom_ip='192.168.100.2'
ansi3vm guest_custom_ip='192.168.100.3'
ansi4vm guest_custom_ip='192.168.100.4'

al definir una variable “guest_custom_ip” para cada vm, ansible leerá este inventario cuando sera lanzado e iterará sobre estas líneas usando la variable que sustituiremos en el playbook donde dice:

networks:
  ip: el.ip.que.pusimos anteriormente

por:

networks:
  ip: '{{ guest_custom_ip }}'

y ademas donde dice:

vars:
vmname_var: 'ansi1vm'
-> cambiamos por la variable especial '{{ inventory_hostname }}'

Que simplemente leerá los nombres que estan definidos como: “ansi1vm, ansi2vm, ansi3vm, ansi4vm” en el inventario

Terminando con:

ansible-playbook provision-infra-test-centos.yml -i vms-deploy --vault-id @prompt

Hasta aqui este post, en los próximos comenzaré a traducir los tutoriales que están escritos aquí hacia ansible, para que vean como se va automatizando los procesos sin tener que perder todo un día actualizando las mismas cosas cada vez que sale algún update.

(Visited 1 times, 1 visits today)
Antonio Peña Díaz
Sobre Antonio Peña Díaz 3 Artículos
System Network/Administrator doing Cloud Services for SaaS

Sé el primero en comentar

Dejar una contestacion

Tu dirección de correo electrónico no será publicada.


*