Inhaltsverzeichnis

Ansible

Bild: Ansible Logo Einzelne Serversysteme mag man durchaus noch manuell einzeln installieren, konfigurieren und pflegen mögen und auch durchaus können. Komplexere Installationen, oder gleichartige Installationen lassen sich so aber nicht mehr ressourcenschonend und transparent nachvollziehbar betreiben. Daher wird man aus folgenden Gründen bestrebt sein, für diese Aufgaben ein Konfigurationsmanagement zu verwenden:

Genau in solchen Umgebungen bedient man sich daher der Automatisierung bzw. Orchestrierung.

Doch was versteht man nun unter diesem Begriff Orchestrierung? Orchestrierung beschreibt das flexible Kombinieren mehrerer Services bzw. Dienste wie auch unterschiedlicher Serverinstanzen zu einer sinnvollen (Gesamt-)Konzeption oder auch Komposition. So wird man den Webserver erst starten, wenn zuvor der Datenbank und z.B. das NAS zur Verfügung steht und nicht umgekehrt. Die Anlehnung an Begrifflichkeiten aus der Musik ist hier ganz bewusst und nicht zufällig gewählt. Die Sicht auf einzelne Service-/Daemon entspricht in etwa die eines Notenblattes einer Einzelstimme in einem Orchester. Einzelne Stimmen bzw. Instrumente machen aber noch lange kein stimmiges Gesamtensemble, erst der Dirigent (Orchestrator) sorgt für ein sinnvolles und optimales Zusammenspiel aller Einzelspieler/-stimmen.

Bekannte Anwendungen rund um das Thema Automatisierung und Orchestrierung von Serversystemen-/Rechenzentren sind Ansible, Puppet oder Chef. Im nachfolgender Anwendungsbeschreibung werden wir uns nun detailliert mit Ansible beschäftigen, da es sich bei diesem Projekt unter anderem folgende schlagkräftigen Vorteile/Argumente klar herausstellen:

  1. Ansible kann in der Community Edition kostenlos genutzt werden. Darüber hinaus bietet aber Red Hat aber auch kostenpflichtige Editionen mit grafischer Oberfläche und Support an.
  2. Eine der grössten Vorteile von Ansible, sind die vorgefertigten „Playbooks“, die z.B. auf GitHub von vielen fleissigen Helfern der Community zur Verfügung gestellt werden. Bei diesen Playbooks handelt es sich um vorgefertigte Scripte, mit denen Server automatisiert bereitgestellt und konfiguriert werden können. Somit muss nicht für jede Anwendung erneut eine neue Konfigurationsvorgehensweise geschrieben werden um eine Anwendung zu orchestrieren. Dank dieser vorgefertigten Playbooks ist die Automatisierung also wesentlich einfacher. Alle Konfigurationsinformationen werden in diesen Ansible Playbooks gesammelt und auf die im Host Inventory gespeicherten Hosts ausgerollt.
  3. Ein weiterer Vorteil von Ansible, ist der Umstand dass kein separater eigener Server aufgesetzt werden muss, um Ansible und seine Paybooks zu nutzen. Der (Client-)Rechner, auf dem die Playbooks zur Verfügung stehen, müssen nur die Server, die automatisiert verwaltet und konfiguriert werden sollen, mit Hilfe der SSH erreichen werden können.
    Ansible arbeitet im Push-Verfahren und benötigt daher neben SSH und Python keine weitere Installation auf den einzelnen Systemen.
  4. Gegenüber Chef und Puppet ist die einfachere Verwaltung und Verwendung von Ansible, da z.B. keine zusätzliche Software auf dem zu verwaltenden System benötigt wird. Die Definitionen erfolgen im JSON-Format. Zusätzliche optionale Module können aber auch in jeder beliebigen Programmiersprache geschrieben sein. Hauptsächlich werden YAML-basierten Skripte, die als „Playbooks“ bezeichnet werden, zur Orchestrierung der Systeme verwendet.
    Gegenüber anderen Konfigurationstools wird bei Ansible mit der Beschreibung des gewünschten Sollzustandes verfolgt und nicht die Abarbeitung granularer Einzelschritte z.B. in einem Script beschrieben. Darüber hinaus werden bei Ansible auch immer nur die Arbeitsschritte ab gearbeitet und erledigt, die aktuell nötig sind und nicht stur eine Abfolge von Einzeltätigkeiten perlenkettenmässig abgearbeitet. Aufgaben lassen sich so beliebig oft ausführen, ohne dass negative Seiteneffekte durch mehrmaliges unnötiges Abarbeiten von Aufgaben auftreten werden,

Grundlagen

Dokumentation

O’REILLY Fachbuch - Ansible: Up & Running

