Buen día
Disponemos de varios clusters de nubes con una gran cantidad de máquinas virtuales en cada uno. Todo este asunto lo organizamos en Hetzner. En cada clúster tenemos una máquina maestra, de la que se toma una instantánea y se distribuye automáticamente a todas las máquinas virtuales dentro del clúster.
Este esquema no nos permite usar gitlab-runners normalmente, ya que surgen muchos problemas cuando aparecen muchos corredores registrados idénticos, lo que nos llevó a buscar una solución alternativa y escribir este artículo/manual.
Probablemente esta no sea la mejor práctica, pero esta solución parecía lo más conveniente y simple posible.
Para ver el tutorial, consulte cat.
Paquetes requeridos en la máquina maestra:
- pitón
- git
- archivo con claves ssh
El principio general para implementar la extracción automática en todas las máquinas virtuales es que necesita una máquina en la que se instalará Ansible. Desde esta máquina, ansible enviará comandos git pull y reiniciará el servicio que se ha actualizado. Para estos fines, creamos una máquina virtual separada fuera de los clústeres y la instalamos:
- pitón
- ansible
- corredor de gitlab
Por cuestiones organizativas: debe registrar gitlab-runner, crear ssh-keygen, cargar la clave ssh pública de esta máquina en .ssh/authorized_keys
en la máquina maestra, abra el puerto 22 para ansible en la máquina maestra.
Ahora configuremos ansible
Ya que nuestro objetivo es automatizar todo lo que sea posible. En archivo /etc/ansible/ansible.cfg
descomentaremos la línea host_key_checking = False
para que ansible no solicite confirmación de nuevas máquinas.
A continuación, debe generar automáticamente un archivo de inventario para ansible, desde donde tomará la IP de las máquinas en las que necesita realizar git pull.
Generamos este archivo usando la API de Hetzner, puede tomar la lista de hosts de su base de datos de AWS, Asure (tiene una API en algún lugar para mostrar sus máquinas en ejecución, ¿verdad?).
La estructura del archivo de inventario es muy importante para Ansible; debería verse así:
[группа]
ip-адрес
ip-адрес
[группа2]
ip-адрес
ip-адрес
Para generar dicho archivo, crearemos un script simple (llamémoslo 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_ip
Es hora de comprobar que Ansible funciona y es compatible con la recepción de direcciones IP:
/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'hostname' group
La salida debe contener los nombres de host de las máquinas en las que se ejecutó el comando.
Algunas palabras sobre la sintaxis:
- /etc/ansible/./vm_list - genera una lista de máquinas
- -i - ruta absoluta al archivo de inventario
- -m - le dice a ansible que use el módulo shell
- -a es el argumento. Cualquier comando se puede ingresar aquí
- grupo: el nombre de su clúster. Si necesita hacer esto en todos los clústeres, cambie el grupo a todos
Vayamos más allá: intentemos ejecutar git pull en nuestras 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 el resultado vemos que ya está actualizado o descargando del repositorio, entonces todo está funcionando.
Ahora esto es para lo que estaba destinado todo.
Enseñemos a nuestro script a ejecutarse automáticamente al comprometerse con la rama master en gitlab
Primero, hagamos nuestro script más hermoso y pongámoslo en un archivo ejecutable (llamémoslo exec_pull):
#!/bin/bash
/etc/ansible/./get_vms && ansible -i /etc/ansible/cloud_ip -m shell -a "$@"
Vayamos a nuestro gitlab y creemos un archivo en el proyecto. .gitlab-ci.yml
Ponemos dentro lo siguiente:
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 -
- hacer un compromiso
- Me alegro que todo esté funcionando
Al transferir .yml a otros proyectos, solo necesita cambiar el nombre del servicio a reiniciar y el nombre del clúster en el que se ejecutarán los comandos ansible.
Fuente: habr.com