Ansible Best Practices
Ansible ist ein Tool, das die Konfigurationsverwaltung durch YAML-Code automatisiert. Es erfreut sich großer Beliebtheit, was zum Teil daran liegt, dass es ohne Client und Daemon funktioniert: Man braucht nur Python und eine SSH-Verbindung!
Da die YAML-Syntax ziemlich benutzerfreundlich ist, ist der Einstieg in Ansible relativ einfach. Ohne eine gründliche Einführung in die Formate und Strukturen von Ansible ist das erste Ergebnis jedoch meist „schlechter“ Code: Er mag zwar funktionieren, ist aber anfällig für zukünftige Fehler, ineffizient oder einfach unlesbar.
In diesem Artikel wollen wir einige der Ansible Best Practices vorstellen, die wir für besonders wichtig halten. Dies ist ein Vorgeschmack auf das, was wir während unserer Ansible-Schulungen bei ATIX besprechen. Wenn Sie daran interessiert sind, Ansible von Grund auf mit einem praktischen Ansatz zu lernen, kontaktieren Sie uns für weitere Informationen zu unseren Trainings.
YAML
-
Nutzen Sie
true
anstelle vonyes
undfalse
anstattno
-
Setzen Sie pro eingerückter Ebene zwei Leerzeichen (nicht vier und NIEMALS Tabs!)
-
Vermeiden Sie Listen und Dictionaries innerhalb einer Zeile
-
Brechen Sie Zeilen um, wenn sie länger als 80 Zeichen sind:
1 a_string: > # transforms linebreaks to spaces
2 R0lGO2313DdhDQAIAIAAAAAAANn
3 Z2SwAAAAAsdasfDQAIAAACF4SDGQ
4 ar3xxbJ9p0qa7R3fasdAS0YxwzaFME
5 1IAADs=
6 7 # this string doesn't have spaces
8 a_folded_string_without: "R0lGO2313DdhDQAIAIAAAAAAANn
9 Z2SwAAAAAsdasfDQAIAAACF4SDGQ
10 ar3xxbJ9p0qa7R3fasdAS0YxwzaFME
11 1IAADs="
Playbook
-
Tasknamen:
-
Geben Sie jeder Task einen Namen
-
Schreiben Sie den ersten Buchstaben dieses Namens immer groß
-
Sorgen Sie dafür, dass der Name die Task angemessen beschreibt; entscheiden Sie sich z.B. für „Install Apache“ anstelle von „Install stuff“
-
-
Verwenden Sie in Playbooks den Stil eines Dictionary, z.B.:
1 # avoid this
2 - name: Install Apache packages
3 yum: name="{{ packages }}" state=present
4 vars:
5 packages:
6 - httpd
7 - httpd-devel
8 9 # use this instead
10 - name: Install Apache packages
11 yum:
12 name: "{{ packages }}"
13 state: present
14 vars:
15 packages:
16 - httpd
17 - httpd-devel
-
Nutzen Sie den Fully Qualified Collection Name (FQCN), z.B.
ansible.builtin.debug
anstattdebug
-
Setzen Sie die Privilegienerweiterung auf Taskebene, nicht Playebene ein
-
Versuchen Sie, die Module
ansible.builtin.command
,ansible.builtin.shell
undansible.windows.win_shell
zu vermeiden: Diese Module sind nicht idempotent! Falls es keine andere Möglichkeit gibt, versuchen Sie, mitchanged_when
,failed_when
zu arbeiten und gegebenenfallscreates
undremoves
zu nutzen, um Ihre Tasks so idempotent wie möglich zu machen
Vaults
-
Verschlüsseln Sie alle vertraulichen Variablen/Dateien mit ansible-vault
-
Speichern Sie das Vault-Passwort an einem sicheren Ort, z.B. als Jenkins Secret oder mit Hilfe eines externen Secret Manager, wie z.B. der Vault von HashiCorp
-
Wenn Sie eine ganze Datei verschlüsseln, kann es sein, dass Sie die Namen Ihrer Variablen vergessen => führen Sie eine Vermittlungsvariable zur besseren Lesbarkeit ein, z.B.:
1 ---
2 # vault.yaml
3 vaulted_password: this_will_be_encrypted
1 ---
2 # vars.yaml
3 password: "{{ vaulted_password }}"
Ansible-Code wiederverwenden
-
Unterteilen Sie Ihre Tasks in Dateien und importieren Sie diese in Ihr Playbook bzw. nehmen Sie sie dort auf
-
Da es wichtige Unterschiede zwischen
import_tasks
undinclude_tasks
gibt (siehe diese Tabelle), versuchen Sie möglichst oftimport_tasks
zu nutzen -
Grundsätzlich sollte man sich für
import_*
entscheiden, insbesondere da-
--list-tasks
auch die importierten Tasks anzeigt (und--start-at-task
wie gewünscht funktioniert) -
--list-tags
auch die Tags der importierten Tags anzeigt -
notify
der importierten Tasks funktioniert (Vorsicht: Sie sollten “notify” mit einer der importierten Tasks nutzen, nicht mit der import_tasks Task selbst!) -
die Optionen der
import_*
Task an ALLE untergeordneten Tasks weitergegeben werden
-
-
Man sollte
include_*
nutzen, wenn-
Sie mehrere Tasks wiederholen möchten
-
der Name der Datei, die aufgenommen werden soll, von einer Variablen abhängt, z.B.
{{ ansible_os_family }}.yaml
-
eine Option NUR für die
include_*
Task gelten soll
-
Rollen
-
Sammeln Sie Ansible-Inhalte, die in zukünftigen Projekten wiederverwendet werden sollen, in Rollen
-
Nutzen Sie eine der beiden Optionen, um die Variablen innerhalb einer Rolle zu definieren –
defaults
undvars
:-
vars
bezeichnet Variablen, die von Usern nicht verändert werden sollen -
defaults
bezieht sich auf Variablen, die von Usern leicht überschrieben werden können
-
-
Fügen Sie ein Präfix zu den Variablen in einer Rolle hinzu, um aufzuzeigen, welcher Rolle sie angehören, z.B. postgresql_version für eine Variable, die in einer postgresql-Rolle definiert wurde (dies ist besonders hilfreich, wenn Sie mit mehreren Rollen gleichzeitig arbeiten)
-
Wenn Sie
ansible-galaxy init my-role
nutzen, um eine Rolle zu initialisieren, vergessen Sie nicht, am Ende alle ungenutzten Directories zu löschen
Templates
Beginnen Sie Ihre Templates mit einer Zeile, die anzeigt, welche Rollen diese Dateien generiert hat. Zu diesem Zweck ist die Variable ansible_role
sehr nützlich, Ihr Template könnte also so anfangen:
1 | # this file was created from the role: {{ansible_role}}
|
2 |
***here comes your actual template*** |
-
Nutzen Sie
ansible_managed
, falls Sie anderen Usern klarmachen möchten, dass eine spezifische Datei von Ansible generiert wurde: Sie können in der Ansible-Konfiguration (ansible.cfg
) eine Variable namensansible_managed
definieren – hier ist ein Minibeispiel so eineransible.cfg
:1 [defaults]
2 ansible_managed: Ansible managed: {file} modified
3 on %Y-%m-%d %H:%M:%S by {uid} on {host}
-
Um sicherzustellen, dass Ihr Template Informationen darüber enthält, wer es wann erstellt hat, schreiben Sie diese Variable an den Anfang Ihrer Templates:
1 # {{ansible_managed}}
2 # this file was created from the role: {{ansible_role}}
3 ***your actual template***
Fazit
Wie man sieht, deckt Ansible vielseitige Themen ab. An vielen Stellen muss man sehr sorgfältig arbeiten, um sauberen Code zu schreiben und sich zu einem späteren Zeitpunkt Arbeit zu ersparen.
Wir hoffen, dass dieser Artikel als gute Referenz dient und bei Ihren zukünftigen Ansible-Projekten hilfreich ist.
Falls Sie Fragen haben oder eine detailliertere Anleitung zu einem dieser spezifischen Themen wünschen, können Sie uns gerne ansprechen.