Ein wertvoller und verlässlicher Begleiter beim eingehenden Studium von Ansible und dessen Fähigkeiten kann sicher das Buch Ansible: Up & Running (ISBN: 978-1-491-97980-8) von O’REILLY herangezogen und empfohlen werden. Bild: Photo des Buchs Ansible: Up & Running von O`REILLY

Gourav Shah - Ansible Playbook Essentials

Ein weiteres sehr gutes Fachbuch zu Ansible in englischer Sprache ist das Buch Ansible Playbook Essentials von Gourav Shah, erhältlich als (eBook, PDF) oder auch als gedruckte Version im einschlägigem Fachbuchhandel zu bestellen: (ISBN: 978-1-784-39829-3). Bild: Buchcover Ansible Playbook Essentials von Gourav Shah

Axel Miesen - Ansible - Das Praxisbuch für Administratoren und DevOps-Teams

Das dritte Buch (aktuelle Auflage von August 2022) im Bunde, welches sehr zu empfehlen ist, ist das Buch Ansible - Das Praxisbuch für Administratoren und DevOps-Teams von Axel Miesen, erschienen im Verlag Rheinwerk Computing. Erhältlich als (eBook, PDF) oder als gedruckte Version im einschlägigen Fachbuchhandel zu bestellen: (ISBN: 978-3-8362-8906-1). Bild: Buchcover Ansible für Administratoren und DevOps-Teams vom Axel Miesen

online-Dokumentation

Eine stets aktuelle Programm- und Projektdokumentation ist in der in der Onlinebibliothek unter : https://docs.ansible.com/ansible/latest/index.html zu finden!

Folgende links sind immer eine gute Quelle, sich zu den Möglichkeiten Rund um Ansible zu informieren:

Dokumentation (RPM)

Vom Maintainer des Paketes ansible wird auch die zugehörige sehr umfangreiche Dokumentation in Form eines eigenen Paketes ansible-doc zur Verfügung gestellt. Wir installieren uns also das zugehörige Paket, mit Hilfe des Distributionsspezifischen Paket-Managers. Bsp.:

 # dnf install ansible-doc -y
 $ sudo apt install ansible-doc -y
 # zypper in ansible-doc -y

Nach erfolgter Installation finden wir auf der Festplatte unserer Admin-Workstation umfangreiche Dokumentationen. Mit Hilfe des Befehls rpm -qil erhalten wir bei Fedora-spezifischen Distributionen einen Überblick über das betreffende Paket.

 # rpm -qi ansible-doc
Name        : ansible-doc
Version     : 2.9.2
Release     : 1.fc31
Architecture: noarch
Install Date: Sa 21 Dez 2019 20:38:39 CET
Group       : Unspecified
Size        : 311719083
License     : GPLv3+
Signature   : RSA/SHA256, Mo 09 Dez 2019 18:59:12 CET, Key ID 50cb390b3c3359c4
Source RPM  : ansible-2.9.2-1.fc31.src.rpm
Build Date  : So 08 Dez 2019 21:42:23 CET
Build Host  : buildvm-aarch64-24.arm.fedoraproject.org
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : http://ansible.com
Bug URL     : https://bugz.fedoraproject.org/ansible
Summary     : Documentation for Ansible
Description :

Ansible is a radically simple model-driven configuration management,
multi-node deployment, and remote task execution system. Ansible works
over SSH and does not require any software or daemons to be installed
on remote nodes. Extension modules can be written in any language and
are transferred to managed machines automatically.

This package installs extensive documentation for ansible

Ein entsprechender Aufruf auf einem Debian-basierten System wäre in diesem Falle:

 $ dpkg -l ansible-doc
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-==================================
ii  ansible-doc    2.9.6+dfsg-1 all          Ansible documentation and examples

Eine Auflistung sämtlicher mitgelieferter Dateien erhält man durch Ergänzung der Option l.

 # rpm -qil ansible-doc

Ein entsprechender Aufruf auf einem Debian-basierten System wäre in diesem Falle:

 $ dpkg -L ansible-doc

Ansible Funktionsbeschreibung

Das folgende Übersichtsskizze zeit die grundlegende Module und die die Funktionsweise von Ansible.

Bild: Ansible Übersichtsskizze

Der Managementknoten im obigen Bild ist der Steuerknoten (Managing Node), der die gesamte Ausführung des Playbooks steuert. Es ist der Knoten, von dem aus die Installation ausgeführt wird, also z.B. unser zentraler Admin-Node. Die Inventarisierungsdatei enthält die Liste der Hosts, auf denen die Ansible Module ausgeführt werden müssen. Der Verwaltungsknoten stellt eine SSH-Verbindung her und führt die kleinen Module auf dem Host-Computer aus, installiert, konfiguriert und aktualisiert ggf. das entsprechende Softwarepaket.

Das Schöne an Ansible ist dabei:

YAML - was ist das?

Wie Eingangs schon beschrieben verwendet Ansible Playbooks zur Beschreibung der Orchestrierungs- und Automatisierungsaufgaben. Diese Playbooks sind meinst in YAML geschrieben und somit für den Admin eher sehr leicht zu verstehen, zu lesen und zu schreiben sind. Diese Playbooks beinhalten dabei detaillierte Informationen, die die Hard- und Software beschreibt. Somit kann z.B. von zentraler Stelle aus gleichnamige Dienste aufgesetzt und auch aktualisiert werden.

Wir wollen uns daher kurz die grundlegende Syntax dazu ansehen. YAML selbst ist relativ einfach und intuitiv und daher in aller Regel einfacher und schneller zu verstehen als z.B. XML und JSON. Eine detaillierte Beschreibung dazu findet sich auch in der Ansible Referens zu YAML.

YAML spezifische Ausdrücke:

Rund um YAML werden wir des öfteren über folgende Ausdrücke stolpern:

  • Service/Server : Ein Prozess auf der Maschine, der den Dienst zur Verfügung stellt.
  • Machine : Ein physischer Server, vm(virtuelle Maschine) oder ein Container.
  • Target machine : Eine Maschine die wir mit Ansible konfigurieren werden.
  • Task : Eine Aktion (ausführen, löschen, aktualisieren) usw., die von Ansible verwaltet wird.
  • Playbook : Dies ist eine yml-Datei, in der Ansible Befehle aufgelistet werden und dann auf dem Zielsystem ausgeführt wird.

Viele hilfreiche Informationen zur YAML-Notation sind in der Ansible-Dokumentation zu finden.

Playbooks

In diesem Abschnitt werden wir uns nun die Playbooks, die Ansbilbe verwendet, etwas genauer ansehen.

Playbooks sind die Dateien, in denen Ansible-Code im YAML1)-Format geschrieben. Playbooks sind eines der Kernmerkmale von Ansible und teilen Ansible mit, was genau ausgeführt und konfiguriert werden soll. Sie sind sozusagen eine Art ToDo-Liste für Ansible, die eine Liste von Aufgaben enthält.

Ein Playbook enthält ein oder mehrere Aufgaben/ Schritte (tasks) zur Installation und Konfiguration, die der Admin auf einem Zielsystem (target machine) ausführen möchte und sind sozusagen die elementaren Bausteine für alle Anwendungsfälle von Ansible. Playbooks werden sequentiell ausgeführt. Jedes Playbook wird entsprechend seiner Aufgabe strukturiert.

Die Aufgabe eines Playbooks ist es, eine Reihe von Anweisungen abzubilden, mit deren ein bestimmtes Zielsystem (machine) bzw. ein Service/Daemon (service/server) auf diesem Zielsystem installiert und konfiguriert wird.

Da es sich bei YAML um eine sogenannte Strict programming language handelt, ist beim Schreiben der YAML-Dateien besondere Sorgfalt geboten. Es gibt zwar verschiedene YAML-Editoren, aber in aller Regel reicht dazu auch ein ganz normaler Editor wie z.B. vim, nano oder emacs.

In nachfolgendem Beispiel wollen wir einen Mailserver „installieren“ und definieren hierzu folegnde Werte/Abschnitte:

  1. name : Dieser Tag gibt den Namen des Ansible-Playbooks an; dieser Wert ist frei wähllbar und muss nur eindeutig sein. In unserem Fall beschreiben wir einfach, was das Script später erledigen soll, nämlich einen Mailserver installieren.
  2. hosts : Dieses Tag gibt die Listen der Hosts oder der Hostgruppe an, gegen die wir dann später die Task ausführen wollen. Das Host-Feld/Tag ist obligatorisch. Es teilt Ansible mit, auf welchen Hosts die aufgelisteten Tasks ausgeführt werden sollen. Die Aufgaben können auf demselben Rechner oder auf einem entfernten Rechner ausgeführt werden. Man kann die Tasks auf einem oder auch mehreren Rechnern ausführen und daher kann das hosts-Tag auch einen Eintrag für eine Gruppe von Hosts haben.
  3. vars : Mit dem Vars-Tag können Sie die Variablen definieren, die wie in unserem Playbook verwenden können.
  4. tasks : Alle Playbooks enthalten entweder Aufgaben oder eine Liste von auszuführenden Aufgaben. Aufgaben sind eine Liste von Aktionen, die wir später auf dem oder den Zielsystem ausführen wollen. Ein Aufgabenfeld enthält einen optionalen Namen der Aufgabe und fungiert als Hilfetext für den Admin.
    Jeder Task verweist intern auf ein Stück Code, das auch als Modul bezeichnet wird. Ein Modul definiert dabei, was später ausgeführt werden soll, und beinhaltet die zugehörigen Argumente, die für das auszuführende Modul erforderlich sind.
 # vim /etc/ansible/beispiel.yml
/etc/ansible/beispiel.yml
--- #YAML start Beispielsscript zur Installation und Konfiguration eines Mailservers
    name: install and configure MX
    hosts: mxtest.dmz.nausch.org
    become: yes

    vars: 
       mx_port_value : 25
   
    tasks:
    -name: Install Postfix
       yum: <code to install the MX>
    
    -name: Ensure the installed service is enabled and running
    service:
      name: <your service name>
#YAML end syntax

Facts

Ansible ermittelt bei jedem Aufruf Systeminformationen des jeweiligen Zielsystems. Im Bezug auf Ansible werden diese Systeminformationen auch als facts bezeichnet. In unseren Playbooks auf die wir nun gleich noch eingehender eingehen werden, können wir dann später noch gezielt zugreifen. In unseren Playbooks können wir dann gezielt auf diesen Daten zugreifen, um z.B. maßgeschneiderte Konfigurationen, basierend auf genau diese facts (Hosteinstellungen) erzeugen lassen.

Wir können uns die facts eines Zielhost z.B. mit folgendem Befehl anzeigen lassen. Wir haben die Option --ask-become-pass angegeben, da unser Zielsystem einige Daten nur preisgibt, sofern der User auch entsprechende root-Rechte besitzt. Die Ausgabe hier wurde entsprechend gekürzt

 $ ansible centos8 --ask-become-pass -m setup

BECOME password:
www8.dmz.nausch.org | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.10.10.90",
            "10.0.0.90"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::d4bb:cb5:9a09:a808",
            "fe80::6d8:6bbc:a9e9:449e"
        ],
        "ansible_apparmor": {
            "status": "disabled"
        },
        "ansible_architecture": "x86_64",
        "ansible_bios_date": "01/01/2011",
        "ansible_bios_version": "0.5.1",

...

...
        "ansible_system_capabilities_enforced": "True",
        "ansible_system_vendor": "Red Hat",
        "ansible_uptime_seconds": 410582,
        "ansible_user_dir": "/root",
        "ansible_user_gecos": "root",
        "ansible_user_gid": 0,
        "ansible_user_id": "root",
        "ansible_user_shell": "/bin/bash",
        "ansible_user_uid": 0,
        "ansible_userspace_architecture": "x86_64",
        "ansible_userspace_bits": "64",
        "ansible_virtualization_role": "guest",
        "ansible_virtualization_type": "kvm",
        "discovered_interpreter_python": "/usr/libexec/platform-python",
        "gather_subset": [
            "all"
        ],
        "module_setup": true
    },
    "changed": false
}

Da die Abfrage/Ausgabe aller facts auf Grund der vielen Daten schnell unübersichtlich werden kann, ist es auch möglich sich nur einen bestimmten Teilbereich anzeigen zu lassen. Im nachfolgenden Beispiel lassen wir uns z.B. nur Speicherrelevante facts anzeigen:

 # ansible centos8 --ask-become-pass -m setup -a 'filter=ansible_mem*'

BECOME password:
www8.dmz.nausch.org | SUCCESS => {
    "ansible_facts": {
        "ansible_memfree_mb": 7203,
        "ansible_memory_mb": {
            "nocache": {
                "free": 7517,
                "used": 294
            },
            "real": {
                "free": 7203,
                "total": 7811,
                "used": 608
            },
            "swap": {
                "cached": 0,
                "free": 4095,
                "total": 4095,
                "used": 0
            }
        },
        "ansible_memtotal_mb": 7811,
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false
}

Variablen

Variablen in Playbooks sind der Verwendung von Variablen in jeder anderen Programmiersprache sehr ähnlich. Mit Hilfe von Variablen können wir einfach wiederkehrende Werteangaben einmal definieren und später reicht es dann jeweils auf diese Definition zu referenzieren.

Bei der Definition bzw.genauer gesagt bei der Wertezuweisung zu Variablen, stehen uns altbekannte Möglichkeiten aus diversen Programmiersprachen zur Verfügung. so können wir z.B. bei der Definition der Nodes hosts: folgende Wertedefinitionen verwenden:

Neben der Variablenzuweiseung ist es auch ferner möglich Variablen auf Grund einer Bedingung zu setzen.

So können wir zum Beispiel die Variable DNS_port definieren und dieser dem Wert 53 zuweisen. Diese Variable und natürlich auch den zugehörigen Wert können wir dann in unserem Playbook überall dort Verwenden, wo wir später die Variable dns_port verwenden. Die zugehörige Definition in einem unserer Playbooks würde dann wie folgt aussehen.

---
  - hosts : dns.dmz.nausch.org 
  vars:
    dns_port : 53 

Im nachfolgednen Beispiel wollen wir eine Variable fallbezogen setzen.

---
block: 
   - name: Install bind Nameserver-Daemon 
      action: > 
      yum name = "demo-nds1" state = present 
      register: Output 
          
   always: 
      - debug: 
         msg: 
            - "Install bind task ended with message: {{Output}}" 
            - "Installed bind  - {{Output.changed}}"

In diesem Beispiel haben wir die Variable output verwendet. Sehen wir uns nun dazu die einzelnen Definitionen (keywords) etwas genauer an:

  1. block : Ansible syntax zur Ausführung des nachfolgenden Code-Blocks.
  2. name : Relevanter Name des Blocks - Dieser wird bei der Protokollierung verwendet und hilft bei der Fehlersuche, wenn alle Blöcke erfolgreich ausgeführt wurden.
  3. action : Der Code neben dem Action-Tag ist die auszuführende Aufgabe. Die action wiederum ist ein Ansible-Schlüsselwort, das in yaml verwendet wird.
  4. register : Die Ausgabe der Aktion wird mit dem Register-Schlüsselwort registriert und Output ist der Variablenname, der die Aktionsausgabe enthält.
  5. always : Dies ist ein Ansible-Schlüsselwort, das angibt, dass die Aktion immer ausgeführt werden soll.
  6. msg : Zeigt die definierte Meldung an.

Verwendung der Variable {{Output}}:
Zunächst wird der wert der Variable Output ermittelt. Ausserdem wird der Wert der Ausgabevariablen ausgegeben, so wie er im Abschnitt msg verwendet wird.

Zusätzlich kann man einer Variable noch eine sog. Sub-Eigenschaft zuweisen; so wird in dem gezeigten Fall erfolgt die Ausgabe nur, wenn sich die Ausgabe auch wirklich geändert hat, die Bedingung also erfüllt worden ist.

Blöcke

Ein Playbook wird meist in einzelen Abschnitte und Code-Blöcken unterteilt. Somit ist ein Playbook zum einen leichter für den Admin les- und handelbar. Ferner hilft das Schreiben der spezifischen Anweisung in Blöcken, Funktionalitäten zu trennen, sie bei Bedarf mit Ausnahmeregeln zu behandeln oder in den nachfolgend gezeihgten Schleifenbedingungen abzuarbeiten.

Ausnahmeregelung und -behandlung

Die Ausnahmebehandlung in Ansible ist ähnlich der Ausnahmebehandlung in jeder Programmiersprache. Nachfolgendes Beispiel soll dies entsprechend illustrieren:

---
tasks: 
   - name: Name des auszuführenden tasks
      always: 
         - debug: msg = "Debugmeldung, welche immer ausgegben und immer geloggt werden soll." 

      block: 
         - debug: msg = 'Debugmeldung die ausgegeben und geloggt werden soll ' 
         - command: <Befehl der ausgeführt werden soll> 
      
      rescue: 
         - debug: msg = 'Folgender Ausnahmezustand wurde festgestellt und wird auch ausgegeben ' 
         - command: <Rescue Befehle die ausgeführt werden, sofern obige Ausnahme auftrat.

Auch hier werfen wir nun einen Blick auf die einzelnen Definitionen:

  1. always und rescue sind spezifische Schlüsselwörter für Ausnahmebedingungen und -regelungen.
  2. always Wird immer vorbehaltlos ausgeführt.
  3. block definiert die shell Befehle die auf dem Zielsystem ausgeführt werden sollen.
    Wenn der Befehl, der innerhalb des block-Abschnittes definiert wurde, fehlschlägt, dann erreicht die Ausführung den Rescue-Block und er wird ausgeführt. Sofern es keinen Fehler m Befehl unter Block-Definition gab, dann wird der Rescue-Block nicht ausgeführt!

Schleifen

Das nachfolgende Konfigurationsbeispiel, bzw. ein Auszug aus einem Playbook, zeigt, wie Schleifenbedingungen in Ansible gesetzt und verarbeitet werden. In diesem Beispiel wollen wir alle html-Dateien eines Verzeichnisses auf einem Webserver, bzw. genauer gesagt aus dessen DOCUMENT_ROOT kopieren.

Die meisten der Befehle, die im folgenden Beispiel verwendet werden, haben wir uns zuvor schon genauer angesehen, so dass wir uns hier auf die Verwendung von Schleifen konzentrieren.

--- #Ansible Schleifenoperation 
- hosts: www-n.dmz.nausch.org 
   tasks: 
      - name: Install Apache 
      shell: "ls *.html" 
      register: output 
      args: 
         chdir: /var/www/html/demo/webseite 
      
      - file: 
         src: '/tmp/{{ item }}' 
         dest: ''/var/www/html/demo/webseite/{{ item }}' 
         state: link 
      loop: " {{ output.stdout_lines }} "

Bedingungen

Bedingungen verwendet man immer dann, wenn man einen bestimmten Schritt nur dann ausführen möchte, wenn zuvor eine definierte Bedingung erfüllt worden ist.

Im nachfolgenden Beispiel wird die Nachricht gewünschte OS vorhanden nur ausgegeben wenn die Variable os den Wert RedHat beinhaltet. Das Keyword when kann dabei mit den bekannten logischen Verknüpfungen logisch und bzw. logisch oder verwendet werden.

--- #Beispiel für eine Bedingung
- hosts: all 
   vars: 
      os: "RedHat" 
   tasks: 
      - name: Testing Ansible Variable 
      debug: 
         msg: "gewünschte OS vorhanden" 
         when: os == "RedHat" 

adhoc - Befehle

Ad-hoc-Befehle sind Befehle, die einzeln auf der Konsole ausgeführt werden, unabhängig davon, ob ein entsprechende Playbook definiert wurde.

So könnte man zum Beispiel einen reboot aller definierten Server anstoßen, in dem man den passenden adhoc-Befehl mit Hilfe des Programms /usr/bin/ansible ausführt. Hierzu werden wir uns nachfolgend gleich einmal ein entsprechendes Beispiel etwas genauer ansehen.

Der Befehl ansible-playbook wird für das Konfigurationsmanagement und das Deployment verwendet. Wird beim Aufruf von ansible keine zusätzlichen Befehle und Optionen angegeben bzw. beim Aufruf von ansible-playbook kein Playbook verwendet gibt der Befehl alle zur Verfügung stehenden Optionen aus.

Bsp.:

 #  ansible-playbook
Usage: ansible-playbook [options] playbook.yml [playbook2 ...]

Runs Ansible playbooks, executing the defined tasks on the targeted hosts.

Options:
  --ask-vault-pass      ask for vault password
  -C, --check           don't make any changes; instead, try to predict some
                        of the changes that may occur
  -D, --diff            when changing (small) files and templates, show the
                        differences in those files; works great with --check
  -e EXTRA_VARS, --extra-vars=EXTRA_VARS
                        set additional variables as key=value or YAML/JSON, if
                        filename prepend with @
  --flush-cache         clear the fact cache
  --force-handlers      run handlers even if a task fails
  -f FORKS, --forks=FORKS
                        specify number of parallel processes to use
                        (default=5)
  -h, --help            show this help message and exit
  -i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY
                        specify inventory host path or comma separated host
                        list. --inventory-file is deprecated
  -l SUBSET, --limit=SUBSET
                        further limit selected hosts to an additional pattern
  --list-hosts          outputs a list of matching hosts; does not execute
                        anything else
  --list-tags           list all available tags
  --list-tasks          list all tasks that would be executed
  -M MODULE_PATH, --module-path=MODULE_PATH
                        prepend colon-separated path(s) to module library
                        (default=[u'/root/.ansible/plugins/modules',
                        u'/usr/share/ansible/plugins/modules'])
  --new-vault-id=NEW_VAULT_ID
                        the new vault identity to use for rekey
  --new-vault-password-file=NEW_VAULT_PASSWORD_FILES
                        new vault password file for rekey
  --skip-tags=SKIP_TAGS
                        only run plays and tasks whose tags do not match these
                        values
  --start-at-task=START_AT_TASK
                        start the playbook at the task matching this name
  --step                one-step-at-a-time: confirm each task before running
  --syntax-check        perform a syntax check on the playbook, but do not
                        execute it
  -t TAGS, --tags=TAGS  only run plays and tasks tagged with these values
  --vault-id=VAULT_IDS  the vault identity to use
  --vault-password-file=VAULT_PASSWORD_FILES
                        vault password file
  -v, --verbose         verbose mode (-vvv for more, -vvvv to enable
                        connection debugging)
  --version             show program's version number and exit

  Connection Options:
    control as whom and how to connect to hosts

    -k, --ask-pass      ask for connection password
    --private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
                        use this file to authenticate the connection
    -u REMOTE_USER, --user=REMOTE_USER
                        connect as this user (default=None)
    -c CONNECTION, --connection=CONNECTION
                        connection type to use (default=smart)
    -T TIMEOUT, --timeout=TIMEOUT
                        override the connection timeout in seconds
                        (default=10)
    --ssh-common-args=SSH_COMMON_ARGS
                        specify common arguments to pass to sftp/scp/ssh (e.g.
                        ProxyCommand)
    --sftp-extra-args=SFTP_EXTRA_ARGS
                        specify extra arguments to pass to sftp only (e.g. -f,
                        -l)
    --scp-extra-args=SCP_EXTRA_ARGS
                        specify extra arguments to pass to scp only (e.g. -l)
    --ssh-extra-args=SSH_EXTRA_ARGS
                        specify extra arguments to pass to ssh only (e.g. -R)

  Privilege Escalation Options:
    control how and which user you become as on target hosts

    -s, --sudo          run operations with sudo (nopasswd) (deprecated, use
                        become)
    -U SUDO_USER, --sudo-user=SUDO_USER
                        desired sudo user (default=root) (deprecated, use
                        become)
    -S, --su            run operations with su (deprecated, use become)
    -R SU_USER, --su-user=SU_USER
                        run operations with su as this user (default=None)
                        (deprecated, use become)
    -b, --become        run operations with become (does not imply password
                        prompting)
    --become-method=BECOME_METHOD
                        privilege escalation method to use (default=sudo),
                        valid choices: [ sudo | su | pbrun | pfexec | doas |
                        dzdo | ksu | runas | pmrun ]
    --become-user=BECOME_USER
                        run operations as this user (default=root)
    --ask-sudo-pass     ask for sudo password (deprecated, use become)
    --ask-su-pass       ask for su password (deprecated, use become)
    -K, --ask-become-pass
                        ask for privilege escalation password

Zusätzliche Hinweise zum Befehl ansible-playbook finden sich in der zugehörigen manpage.

ANSIBLE-PLAYBOOK(1)                         System administration commands                        ANSIBLE-PLAYBOOK(1)

NAME
       ansible-playbook - Runs Ansible playbooks, executing the defined tasks on the targeted hosts.

SYNOPSIS
       ansible-playbook [options] playbook.yml [playbook2 ...]

DESCRIPTION
       the tool to run Ansible playbooks, which are a configuration and multinode deployment system. See the project
       home page (https://docs.ansible.com) for more information.

COMMON OPTIONS
       --ask-su-pass
           ask for su password (deprecated, use become)

       --ask-sudo-pass
           ask for sudo password (deprecated, use become)

       --ask-vault-pass
           ask for vault password

       --become-method BECOME_METHOD
           privilege escalation method to use (default=sudo), valid choices: [ sudo | su | pbrun | pfexec | doas |
           dzdo | ksu | runas | pmrun ]

       --become-user BECOME_USER
           run operations as this user (default=root)

       --flush-cache
           clear the fact cache

       --force-handlers
           run handlers even if a task fails

       --list-hosts
           outputs a list of matching hosts; does not execute anything else

       --list-tags
           list all available tags

       --list-tasks
           list all tasks that would be executed

       --new-vault-id NEW_VAULT_ID
           the new vault identity to use for rekey

       --new-vault-password-file
           new vault password file for rekey

       --private-key, --key-file
           use this file to authenticate the connection

       --scp-extra-args SCP_EXTRA_ARGS
           specify extra arguments to pass to scp only (e.g. -l)

       --sftp-extra-args SFTP_EXTRA_ARGS
           specify extra arguments to pass to sftp only (e.g. -f, -l)

       --skip-tags
           only run plays and tasks whose tags do not match these values
           specify common arguments to pass to sftp/scp/ssh (e.g. ProxyCommand)

       --ssh-extra-args SSH_EXTRA_ARGS
           specify extra arguments to pass to ssh only (e.g. -R)

       --start-at-task START_AT_TASK
           start the playbook at the task matching this name

       --step
           one-step-at-a-time: confirm each task before running

       --syntax-check
           perform a syntax check on the playbook, but do not execute it

       --vault-id
           the vault identity to use

       --vault-password-file
           vault password file

       --version
           show program’s version number and exit

       -C, --check
           don’t make any changes; instead, try to predict some of the changes that may occur

       -D, --diff
           when changing (small) files and templates, show the differences in those files; works great with --check

       -K, --ask-become-pass
           ask for privilege escalation password

       -M, --module-path
           prepend colon-separated path(s) to module library (default=[u'/home/jenkins/.ansible/plugins/modules',
           u'/usr/share/ansible/plugins/modules'])

       -R SU_USER, --su-user SU_USER
           run operations with su as this user (default=None) (deprecated, use become)

       -S, --su
           run operations with su (deprecated, use become)

       -T TIMEOUT, --timeout TIMEOUT
           override the connection timeout in seconds (default=10)

       -U SUDO_USER, --sudo-user SUDO_USER
           desired sudo user (default=root) (deprecated, use become)

       -b, --become
           run operations with become (does not imply password prompting)

       -c CONNECTION, --connection CONNECTION
           connection type to use (default=smart)

       -e, --extra-vars
           set additional variables as key=value or YAML/JSON, if filename prepend with @

       -f FORKS, --forks FORKS
           specify number of parallel processes to use (default=5)

       -h, --help
           show this help message and exit


       -b, --become
           run operations with become (does not imply password prompting)

       -c CONNECTION, --connection CONNECTION
           connection type to use (default=smart)

       -e, --extra-vars
           set additional variables as key=value or YAML/JSON, if filename prepend with @

       -f FORKS, --forks FORKS
           specify number of parallel processes to use (default=5)

       -h, --help
           show this help message and exit

       -i, --inventory, --inventory-file
           specify inventory host path or comma separated host list. --inventory-file is deprecated

       -k, --ask-pass
           ask for connection password

       -l SUBSET, --limit SUBSET
           further limit selected hosts to an additional pattern

       -s, --sudo
           run operations with sudo (nopasswd) (deprecated, use become)

       -t, --tags
           only run plays and tasks tagged with these values

       -u REMOTE_USER, --user REMOTE_USER
           connect as this user (default=None)

       -v, --verbose
           verbose mode (-vvv for more, -vvvv to enable connection debugging)

ENVIRONMENT
       The following environment variables may be specified.

       ANSIBLE_CONFIG — Override the default ansible config file

       Many more are available for most options in ansible.cfg

FILES
       /etc/ansible/ansible.cfg — Config file, used if present

       ~/.ansible.cfg — User config file, overrides the default config if present

AUTHOR
       Ansible was originally written by Michael DeHaan. See the AUTHORS file for a complete list of contributors.

COPYRIGHT
       Copyright © 2017 Red Hat, Inc | Ansible. Ansible is released under the terms of the GPLv3 License.

SEE ALSO
       ansible(1), ansible-config(1), ansible-console(1), ansible-doc(1), ansible-galaxy(1), ansible-inventory(1),
       ansible-pull(1), ansible-vault(1)

       Extensive documentation is available in the documentation site: http://docs.ansible.com. IRC and mailing list
       info can be found in file CONTRIBUTING.md, available in: https://github.com/ansible/ansible

Ansible 2.4.2.0                                       11/29/2017                                  ANSIBLE-PLAYBOOK(1)

Will man z.B. die installierte und Verwendete Version von Ansible abfragen gibt man die Opion --version beim Aufruf des Befehls ansible an.

 # ansible --version
ansible [core 2.13.2]
  config file = /home/django/.ansible.cfg
  configured module search path = ['/home/django/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.8/dist-packages/ansible
  ansible collection location = /home/django/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.8.10 (default, Jun 22 2022, 20:18:18) [GCC 9.4.0]
  jinja version = 3.1.2
  libyaml = True

Sehen wir uns nun an, wie wir die zuvor gestelle Aufgabe des gleichzeitigen Neustarts von einer Gruppe Server parallelisiert anstoßen können. Im folgenden Beispiel wollen wir in der Gruppe intranet alle Server neu starten und dabei statt der default-mäßigen parallelen Abarbeitung von 5 parallelen Prozessen 15 verwenden.

 $ ansible intranet -a "/usr/sbin/reboot" -f 15

Genau so ist es natürlich möglich parallel auf mehreren Maschinen eine Date (um)zukopieren. Im nachfolgenden Beispiel kopieren wir auf allen DMZ-Maschinen die Datei /etc/yum.repos.d/nausch.org.repo in das Zielverzeichnis /tmp und geben dabei einen neuen Dateinamen an.

 $ ansible dmz -m copy -a "src = /etc/yum.repos.d/nausch.org.repo dest = /tmp/nausch.org.repo.backup"

Ebenso kann man natürlich auch auf allen Webservern (Gruppe www) z.B. ein spezifisches Verzeichnis anlegen lassen.

 $ ansible www -m file -a "dest = /var/www/html/new_website mode = 755 owner = apache group = apache state = directory"

Natürlich kann man auf diesem Wege auch ganze Ordnerstrukturen und Dateien auf mehreren Maschinen der Gruppe intranet löschen.

 $ ansible intranet -m file -a "dest = /home/admin1/.ssh/authorized_keys state = absent"

Aber nicht nur für die Ausführung von Dateibefehlen kann über adhoc-Kommandos erfolgen, sondern z.B. auch Befehle des Paketmanagers dnf bzw. auf älteren Systemen yum.

Der folgende Befehl prüft z.B. ob das Paket bash-completion auf allen Servern der Gruppe all nicht installiert wurde:

 $ ansible all -m yum -a "name = bash-completion state = absent" 

Im folgenden Beispiel wollen wir wissen, ob auf allen Systemen im Intranet der Timeserver-Daemon chrony installiert wurde.

 $ ansible intranet -m yum -a "name = chrony state = present"

Wollen wir zusätzlich noich wissen, ob auch die letzte Version installiert wurde, benutzen wir folgenden Aufruf:

 $ ansible intranet -m yum -a "name = chrony state = latest" 

Module - Dokumentation

Ansible bringt bei der Installation eine Vielzahl von Modulen, die sich im Verzeichnis ../ansible/modules/ befinden, mit, mit deren Hilfe wir uns die Arbeit mit unseren Playbooks wesentlich vereinfachen können.

Wie diese Module zu verwenden sind, kann man entweder über die Ansible-Dokuseite im WEB erkunden oder auch mit Hilfe des Befehls ansible#doc erfragen.

Also entweder im Falle des Modules dnf die Webseite https://docs.ansible.com/ansible/latest/modules/dnf_module.html besuchen oder auf der Konsole den Befehl ansible-doc dnf bemühen.

 $ ansible-doc dnf
> DNF    (/usr/lib/python3.6/site-packages/ansible/modules/packaging/os/dnf.py)

        Installs, upgrade, removes, and lists packages and groups with the `dnf' package
        manager.

  * This module is maintained by The Ansible Core Team
