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

в 12:32, , рубрики: Ansible, devops, Git, linux, виртуализация, системное администрирование

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

Доброго дня

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

Эта схема не позволяет нам нормально использовать gitlab-runner'ы, так как возникает очень много проблем при появлении множества одинаковых зарегистрированных раннеров, что и побудило к нахождению обходного пути и к написанию этой статьи/мануала.

Вероятно, это не best practice, но это решение показалось максимально удобным и простым.

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

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

  • python
  • git
  • файл с ssh ключами

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

  • python
  • 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.

Автор: Nepomniashchev

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js