
Guten Tag
Wir haben mehrere Cloud-Cluster, von denen jeder mit einer Vielzahl virtueller Maschinen ausgestattet ist. All dies wird bei Hetzner gehostet. In jedem Cluster haben wir eine Master-Maschine, von der ein Snapshot erstellt wird und der automatisch auf alle virtuellen Maschinen im Cluster verteilt wird.
Dieses Schema erlaubt uns nicht, die GitLab-Runner richtig zu nutzen, da beim Auftreten vieler identischer registrierter Runner zahlreiche Probleme auftreten, was uns zu finden einer Umgehungslösung und zum Schreiben dieses Artikels/Tutorials veranlasst hat.
Es ist wahrscheinlich nicht die beste Praxis, aber diese Lösung erschien uns als die bequemste und einfachste.
Für das Tutorial bitte nach dem Cut.
Benötigte Pakete auf der Master-Maschine:
- Python
- git
- Datei mit SSH-Schlüsseln
Das grundlegende Prinzip der Implementierung eines automatischen git pull auf allen virtuellen Maschinen besteht darin, dass eine Maschine erforderlich ist, auf der Ansible installiert wird. Von dieser Maschine aus wird Ansible die Befehle git pull und den Neustart des aktualisierten Dienstes senden. Zu diesem Zweck haben wir eine separate virtuelle Maschine außerhalb der Cluster erstellt und darauf installiert:
- Python
- ansible
- gitlab-runner
Von organisatorischer Seite ist es notwendig, den gitlab-runner zu registrieren, ssh-keygen auszuführen und den öffentlichen ssh-Schlüssel dieser Maschine in .ssh/authorized_keys auf der Master-Maschine abzulegen, sowie den Port 22 für Ansible auf der Master-Maschine zu öffnen.
Jetzt konfigurieren wir Ansible.
Da unser Ziel ist, alles zu automatisieren, was möglich ist. In der Datei /etc/ansible/ansible.cfg werden wir die Zeile host_key_checking = False, auskommentieren, damit Ansible keine Bestätigung neuer Maschinen anfragt.
Als Nächstes müssen wir eine Inventar-Datei für Ansible automatisch generieren, von wo Ansible die IP-Adressen der Maschinen abholt, auf denen git pull ausgeführt werden muss.
Wir generieren diese Datei über die API von Hetzner, Sie können die Liste der Hosts auch aus Ihrer AWS, Azure, DB entnehmen (Sie haben doch irgendwo eine API zur Ausgabe Ihrer laufenden Maschinen, nicht wahr?).
Für Ansible ist die Struktur der Inventar-Datei sehr wichtig, das Format sollte wie folgt aussehen:
[gruppe]
ip-Adresse
ip-Adresse
[gruppe2]
ip-Adresse
ip-AdresseUm eine solche Datei zu generieren, erstellen wir ein einfaches Skript (nennen wir es 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_ipJetzt ist es an der Zeit zu überprüfen, ob Ansible funktioniert und die IP-Adressen korrekt abruft:
/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'hostname' group
Im Output sollten die Hostnamen der Maschinen angezeigt werden, auf denen der Befehl ausgeführt wurde.
Ein paar Worte zur Syntax:
- /etc/ansible/./vm_list — генерируем список машин
- -i — absoluter Pfad zur Inventardatei
- -m — Ansible anweisen, das Shell-Modul zu verwenden
- -a — Argument. Hier kann jeder Befehl eingetragen werden
- group — der Name Ihres Clusters. Wenn alle Cluster betroffen sein sollen, ändern Sie group in all
Weiter geht's — wir versuchen, ein git pull auf unseren durchzuführen virtuellen Maschinen wurde vereinfacht.:
/etc/ansible/./vm_list && ansible -i /etc/ansible/cloud_ip -m shell -a 'cd /path/to/project && git pull' group Wenn wir im Output already up to date oder eine Ausgabe aus dem Repository sehen, funktioniert alles.
Jetzt das, wofür das Ganze gedacht war
Wir bringen unser Skript dazu, automatisch bei einem Commit in den Master-Branch in GitLab auszuführen
Zuerst verschönern wir unser Skript und packen es in eine ausführbare Datei (wir nennen sie exec_pull) —
#!/bin/bash
/etc/ansible/./get_vms && ansible -i /etc/ansible/cloud_ip -m shell -a "$@" Gehen Sie zu unserem GitLab und erstellen Sie eine Datei im Projekt .gitlab-ci.yml
Fügen Sie Folgendes ein:
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 Alles bereit. Jetzt —
- einen Commit machen
- wohl wissend, dass alles funktioniert
Beim Übertragen der .yml in andere Projekte reicht es aus, nur den Servicenamen für den Neustart und den Namen des Clusters, auf dem die ansible-Befehle ausgeführt werden, zu ändern.
Quelle: habr.com
