
Dzień dobry
Mamy kilka chmurowych klastrów z dużą liczbą maszyn wirtualnych w każdym z nich. Całość hostujemy w Hetznerze. W każdym klastrze mamy jedną maszynę główną, z której wykonywany jest zrzut stanu i automatycznie rozprowadzany do wszystkich wirtualek w klastrze.
Ten schemat nie pozwala nam na normalne korzystanie z gitlab-runnerów, ponieważ pojawia się wiele problemów z wieloma zarejestrowanymi runnerami, co skłoniło nas do znalezienia sposobu obejścia i napisania tego artykułu/manuala.
Prawdopodobnie to nie jest najlepsza praktyka, ale to rozwiązanie wydaje się maksymalnie wygodne i proste.
Szczegółowe informacje znajdziesz w rozwinięciu.
Potrzebne pakiety na maszynie głównej:
- python
- sshpass
- plik z kluczami ssh
Ogólny zasad realizacji automatycznego git pull’a na wszystkich wirtualkach polega na tym, że potrzebna jest maszyna, na której będzie zainstalowany Ansible. Z tej maszyny Ansible będzie wysyłał polecenia git pull i restartował usługę, która została zaktualizowana. Utworzyliśmy w tym celu osobną maszynę wirtualną poza klastrami, zainstalowaliśmy na niej:
- python
- ansible
- gitlab-runner
Z kwestii organizacyjnych — należy zarejestrować gitlab-runner, zrobić ssh-keygen, wrzucić publiczny klucz ssh tej maszyny do .ssh/authorized_keys na maszynie głównej, otworzyć port 22 na maszynie głównej dla Ansible.
Teraz skonfigurujemy Ansible
Ponieważ naszym celem jest zautomatyzowanie wszystkiego, co tylko możliwe. W pliku /etc/ansible/ansible.cfg odkomentujemy linię host_key_checking = False, aby Ansible nie pytał o potwierdzenie nowych maszyn.
Następnie trzeba automatycznie wygenerować plik inwentaryzacyjny dla Ansible, z którego będziemy pobierać adresy IP maszyn, na których trzeba wykonać git pull.
Generujemy ten plik za pomocą API Hetzner, możecie jednak pobierać listę hostów z AWS, Azure, bazy danych (musi gdzieś być API do wyprowadzania uruchomionych maszyn, prawda?).
Dla Ansible bardzo ważna jest struktura pliku inwentaryzacyjnego, jego forma powinna być następująca:
[grupa]
ip-adres
ip-adres
[grupa2]
ip-adres
ip-adresAby wygenerować taki plik, stworzymy prosty skrypt (nazwijmy go 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_ipCzas sprawdzić, czy Ansible działa i poprawnie komunikuje się z pobieraniem adresów IP:
/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'hostname' group
W wyjściu powinniśmy otrzymać nazwy hostów maszyn, na których wykonano polecenie.
Kilka słów o składni:
- /etc/ansible/./vm_list — генерируем список машин
- -i — absolutna ścieżka do pliku inwentaryzacyjnego
- -m — mówimy Ansible, aby użyło modułu shell
- -a — argument. Here you can enter any command
- group — the name of your cluster. If you need to apply it to all clusters, replace group with all
Let's move on — let's try to do git pull on our maszynach wirtualnych:
/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'cd /path/to/project && git pull' group If we see already up to date or a dump from the repository in the output, it means everything is working.
Now to what this was all about
We'll teach our script to run automatically on commit to the master branch in GitLab
First, let's make our script more elegant and put it into an executable file (let's call it exec_pull) —
#!/bin/bash
/etc/ansible/./get_vms && ansible -i /etc/ansible/cloud_ip -m shell -a "$@" Let's go to our GitLab and create a file in the project .gitlab-ci.yml
We place the following inside:
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 Everything is ready. Now —
- let's make a commit
- making sure that everything works
When transferring .yml to other projects, it's enough to just change the service name for restart and the name of the cluster where the ansible commands will be executed.
Źródło: habr.com