OPTIONS (= is mandatory):

- allow_downgrade
        Specify if the named package and version is allowed to downgrade a maybe already
        installed higher version of that package. Note that setting allow_downgrade=True can
        make this module behave in a non-idempotent way. The task could end up with a set of
        packages that does not match the complete list of specified packages to install
        (because dependencies between the downgraded package and others can cause changes to
        the packages which were in the earlier transaction).
        [Default: no]
        type: bool
        version_added: 2.7

- autoremove
        If `yes', removes all "leaf" packages from the system that were originally installed as
        dependencies of user-installed packages but which are no longer required by any such
        package. Should be used alone or when state is `absent'
        [Default: no]
        type: bool
        version_added: 2.4

- bugfix
        If set to `yes', and `state=latest' then only installs updates that have been marked
        bugfix related.
        [Default: no]
        type: bool
        version_added: 2.7

- conf_file
        The remote dnf configuration file to use for the transaction.
        [Default: (null)]

- disable_excludes
        Disable the excludes defined in DNF config files.
        If set to `all', disables all excludes.
        If set to `main', disable excludes defined in [main] in dnf.conf.
        If set to `repoid', disable excludes defined for given repo id.
        [Default: (null)]
        version_added: 2.7

- disable_gpg_check
        Whether to disable the GPG checking of signatures of packages being installed. Has an
        effect only if state is `present' or `latest'.
        [Default: no]
        type: bool

