ansible

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.

Tuesday, April 30, 11:00 – 11:45 a.m. CEST
Webinar: Driving Efficiency with Event-Driven Ansible: An Introduction

Unravel the theoretical foundations of Event-Driven Ansible alongside a practical demonstration.
Presented by our blog author Dr. Ottavia Balducci.

YAML

  • Nutzen Sie true anstelle von yes und false anstatt no

  • 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 anstatt debug

  • Setzen Sie die Privilegienerweiterung auf Taskebene, nicht Playebene ein

  • Versuchen Sie, die Module ansible.builtin.command, ansible.builtin.shell und ansible.windows.win_shell zu vermeiden: Diese Module sind nicht idempotent! Falls es keine andere Möglichkeit gibt, versuchen Sie, mit changed_when, failed_when zu arbeiten und gegebenenfalls creates und removes 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 und include_tasks gibt (siehe diese Tabelle), versuchen Sie möglichst oft import_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 und vars:

    • 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 namens ansible_managed definieren – hier ist ein Minibeispiel so einer ansible.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.

ansible

Ansible-Schulung

ATIX bietet Ansible-Schulungen für Anfänger:innen und Fortgeschrittene an, in denen Teilnehmer:innen lernen, wie man Ansible als Konfigurationsmanagement-Tool nutzt. So können sie ihre Infrastruktur mit Ansible-Rollen effizienter verwalten und finden heraus, wie sie Ansible-Rollen, Inventories und Playbooks bestmöglich erstellen, nutzen und pflegen.

The following two tabs change content below.

Ottavia Balducci

Neueste Artikel von Ottavia Balducci (alle ansehen)