
Buenos días
Contamos con varios clústeres en la nube que albergan numerosas máquinas virtuales en cada uno. Todo esto está alojado en Hetzner. En cada clúster, tenemos una máquina maestra, de la cual se realiza una instantánea y se distribuye automáticamente a todas las virtuales dentro del clúster.
Este esquema no nos permite usar correctamente los gitlab-runners, ya que surgen muchos problemas con la aparición de numerosos runners registrados idénticos, lo que llevó a buscar una solución alternativa y a escribir este artículo/manual.
Probablemente, esto no es lo mejor, pero esta solución nos pareció la más conveniente y sencilla.
Por favor, vean el tutorial a continuación.
Los paquetes necesarios en la máquina maestra:
- python
- git
- archivo con las claves ssh
El principio general para implementar el git pull automático en todas las virtuales es que se necesita una máquina donde se instalará Ansible. Desde esta máquina, Ansible enviará comandos git pull y reiniciará el servicio que fue actualizado. Creamos para estos fines una máquina virtual separada fuera de los clústeres y le instalamos:
- python
- ansible
- gitlab-runner
En cuestiones organizativas, es necesario registrar el gitlab-runner, hacer un ssh-keygen, y colocar la clave ssh pública de esta máquina en .ssh/authorized_keys en la máquina maestra, abrir el puerto 22 en la máquina maestra para Ansible.
Ahora configuremos Ansible
Ya que nuestro objetivo es automatizar todo lo que sea posible. En el archivo /etc/ansible/ansible.cfg descomentamos la línea host_key_checking = False, para que Ansible no pida confirmación para nuevas máquinas.
A continuación, es necesario generar automáticamente un archivo de inventario para Ansible, de donde tomará las IP de las máquinas en las que se debe hacer git pull.
Generamos este archivo utilizando la API de Hetzner, aunque usted puede obtener la lista de hosts de su AWS, Azure, base de datos (¿tiene alguna API para mostrar sus máquinas en funcionamiento, verdad?).
Para Ansible, la estructura del archivo de inventario es muy importante, debe tener el siguiente formato:
[grupo]
ip-dirección
ip-dirección
[grupo2]
ip-dirección
ip-direcciónPara generar un archivo así, hagamos un sencillo script (lo llamaremos vm_list):
#!/bin/bash
echo [group] > /etc/ansible/cloud_ip &&
"ваш CLI запрос на получение IP запущенных машин в кластере" >> /etc/ansible/cloud_ip
echo " " >> /etc/ansible/cloud_ip
echo [group2] > /etc/ansible/cloud_ip &&
"ваш CLI запрос на получение IP запущенных машин в другом кластере" >> /etc/ansible/cloud_ipEs el momento de verificar que Ansible funciona y se comunica adecuadamente con la obtención de las direcciones IP:
/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'hostname' group
En la salida debemos obtener los nombres de host de las máquinas en las que se ejecutó el comando.
Unas palabras sobre la sintaxis:
- /etc/ansible/./vm_list — генерируем список машин
- -i — ruta absoluta al archivo de inventario
- -m — indicamos a Ansible que utilice el módulo shell
- -a — argumento. Aquí se puede escribir cualquier comando
- grupo — el nombre de tu clúster. Si es necesario hacer en todos los clústeres, cambiamos grupo a all
Seguimos adelante — intentemos hacer git pull en nuestros máquinas virtuales:
/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'cd /path/to/project && git pull' group Si en la salida vemos already up to date o descarga del repositorio, significa que todo funciona.
Ahora lo que se pensó para esto
Enseñaremos a nuestro script a ejecutarse automáticamente al hacer commit en la rama maestra en gitlab
Primero haremos que nuestro script sea más bonito y lo pondremos en un archivo ejecutable (lo llamaremos exec_pull) —
#!/bin/bash
/etc/ansible/./get_vms && ansible -i /etc/ansible/cloud_ip -m shell -a "$@" Vamos a nuestro gitlab y en el proyecto creamos un archivo .gitlab-ci.yml
Colocamos lo siguiente dentro:
variables:
GIT_STRATEGY: none
VM_GROUP: group
stages:
- pull
- restart
run_exec_pull:
stage: pull
script:
- /etc/ansible/exec_pull 'cd /path/to/project/'$CI_PROJECT_NAME' && git pull' $VM_GROUP
only:
- master
run_service_restart:
stage: restart
script:
- /etc/ansible/exec_pull 'your_app_stop && your_app_start' $VM_GROUP
only:
- master Todo está listo. Ahora —
- hacemos commit
- esperamos que todo funcione
Al trasladar .yml a otros proyectos, solo es necesario cambiar el nombre del servicio para reiniciar y el nombre del clúster en el que se ejecutarán los comandos ansible.
Fuente: habr.com
