Ansible + авто git pull в кластері віртуальних машин у хмарі

Ansible + авто git pull в кластері віртуальних машин у хмарі

Доброго дня

У нас є кілька хмарних кластерів з великою кількістю віртуальних машин у кожному. Вся ця справа у нас хоститься у Hetzner'e. У кожному кластері у нас є по одній майстер-машині, з неї робиться снепшот і автоматично розноситься по всіх віртуалках усередині кластера.

Ця схема не дозволяє нам нормально використовувати gitlab-runner'и, тому що виникає дуже багато проблем при появі безлічі однакових зареєстрованих раннерів, що спонукало до знаходження обхідного шляху і до написання цієї статті/мануалу.

Ймовірно, це не best practice, але це рішення здалося максимально зручним та простим.

За туторіалом прошу під кат.

Необхідні пакети на майстер-машині:

  • пітон
  • мерзотник
  • файл із ssh ключами

Загальний принцип реалізації автоматичного gut pull'a на всіх віртуалках полягає в тому, що потрібна машина, на якій буде встановлено Ansible. З цієї машини ansible буде відправляти команди git pull і ресторту сервісу, який заапдейтівся. Ми створили для цих цілей готельну віртуальну машину поза кластерами, поставили на неї:

  • пітон
  • ansible
  • gitlab-runner

З організаційних питань - необхідно зареєструвати gitlab-runner, зробити ssh-keygen, закинути публічний ssh ​​ключ цієї машини .ssh/authorized_keys на майстер-машині, відкрити на майстер-машині 22 порт для ansible.

Тепер налаштуємо ansible

Бо наша мета – автоматизувати все, що тільки можна. У файлі /etc/ansible/ansible.cfg ми розкоментуємо рядок host_key_checking = False, щоб ansible не просив підтвердження нових машин.

Далі необхідно автоматично генерувати інвентаризаційний файл для ansible, звідки він буде забирати ip машин, на яких потрібно робити git pull.

Ми генеруємо цей файл за допомогою API Hetzner'a, ви можете брати список хостів з вашої AWS, Asure, БД (у вас десь є API для виведення ваших запущених машин, так?).

Для Ansible дуже важливою є структура інвентаризаційного файлу, його вид має бути наступним:

[группа]
ip-адрес
ip-адрес

[группа2]
ip-адрес
ip-адрес

Для створення такого файлу зробимо простенький скрипт (назвемо його 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

Саме час перевірити, що ansible працює і дружить з одержувачем ip адрес:

/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'hostname' group

В аутпуті мають отримати хостнейми машин, на яких виконалася команда.
Пара слів про синтаксис:

  • /etc/ansible/./vm_list - генеруємо список машин
  • -i - абсолютний шлях до інвентаризаційного файлу
  • -m - говоримо ансиблу використовувати модуль shell
  • -a – аргумент. Сюди можна вписати будь-яку команду
  • group – назва вашого кластера. Якщо потрібно зробити на всіх кластерах, міняємо group на all

Ідемо далі - спробуємо зробити git pull на наших віртуальних машинах:

/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'cd /path/to/project && git pull' group 

Якщо в аутпуті бачимо already up to date або вивантаження з репозиторію, то все працює.

Тепер те, заради чого це все замислювалося

Навчимо наш скрипт виконуватись автоматично при коміті в майстер-гілці в gitlab'e

Спочатку зробимо наш скрипт красивішим і засунемо його у виконуваний файл (назвемо його exec_pull).

#!/bin/bash

/etc/ansible/./get_vms && ansible -i /etc/ansible/cloud_ip -m shell -a "$@"

Ідемо до нашого gitlab і в проекті створюємо файл .gitlab-ci.yml
Всередину поміщаємо наступне:

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 

Все готово. Тепер -

  • робимо коміт
  • Радіюсь тому, що все працює

При перенесенні .yml в інші проекти достатньо лише змінити ім'я сервісу для рестарту та ім'я кластера, на якому виконуватимуться команди ansible.

Джерело: habr.com

Додати коментар або відгук