- disable_plugin
        `Plugin' name to disable for the install/update operation. The disabled plugins will
        not persist beyond the transaction.
        [Default: (null)]
        version_added: 2.7

- disablerepo
        `Repoid' of repositories to disable for the install/update operation. These repos will
        not persist beyond the transaction. When specifying multiple repos, separate them with
        a ",".
        [Default: (null)]

- download_dir
        Specifies an alternate directory to store packages.
        Has an effect only if `download_only' is specified.
        [Default: (null)]
        type: str
        version_added: 2.8

- download_only
        Only download the packages, do not install them.
        [Default: no]
        type: bool
        version_added: 2.7

- enable_plugin
        `Plugin' name to enable for the install/update operation. The enabled plugin will not
        persist beyond the transaction.
        [Default: (null)]
        version_added: 2.7

- enablerepo
        `Repoid' of repositories to enable for the install/update operation. These repos will
        not persist beyond the transaction. When specifying multiple repos, separate them with
        a ",".
        [Default: (null)]

- exclude
        Package name(s) to exclude when state=present, or latest. This can be a list or a comma
        separated string.
        [Default: (null)]
        version_added: 2.7

- install_repoquery
        This is effectively a no-op in DNF as it is not needed with DNF, but is an accepted
        parameter for feature parity/compatibility with the `yum' module.
        [Default: yes]
        type: bool
        version_added: 2.7

