Allgemein

Erfahrungen und Best-Practices mit Ansible

Bereits seit März 2014 arbeite ich mit Ansible – beginnend mit Version 1.1.

Während meiner Arbeit habe ich viele Playbooks und Rollen geschrieben, um Betriebssysteme, Anwendungen und Continuous Delivery-Pipelines zu konfigurieren. Mit Ansible verwalte ich AWS-Instanzen, VMWare-Cluster und Xen-Hosts.

Ich verwalte auch einige Open Source Ansible Rollen auf GitHub und ich habe Dockerfiles für Betriebssystem-Images geschrieben, die Ansible enthalten (hauptsätlich zum Testen der Rollen).

Im Laufe der Zeit sammelten mein Team und ich einige Best Practices, die wir beim Schreiben und Ausführen von Ansible-Code in der Produktion beachten. Der folgende Beitrag nennt und erklärt die (aus meiner Sicht) Best Practices.

Natürlich schreibe ich nicht als erster über Ansible Best-Practices. Es gibt andere Quellen, die sehr informativ waren und mir enorm geholfen haben:

Über das Schreiben von Ansible Playbooks

Benennung der Aufgaben und Plays

Beim Schreiben von Tasks und Plays in Ansible ist die Benennung optional. Allerdings sollten Sie Ihren Aufgaben und Plays immer sinnvolle Namen geben. Wenn Sie ein Playbook ohne benannte Tasks ausführen, sehen Sie die folgende Ausgabe:

Beim Versuch, fehlgeschlagene Tasks zu debuggen, ist es wirklich hilfreich zu wissen, welche Aufgabe fehgeschlagen ist und was diese hätte machen sollen. Die Benennung der obigen Aufgabe kann daher folgende Ausgabe ergeben:

Das ist hilfreicher, oder?

Variablen im Task-Namen

Versuchen Sie, beim Schreiben von Task-Namen aussagekräftig zu sein. Fügen Sie so viele Informationen wie nötig hinzu. Eine gute Möglichkeit hierfür ist die Verwendung von Variablen in den Task-Namen. Wenn Sie beispielsweise ermitteln möchten, für welchen Host eine Aufgabe aktuell ausgeführt wird, können Sie eine Variable in ihren Task-Namen aufnehmen.

Angenommen, Sie haben folgenden Task, der die Variable inventory_hostname im Namen enthält:

Wird diese auf einem Host ausgeführt, wird folgende Ausgabe erzeugt:

Dies ist ein guter Weg, um zu bestimmen, was das Playbook gerade macht.

Überflüssige Informationen auslassen

Eine Sache, die Sie nicht machen müssen, ist den Rollennamen im Task-Namen einzuschließen. Dieser ist ohnehin schon enthalten:

Playbook:

Task-Datei der Rolle:

und die Ausgabe des Plays:

Sehen Sie, wie der Rollenname in die Aufgabenbeschreibung aufgenommen wird, ohne dass er explizit definiert ist?

Verwendung von Modulen anstatt Ausführung von Commands

Diese sollte zwar offensichtlich sein, aber für Personen, die aus einem klassischen Adminhintergrund kommen und neu bei Ansible sind, ist es oft nicht der Fall: Ansible ist batteries-included und verfügt über mehr als 1000 Module zur Verwaltung von Systemen. Meistens ist es nicht notwendig (noch nützlich!) statt der Modulverwendung auf Shell-Befehle zurückzugreifen.

Hier ist ein einfaches Beispiel. Anstatt Folgendes zu tun:

sollten Sie dies durchführen:

Ansible ist behiflich, wenn es darum geht, zu erkennen, wann Sie Module anstelle von Commands verwenden sollten. Es erkennt diese Verwendungen und gibt eine Warnung aus. Wenn die obige Aufgabe mit command ausgeführt wird, zeigt Ansible:

Verwenden des Copy- oder Template-Moduls anstelle von Lineinfile

Es ist oft notwendig, einzelne Dateienzeilen zu ändern. Wenn sie dies tun müssen, verwenden viele Leute lineinfile– oder blockinfile-Module, um die Datei zu ändern.

