Technic Blog

Technik BlogAnsible

15. März 2017 Dr. Wolfgang Gehrke

Kurzer Überblick über die Technologie

Ansible ist ein open-source Werkzeug, welches bei der Automatisierung von häufigen Arbeitsabläufen, der Orchestrierung der Infrastruktur und dem Konfigurationsmanagement hilft. Von einem zentralen Unix Steuerhost können verschiedene Elemente der Infrastruktur gesteuert werden: z.B. Unix- oder Windows-Server, Netzwerkkomponenten und Hypervisoren. Dieses Werkzeug ist in der Programmiersprache Python implementiert, wobei seine Funktionalität aber auch durch den Einsatz anderer Sprachen über sehr einfache Schnittstellen erweitert werden kann.

Ansible Kommunikation mit Server Systemen
Ansible Serverkommunikation
Ansible Kommunikation mit Netzwerk Systemen
Ansible Netzwerkgerätkommunikation

Es kommt ohne einen eigenen Agenten aus und benutzt stattdessen SSH oder WinRM Verbindungen. Ein Script bzw. Playbook verwendet zur Beschreibung des Jobs YAML als Notation, welche sehr einfach gegliedert und gut lesbar ist. Einzelne Arbeitsschritte rufen Module auf, die eine JSON Notation als Resultat zurückgeben.

  • ---
    - hosts: mail_hosts
      gather_facts: true
      tasks:
      - name: shutdown Linux
        command: "shutdown -P +1"
        async: 0
        poll: 0
        when: ansible_system == "Linux"
      - name: shutdown Windows
        raw: 'start-process "C:\\Windows\\System32\\shutdown.exe" -ArgumentList "-s -t 60"'
        when: ansible_system == "Win32NT"
    
  • $ ansible -m win_ping windows_hosts
    windows_host1 | SUCCESS => {
        "changed": false,
        "ping": "pong"
    }
    windows_host2 | SUCCESS => {
        "changed": false,
        "ping": "pong"
    }
    $ ansible -m ping linux_host
    linux_host | SUCCESS => {
        "changed": false,
        "ping": "pong"
    }
    $
    

Die Verarbeitung von Variablen erfolgt durch die Jinja template engine in Python. Ebenso können Musterdateien mit variablen Teilen bereitgestellt werden, welche auch erst mit Jinja aufbereitet werden. Dieser Prozess lässt sich mit eigenen Plugins erweitern, welche in Python programmiert sein müssen.

  • ---
    - hosts: webservers
      gather_facts: true
      vars:
        web:
          deb: "apache2"
          rpm: "httpd"
      tasks:
      - name: install required packages (deb)
        apt: 
          name: "{{ web.deb }}"
          state: "latest"
        when: ansible_os_family == "Debian"
      - name: install required packages (rpm)
        yum:
          name: "{{ web['rpm'] }}"
          state: "latest"
        when: ansible_os_family == "RedHat"
    
  • $TTL {{ 24 * 60 * 60 }}
    $ORIGIN {{ DOMAIN.split('.')[-1] }}.
    
    {{ DOMAIN.split('.')[0:-1] | join('.') }} IN SOA {{ DNS_PRIMARY }}. {{ DNS_HOSTMASTER }}. (
                                    {{ lookup('pipe', 'date +%s') }}
                                    {{ 2 * 60 * 60 }}
                                    {{ 15 * 60 }}
                                    {{ 14 * 24 * 60 * 60 }}
                                    {{ 5 * 60 }} )
    {% for item in DNS_SERVERS %}
                    IN      NS      {{ item }}.
    {% endfor %}
    
    $ORIGIN {{ DOMAIN }}.
    
    ; domain generated on {{ lookup('pipe', 'date') }}
    

Ein zentraler Begriff im Konfigurationsmanagement ist die Idempotenz. Mathematisch bedeutet dies für eine Funktion, dass nach einmaliger Anwendung der Funktion ein Fixpunkt erreicht ist. Übertragen auf ein Playbook, welches einen gewünschten Endzustand beschreibt, besagt idempotent, dass einmaliges Anwenden das gleiche Resultat liefert, wie die mehrfache Anwendung - was bedeutet, dass man es bei unvorhergesehenem Abbruch ohne Probleme erneut aufrufen können sollte.

Arten des Einsatzes von Ansible

ad-hoc
zur Ausführung eines Moduls auf einer Menge von Zielmaschinen
Script
für die Abarbeitung eines Playbooks auf einem oder mehreren Targets
Kontrollmodus
für jeden Schritt wird nur geprüft, ob tatsächlich eine Operation ausgeführt werden muss (d.h. Test auf Vorhandenseins des Endzustands)

Durch weitere Parameter kann man beeinflussen, wie viele Hosts parallel bearbeitet werden oder wie lange auf eine Verbindung zu einem Host gewartet werden soll.

Schritte bei der Abarbeitung eines Moduls

  • Vorbereitung der Ausführung auf dem Kontrollhost (z.B. Verarbeitung der Variablen, Testbedingungen, Templates)
  • Übertragung zum Remotehost in temporäre Dateien (z.B. Script und Variablenbelegung)
  • Ausführung auf dem Remotehost (mit Beobachtung des Returncode und der JSON Ausgabe des Moduls)
  • Einsammeln aller Informationen des Modullaufes und Löschen aller temporären Dateien auf dem Remotehost
  • lokale Verarbeitung des Resultates

Beispiel für den Einsatz von Ansible

