Ansible beschleunigen

Ansible beschleunigen
Es ist kein Geheimnis, dass Ansible mit den "Standard-Einstellungen" nicht immer besonders schnell arbeitet. In diesem Artikel werde ich auf einige Gründe dafür hinweisen und ein nützliches Minimum an Einstellungen vorschlagen, die möglicherweise die Geschwindigkeit Ihres Projekts erheblich erhöhen können.

Hier und im Folgenden besprechen wir Ansible 2.9.x, das in einer frisch erstellten virtualenv auf Ihre bevorzugte Weise installiert wurde.

Nach der Installation erstellen wir neben Ihrem Playbook die Datei "ansible.cfg" – diese Platzierung ermöglicht es, die Einstellungen zusammen mit dem Projekt zu verschieben, und sie werden zudem relativ automatisiert geladen.

Pipelining

Darüber, dass Pipelining verwendet werden sollte, also nicht das Kopieren von Modulen ins Dateisystem des Zielsystems, sondern die Übertragung eines in Base64 kodierten Zip-Archivs direkt an stdin des Python-Interpreters, haben einige vielleicht schon gehört, andere nicht, aber die Tatsache bleibt bestehen: diese Einstellung bleibt weiterhin unterschätzt. Leider konfigurierte eine der gängigen Linux-Distributionen zuvor sudo nicht optimal – sodass dieser Befehl ein tty (Terminal) benötigte. Daher wurde diese sehr nützliche Einstellung in Ansible standardmäßig deaktiviert gelassen.

pipelining = True

Fakten sammeln

Wussten Sie, dass Ansible mit den Standardeinstellungen für jedes Play das Sammeln von Fakten über alle beteiligten Hosts initiiert? Wenn Sie es nicht wussten, wissen Sie es jetzt. Um dies zu vermeiden, müssen Sie entweder den expliziten Modus für das Sammeln von Fakten (explicit) oder den intelligenten Modus aktivieren. In letzterem werden Fakten nur von den Hosts gesammelt, die in vorherigen Plays nicht aufgetaucht sind.
UPD. Beim Kopieren müssen Sie eine dieser Einstellungen auswählen.

gathering = smart|explicit

Wiederverwendung von SSH-Verbindungen

Wenn Sie Ansible jemals im Debug-Modus (Option "v", die ein bis neun Mal wiederholt wird) ausgeführt haben, haben Sie vielleicht bemerkt, dass die SSH-Verbindungen ständig aufgebaut und getrennt wurden. Hier gibt es ebenfalls einige Feinheiten.

Den Schritt des erneuten Aufbaus der SSH-Verbindung kann man auf zwei Ebenen gleichzeitig vermeiden: sowohl im SSH-Client als auch beim Übertragen von Dateien an den verwalteten Host from dem Steuerungsrechner.
Um eine offene SSH-Verbindung wiederzuverwenden, reicht es aus, die benötigten Schlüssel einfach an den SSH-Client zu übergeben. Dann beginnt der Client Folgendes zu tun: Bei der ersten Einrichtung der SSH-Verbindung wird ein sogenannter Control-Socket zusätzlich erstellt, bei den folgenden Verbindungen wird die Existenz dieses Sockets überprüft, und im Erfolgsfall wird die bestehende SSH-Verbindung wiederverwendet. Damit das alles sinnvoll ist, legen wir eine Zeit fest, wie lange die Verbindung bei Inaktivität bestehen bleibt. Näheres kann in der SSH-Dokumentationnachgelesen werden, und im Kontext von Ansible verwenden wir einfach die "Weiterleitung" der benötigten Optionen an den SSH-Client.

ssh_args = "-o ControlMaster=auto -o ControlPersist=15m"

Um eine bereits offene SSH-Verbindung beim Übertragen von Dateien an den verwalteten Host wiederzuverwenden, reicht es aus, eine weitere unbekannte Einstellung, ssh_transfer_method, anzugeben. Die Dokumentation dazu ist äußerst mangelhaft und führt in die Irre, denn diese Option funktioniert durchaus! Das Lesen dem Quellcode erlaubt zu verstehen, was genau passieren wird: Auf dem verwalteten Host wird der Befehl dd ausgeführt, der direkt mit der benötigten Datei arbeitet.

transfer_method = piped

Übrigens gibt es diese Einstellung auch im Develop-Zweig, und sie ist nicht verschwunden..

Fürchte das Messer nicht, fürchte die Gabel.