Im Laufe der Jahre habe ich jedoch gelernt, dass man diese Module in der Regel nicht verwenden sollte, wenn Sie Dateien ändern möchten. Sie sollten lieber das Template– oder Copy-Modul verwenden, um nicht nur einzelne Zeilen sondern die gesamte Datei zu verwalten.

Dafür gibt es zweierlei Gründe. Einerseits müssen Sie bei der Verwendung von lineinfile oft Regex verwenden. Daraus resultieren zwei Probleme. Tatsächlich ist die Verwendung von Regex oft in Ordnung, wenn die Regex einfach ist (oder Sie und die Personen, die Ihre Playbooks benutzen, mit Regex vertraut sind)! Der zweite Grund ist, dass Sie wissen und sich erinnern müssen, dass diese bestimmte Zeile in dieser einen Konfigurationsdatei von Ansible verwaltet wird. Wenn Sie die gesamte Datei mit einem Template verwalten, können Sie dieansible_managed-Variable verwenden, um deutlich zu machen, dass sich die Datei unter Ansible-Kontrolle befindet. Hier ist ein Beispiel. An Stelle von:

verwenden Sie:

oder:

…mit der Vorlagedatei, die wie folgt aussieht:

Bonus: Sie können eine Variable für den selinux-state verwenden und sie einfach auf Servern, auf denen selinux nicht im Enforcing-Status sein sollte, ändern.

Explizit beim Schreiben von Aufgaben sein

Wenn ich meine, dass Sie beim Schreiben von Ansible-Aufgaben eindeutig sein sollten, ist es am besten, dies anhand eines Beispiels zu zeigen. Anstatt das zu schreiben:

ist es besser Folgendes zu schreiben:

Auch hierfür gibt es zwei Gründe. Der erste ist technischer Natur: Wenn Sie den Besitzer und die Gruppe der Datei nicht explizit deklarieren, ist der Eigentümer der Benutzer, der Ansible ausgeführt hat. Das ist etwas, was nicht immer wünschenswert ist und leicht vermieden werden kann, wenn man explizit ist.

Der zweite Grund ist eher ein organisatorischer oder “menschlicher Grund”. Wenn Personen Ihr Playbook oder Ihre Rolle verwenden, kennen sie möglicherweise nicht immer die Standardeinstellungen der Module, die Sie verwenden oder was Sie mit den Tasks erreichen möchten. Wenn Sie in Ihren Tasks explizit sind, gibt es weniger Raum für Vermutungen und Interpretationen.

Dokumentation der Tasks

Bei der Benennung Ihrer Tasks ist es zwar wichtig zu wissen, was sie machen, jedoch ist es oft wichtiger zu dokumentieren, warum der Task das macht, was sie eben macht. Wenn es nicht direkt offensichtlich ist, was der Task macht, schreiben Sie einfach einige Kommentare über ihn. Somit können Sie detaillierter erklären was und warum etwas passiert:

Wenn Sie das command , shell or raw -Modul anstatt der “korrekten” Module nutzen müssen, dokumentieren Sie, warum Sie diese nicht nutzen können:

Danke an mikeoquinn für den Vorschlag!

Über das Variablen-Schreiben

Präfixe in Variablen nutzen

Es gibt einige Dinge, an die Sie sich beim Schreiben von Variablen für Ihre Rollen beachten sollten. Das Erste ist, dass Sie ihnen den Namen der Rolle voranstellen sollten. Dies macht es einfacher zu wissen, wo die Variable verwendet wird.

Hier ist ein Beispiel. Stellen Sie sich vor, Sie schreiben eine Rolle für die Installation und Konfiguration des Apache-Webservers (Sie müssen das wahrscheinlich nicht tun). Die Rolle wird apache genannt. Jetzt möchten Sie eine Variable erstellen, die den Standard-Listen-Port konfiguriert.

Sie werden es wahrscheinlich so machen:

Allerdings sollten Sie es so machen:

Abgesehen von dem bereits erwähnten Grund gibt es hier keine Zweideutigkeit. Sie wissen definitiv, dass diese Variable zur Apache-Rolle gehört. Es könnte eine andere Rolle für eine andere Software geben, die auch einen Listen-Port definiert. Bei Variablen mit Präfixen ist dies kein Problem, da Variablen jetzt ihren eigenen Namensraum haben.