- install_weak_deps
        Will also install all packages linked by a weak dependency relation.
        [Default: yes]
        type: bool
        version_added: 2.8

- installroot
        Specifies an alternative installroot, relative to which all packages will be installed.
        [Default: /]
        version_added: 2.3

- list
        Various (non-idempotent) commands for usage with `/usr/bin/ansible' and `not'
        playbooks. See examples.
        [Default: (null)]

- lock_timeout
        Amount of time to wait for the dnf lockfile to be freed.
        [Default: 30]
        type: int
        version_added: 2.8

= name
        A package name or package specifier with version, like `name-1.0'. When using
        state=latest, this can be '*' which means run: dnf -y update. You can also pass a url
        or a local path to a rpm file. To operate on several packages this can accept a comma
        separated string of packages or a list of packages.
        (Aliases: pkg)
        elements: str
        type: list

- releasever
        Specifies an alternative release from which all packages will be installed.
        [Default: (null)]
        version_added: 2.6

- security
        If set to `yes', and `state=latest' then only installs updates that have been marked
        security related.
        [Default: no]
        type: bool
        version_added: 2.7

- skip_broken
        Skip packages with broken dependencies(devsolve) and are causing problems.
        [Default: no]
        type: bool
        version_added: 2.7

- state
        Whether to install (`present', `latest'), or remove (`absent') a package.
        Default is `None', however in effect the default action is `present' unless the
        `autoremove' option is enabled for this module, then `absent' is inferred.
        (Choices: absent, present, installed, removed, latest)[Default: (null)]