Eine weitere nützliche Einstellung ist forks. Diese legt die Anzahl der Arbeitsprozesse fest, die gleichzeitig mit den Hosts verbunden werden und Aufgaben ausführen. Aufgrund der Eigenschaften von Python als Programmiersprache werden genau Prozesse und nicht Threads verwendet, da Ansible weiterhin Python 2.7 unterstützt – keine asyncio, hier gibt es nichts, was asynchron gemacht werden müsste! Standardmäßig startet Ansible fünf Worker, aber wenn man richtig danach fragt, kann er auch mehr starten:

forks = 20

Ich warne vorab, dass es hier einige Schwierigkeiten geben kann, die mit dem vorhandenen Speicher auf dem verwaltenden Gerät zusammenhängen. Anders gesagt, es mag zwar möglich sein, forks=100500 zu setzen, aber wer hat gesagt, dass das funktioniert?

Kommen wir alles zusammen.

Für ansible.cfg (INI-Format) könnten die erforderlichen Einstellungen so aussehen:

[defaults]
gathering = smart|explicit
forks = 20
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=15m
transfer_method = piped

Und wenn du alles in einem ordentlichen YAML-Inventar eines gesunden Menschen verstecken möchtest, könnte es etwa so aussehen:

---
all:
  vars:
    ansible_ssh_pipelining: true
    ansible_ssh_transfer_method: piped
    ansible_ssh_args: -o ControlMaster=auto -o ControlPersist=15m

Leider wird dies mit den Einstellungen „gathering = smart/explicit“ und „forks = 20“ nicht funktionieren: Ihre YaML-Äquivalente existieren nicht. Entweder definieren wir sie in ansible.cfg oder übergeben sie über die Umgebungsvariablen ANSIBLE_GATHERING und ANSIBLE_FORKS.

Über Mitogen
— Wo steht hier etwas über Mitogen? — könntest du, verehrter Leser, fragen. In diesem Artikel — nirgendwo. Aber wenn du wirklich bereit bist, seinen Code zu lesen und zu verstehen, warum dein Playbook mit Mitogen fehlschlägt, während es mit Vanilla Ansible einwandfrei funktioniert, oder warum dasselbe Playbook bisher immer korrekt lief und nach dem Update merkwürdig wurde — nun, Mitogen könnte potenziell dein Werkzeug sein. Wende es an, beschäftige dich damit, schreibe Artikel — ich lese sie mit Interesse.

Warum ich persönlich Mitogen nicht verwende? Weil er nur funktioniert, solange die Aufgaben wirklich einfach sind und alles gut läuft. Sobald man etwas nach links oder rechts abweicht — vorbei: Eine Handvoll verwirrender Ausnahmen kommt zurück, und um das Bild abzurunden, fehlt nur der gängige Satz „Danke an alle, ihr seid entlassen.“ Zusammenfassend möchte ich einfach keine Zeit damit verbringen, die Ursachen des nächsten „unterirdischen Klopfens“ herauszufinden.

Einige dieser Einstellungen wurden während der Lektüre dem Quellcode des Verbindungs-Plugins mit dem sprechenden Namen „ssh.py“ entdeckt. Ich teile die Ergebnisse der Lektüre in der Hoffnung, dass es noch jemanden inspiriert, in den Quellcode zu schauen, ihn zu lesen, die Implementierung zu überprüfen und mit der Dokumentation zu vergleichen — denn das wird dir früher oder später positive Ergebnisse bringen. Viel Glück!

Nur registrierte Benutzer können an der Umfrage teilnehmen. Bitte einloggen.

Welche der genannten Ansible-Einstellungen zur Beschleunigung deiner Projekte verwendest du?

  • 69,6%pipelining = true32

  • 34,8%gathering = smart/explicit16

  • 52,2%ssh_args = "-o ControlMaster=auto -o ControlPersist=…"24

  • 17,4%transfer_method = piped8

  • 63,0%forks = XXX29

  • 6,5%Nichts davon, nur Mitogen3

  • 8,7%Mitogen + ich werde hervorheben, welche dieser Einstellungen genau4

46 Benutzer haben abgestimmt. 21 Benutzer haben sich enthalten.

Möchtest du noch mehr über Ansible erfahren?

  • 78,3%Ja, natürlich54

  • 21,7%Ja, ich möchte nur mehr Hardcore-Dinge!15

  • 0,0%Nein, und das brauche ich nicht0

  • 0,0%Nein, zu kompliziert!!!0

69 Benutzer haben abgestimmt. 7 Benutzer haben sich enthalten.

Quelle: habr.com

60GB SSD 8Gb DDR4