Übrigens, Puppet und Chef sind hier im Vorteil und haben echte Namensräume für ihre Rollen. Ansible ist nicht so konzipiert.

Über das Schreiben und Verwenden von Variablen

Wenn Sie eine Variable in Ansible verwenden, muss diese zitiert sein.

Das folgende Beispiel wird nicht funktionieren:

Dies funktioniert jedoch:

Sie können auch einzelne Hochkommata verwenden und die Leerzeichen zwischen den geschweiften Klammern und dem Variablennamen weglassen. Ich bin jedoch der Ansicht, dass die oben stehende Ausführung der am besten lesbare Stil ist. Das Wichtigste ist, bei einem Stil zu bleiben.

Zeigen Sie keine sensiblen Daten in der Ansible-Ausgabe

Wenn Sie das Template-modul verwenden und sich Passwörter oder andere sensible Daten in der Datei befinden, möchten Sie nicht, dass es im Ansible-Output angezeigt wird. Dafür ist die no_log-Option da. Wenn diese zu einem Task hinzugefügt wird, wird die entsprechende Ausgabe des Tasks nicht protokolliert.

Hier ist ein Playbook-Beispiel:

Ohne no_log: true sieht die Ausgabe so aus:

Mit no_log: true wird es so aussehen:

Um vertrauliche Daten in Ihren Playbooks und Rollen geheim zu halten, verwenden Sie ansible-vault. Es gibt eine ausführliche Dokumentationvon Ansible mit guten Beispielen. Daher werde ich dieses Thema hier nicht weiter behandeln.

Über das Schreiben und (Wieder-) Verwenden von Rollen

Vor dem Schreiben von Playbooks und Rollen ist es immer eine gute Idee zu überprüfen, ob jemand anderes die Arbeit für Sie bereits erledigt hat. Für die gängigsten Anwendungen gibt es bereits Rollen in Ansible Galaxy. Wenn Sie dort nach Rollen suchen, sortieren Sie nach Stargazern (und vielleicht nach Downloads), um die beliebtesten (und hoffentlich gut gepflegten) Rollen zu finden. Es gibt einige Leute und Organisationen, die viele qualitativ hochwertige Rollen anbieten. geerlingguy, jdauphant, ANXS und (Eigenwerbung!) dev-sec bieten einige großartige Rollen an.

Wenn Sie eine Rolle erstellen, benutzen Sie ansible-galaxy init, um das initiale Verzeichnislayout zu erstellen. Behalten Sie dieses auch bei!

Wenn Sie alle hier aufgeführten Best Practices befolgen, sollten Ihre Rollen problemlos auf Ansible Galaxy und Github veröffentlicht werden können.

Dokumentieren von Rollen

Bei der Dokumentation von Rollen ist es am besten, das von ansible-galaxy init erstellte Template zu verwenden. Dort müssen Sie die Rolle und ihre Funktion beschreiben, die verwendeten Variablen auflisten und erklären sowie die benötigten Abhängigkeiten und Beispiele nennen. Ich versuche immer, die Variablen in Form einer Tabelle mit mehr Inhalt zu versehen, indem ich den Variablennamen, den Standardwert und eine Erklärung der Variable gebe:

Andere Best-Practice-Überlegungen

Die Ansible Verzeichnisstruktur

Wenn Sie Ihr Ansible-Verzeichnis strukturieren, können Sie im Grunde das machen, was Sie wollen. Ansible bietet jedoch einige vernünftige Beispiele in seiner Dokumentation. Dieses Verzeichnis kann gleichzeitig auch als Git-Repository verwendet werden, welches wiederum von Jenkins oder AWX verwendet wird.

Für jedes Projekt versuchen wir dieselbe Struktur zu verwenden, die in etwa so aussieht:

Die ansible.cfg Datei

Die ansible.cfg hat hauptsächlich Standardwerte. Diejenigen, die geändert werden müssen, um zur obige Verzeichnisstruktur zu gehören, sind die folgenden:

Es gibt noch ein paar mehr Themen, über die ich schreiben möchte. Ich werde diesen Artikel hier aktualisieren, sobald ich meine Gedanken niedergeschrieben habe.

Aktuell sind das: mono-repo vs. one repo bei Rollen, Encryption, Rollen testen, jede Variable variablisieren und Auditierung.

 

3 comments

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.