Ein firmeninternes Beispiel, wo Ansible zum Einsatz kommt, ist die DNS Zonenverwaltung. Die entsprechenden Playbooks müssen vom Steuerhost mit mehreren Zielhosts wie einem hidden Master, dem primary Server, den Slaves und einem Testhost auf unterschiedliche Weise kommunizieren - was eigentlich nicht einer ganz typischen Anwendung entspricht. Trotz seiner Einfachheit konnte Ansible dieser Aufgabe gerecht werden durch den Einsatz von conditionals, loops und blocks mit error handling.

Die open-source Version von Ansible bietet nur ein rudimentäres Rechtemanagement, ein sehr einfaches Logging und eine Beschreibung der zu kontaktierenden Resourcen mit Hilfe von Dateien. Dafür musste ein eigenes Framework um Ansible herum programmiert werden. Dieses Framework unterstützt auch die Revisionierung der verschiedenen Playbooks.

Die folgenden Komponenten wurden als Umgebung für Ansible konfiguriert bzw. zusätzlich in PHP programmiert:

Rechteverwaltung
Ansible arbeitet über einen zentralen Steuerhost. Dort werden die Playbooks unter einem bestimmten Nutzer ausgeführt. Um trotzdem verschiedene Administratoren unterscheiden zu können, enthält die Laufumgebung in einer Variablen den Namen des jeweiligen Administrators.
Schlüsselverwaltung
Bei der Verwendung von SSH Zugängen werden prinzipiell nur Schlüssel benutzt. Diese müssen den Playbooks bei der Ausführung zur Verfügung stehen. Potentiell lassen sich damit auch die remote ausgeführten Kommandos beschränken.
Revisionierung
Alle Playbooks werden revisioniert. Außerdem kommen dazu noch die Daten der jeweiligen Anwendung. In dem vorliegenden Fall müssen alle DNS Zonendaten gepflegt werden.
Datenbankanbindung
Manche Informationen über die zu verwaltenden Hosts befinden sich auch in Datenbanken. Diese werden den Playbooks über Dateien bereitgestellt. Dies würde im Falle von Windows auch Zugangsinformationen zu den Systemen beinhalten.
Logging
Alle Aktionen müssen nachvollziehbar sein. Dafür wird einerseits der Logging-Mechanismus von Ansible benutzt. Andererseits wird dieser ergänzt durch ein zentrales Logging aller als root- bzw. Administrator-Nutzer ausgeführten Kommandos.
Fehlerinformation
Da die Playbooks von einem anderen Programm gesteuert werden, müssen sie Informationen im Falle eines Abbruchs übertragen. Das verlangt eine Ausnahmebehandlung, die erst seit Ansible 2.0 möglich ist. Jetzt schreibt ein Playbook am Ende seines Laufes eine Statusdatei in XML, welche dann weiterverarbeitet wird.

Initialisierung von Playbooks
Vorbereitung des Playbooklaufes
Protokollierung des Playbook Processings
Protokollierung bei der Ausführung

Entwicklungsgeschichte von Ansible

Ansible wurde ursprünglich von einem Entwickler konzipiert. In der Zwischenzeit wurde dessen Firma von RedHat gekauft. Für Nutzer, die mehr Komfort benötigen und nicht selbst programmieren möchten, kann auch das kommerzielles Produkt "Ansible Tower" in Betracht kommen.

Ab etwa der Version 2.0 hat RedHat entscheidende Verbesserungen eingebracht. Es gab zum einen Spracherweiterungen zur Ausnahmebehandlung mit Hilfe von Programmblöcken. Zum anderen wurde das Spektrum von Standardmodulen deutlich erweitert z.B. im Netzwerk-, Cloud- und ebenso Windowsbereich.

Nach Abschluss der Arbeiten am DNS erschien in der Version 2.3 von Ansible auch ein Modul "nsupdate". Allerdings erlaubt dieses lediglich DDNS updates und nicht die Arbeit mit einer Zonendatei. Dies könnte in Zukunft Verwendung finden bei der Benutzung von den neuen Katalogzonen im BIND 9.11.

Neben Ansible gibt es noch weitere open-source Software für die Unterstützung Konfigurationsmanagements wie z.B. Chef, CFEngine, Puppet oder Salt, welches Ansible durch die Verwendung von Python noch am ähnlichsten ist. Ansible zeichnet sich durch seinen agent-less Ansatz und eine niedrige Lernkurve aus. Seine sehr einfache Architektur hat jedoch Grenzen bei der Skalierbarkeit durch die Verwendung des etwas aufwendigeren SSH- bzw. WinRM-Kanales, welche andere Systeme durch eigene Agenten beschleunigen.

Fazit

Ansible ist ein Werkzeug zur remote Administration und Konfiguration von Server- und Netzwerkgeräten. Dabei nutzt es etablierte Zugangskanäle und kommt ohne einen eigenen Agenten aus. Seine YAML basierte Syntax ist für den Anfänger schnell zugänglich.

Für ein vollständiges Konfigurationsmanagement in einer größeren Umgebung wird aber unbedingt ein darüberliegendes Framework benötigt. Dieses muss sich um die Bereitstellung der notwendigen Zusatzinformationen und Anmeldedaten kümmern. Außerdem ist ein detailiertes Logging geboten, was über die darin standardmäßig bereitgestellten Möglichkeiten hinausgeht.

Der hiesige Einsatz erforderte bisher noch keine Programmierung von eigenen Modulen. Jedoch sind dafür die Schnittstellen mit Hilfe von Python bzw. PowerShell leicht zugänglich. Im Kontext von Experimenten mit Katalogzonen in BIND 9.11 ergab sich die Notwendigkeit für ein eigenes Filterplugin zur Berechnung eines Hashwertes von Domänennamen.