- update_cache
        Force dnf to check if cache is out of date and redownload if needed. Has an effect only
        if state is `present' or `latest'.
        (Aliases: expire-cache)[Default: no]
        type: bool
        version_added: 2.7

- update_only
        When using latest, only update installed packages. Do not install packages.
        Has an effect only if state is `latest'
        [Default: no]
       type: bool
        version_added: 2.7

- validate_certs
        This only applies if using a https url as the source of the rpm. e.g. for localinstall.
        If set to `no', the SSL certificates will not be validated.
        This should only set to `no' used on personally controlled sites using self-signed
        certificates as it avoids verifying the source site.
        [Default: yes]
        type: bool
        version_added: 2.7


NOTES:
      * When used with a `loop:` each package will be processed individually, it is much
        more efficient to pass the list directly to the `name` option.
      * Group removal doesn't work if the group was installed with Ansible because
        upstream dnf's API doesn't properly mark groups as installed, therefore upon
        removal the module is unable to detect that the group is installed
        (https://bugzilla.redhat.com/show_bug.cgi?id=1620324)


REQUIREMENTS:  python >= 2.6, python-dnf, for the autoremove option you need dnf >= 2.0.1"

AUTHOR: Igor Gnatenko (@ignatenkobrain) <i.gnatenko.brain@gmail.com>, Cristian van Ee (@DJMuggs) <cristian at cvee.org>
        METADATA:
          status:
          - stableinterface
          supported_by: core
        

EXAMPLES:

- name: install the latest version of Apache
  dnf:
    name: httpd
    state: latest

- name: install the latest version of Apache and MariaDB
  dnf:
    name:
      - httpd
     - mariadb-server
    state: latest

- name: remove the Apache package
  dnf:
    name: httpd
    state: absent

- name: install the latest version of Apache from the testing repo
  dnf:
    name: httpd
    enablerepo: testing
    state: present

- name: upgrade all packages
  dnf:
    name: "*"
    state: latest

- name: install the nginx rpm from a remote repo
  dnf:
    name: 'http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm'
    state: present

- name: install nginx rpm from a local file
  dnf:
    name: /usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm
    state: present

- name: install the 'Development tools' package group
  dnf:
    name: '@Development tools'
    state: present

- name: Autoremove unneeded packages installed as dependencies
  dnf:
    autoremove: yes

- name: Uninstall httpd but keep its dependencies
  dnf:
    name: httpd
    state: absent
    autoremove: no

- name: install a modularity appstream with defined stream and profile
  dnf:
    name: '@postgresql:9.6/client'
    state: present

- name: install a modularity appstream with defined stream
  dnf:
    name: '@postgresql:9.6'
    state: present

- name: install a modularity appstream with defined profile
  dnf:
    name: '@postgresql/client'
    state: present

Installation

Nachdem wir uns nun eigehend mit den Grundlagen zu Ansible beschäftigt haben, wollen wir nun noch das eigentliche Paket ansible installieren.

Die Installation von Ansible auf unserer Admin-Workstation, von der wir unsere Zielsysteme aus orchestrieren wollen, gestaltet sich dank unseres Paket-Managers dnf bzw. yum entsprechend einfach. Im Grunde reicht dabei die Installation des Paketes ansible.

 # dnf install ansible  -y

bzw.

 $ sudo apt install ansible -y

oder

 # zyppr in ansible -y

RPM-Paket ansible

Einen Überblick über das Paket kann man mit Hilfe des Befehls rpm -qi sich anzeigen lassen.

 # rpm -qi ansible
Name        : ansible
Version     : 2.9.13
Release     : 1.fc32
Architecture: noarch
Install Date: Sa 03 Okt 2020 10:41:49 CEST
Group       : Unspecified
Size        : 102582504
License     : GPLv3+
Signature   : RSA/SHA256, Fr 04 Sep 2020 00:23:43 CEST, Key ID 6c13026d12c944d0
Source RPM  : ansible-2.9.13-1.fc32.src.rpm
Build Date  : Do 03 Sep 2020 02:10:52 CEST
Build Host  : buildvm-ppc64le-38.iad2.fedoraproject.org
Packager    : Fedora Project
Vendor      : Fedora Project
URL         : http://ansible.com
Bug URL     : https://bugz.fedoraproject.org/ansible
Summary     : SSH-based configuration management, deployment, and task execution system
Description :
Ansible is a radically simple model-driven configuration management,
multi-node deployment, and remote task execution system. Ansible works
over SSH and does not require any software or daemons to be installed
on remote nodes. Extension modules can be written in any language and
are transferred to managed machines automatically.

Interessieren wir uns für eine Datei- und Ordnerliste, werden wir wie immer mit folgendem Aufruf fündig:

 # rpm -qil ansible

weitere Schritte zur Installation und Konfiguration

Nachdem wir uns nun eingehend mit den Grundlagen und auch schon das benötigte Programmpaket auf unserer Admin-Workstation zur Orchestrierung installiert haben, machen wir uns nun an die Konfiguration von Ansible und wagen uns an die ersten Playbooks im Kapitel Erste Schritte Rund um Ansible heran.

Links

1)
Yet Another Markup Language