* Es gibt schon eine Steite [[ansible]] ======= Was es kann/ist ======= * Automatisiert administrative Vorgänge auf Systemen * Linux, Windows, Netzwerkgeräte * benötigt keinen Agenten auf dem Zielsystem * für komplexere Aufgaben werden ansible modules übertragen und ausgeführt und anschließend wieder gelöscht * sind im Prinzip Code-Schnipsel/Scripte * Anweisungen werden in Playbooks abgelegt * yaml-Files die definieren was passieren soll * dadurch Ablegen in git möglich * Inventare die leicht zu verändern sind definieren auf welchen Maschinen Aktionen ausgeführt werden sollen * benutzt Python * Bestandteile sind idempotent * ein Play definiert einen Zustand in dem ein System sein soll * ist es schon in dem Zustand wird es nicht geändert * ein Play kann beliebig oft aufgerufen werden für ein System ohne etwas kaputt zu machen * gleiches gilt für Tasks (einzelne Schritte) und Modules die als Teil von Tasks aufgerufen werden ====== Begriffe ====== ^Begriff ^Beschreibung ^ |Controller|Der Rechner auf dem Ansible läuft| |Managed Hosts/Inventory Hosts|Die Rechner auf denen Aktionen ausgeführt werden| |Plugins|Erweiterungen von Ansible| |Inventory|Liste von Maschinen, fix als Datei oder dynamisch erstellt| |Playbook|Eine Sammlung von Plays aka. Scripten| |Plays|Einzelne Scripte| |Tasks|Einzelne Aufgaben innerhalb eines Plays| |Modules|Eine Aufgabe die im Rahmen eines Tasks ausgeführt wird \\ Praktisch handelt es sich um parametrisierte Scripte in Python, oder PowerShell oder einer anderen Sprache geschrieben| ====== Aufbau ====== * Ansible bringt Plugins mit * inventory -> zur Inventory-Verwaltung * modules -> Komplexe Aktionen die auf den Inventory Hosts ausgeführt werden können * connection -> Kümmern sich um die Verbindungen * become -> Verwaltet die Privilegien -> also zum Beispiel sudo-Plugin * vars -> Benutzung von Variablen in den ansible Playbooks * lookup -> Um Daten von anderen Quellen abzurufen (zum Beispiel Datenbanken, LDAP usw.) * callback -> Andere Funktionen aufrufen bei Erfolg/Miserfolg ====== Dateien ====== ===== ansible.cfg ===== * Konfigurationsdatei auf dem Controller * ini-Dateiformat * per ansible -v kann man sehen welche Datei die mit der höchsten Priorität ist * so wie einige andere Pfade * Die Dateien werden ihrer Piorität nach abgearbeitet (aufsteigende Priorität), nachfolgende Dateien überschreiben ggf. Werte der vorhergehenden * /etc/ansible/ansible.cfg * ~/.ansible.cfg * ./ansible.cfg -> ansible.cfg im aktuellen Verzeichnis * $ANSIBLE_CONFIG= -> eine Umgebungsvariable die auf eine ansible.cfg verweist [defaults] inventory = ./inventory remote_user = myuser ask_pass = false [privilege_escalation] become = True become_ask_pass = False become_user = root become_method = sudo * Datei besteht aus Sektionen * defaults definiert die Defaults -> wenn im Play nicht anders definiert * inventory -> wo das Inventory zu finden ist * remote_user -> User der zum Login genutzt wird * ask_pass -> Ob nach einem Passwort gefragt werden soll * privilege_escalation * Soll der Benutzer nach dem Login gewechselt werden (in der Regel zu einem mit höheren Rechten) * become -> Aktiviert/Deaktiviert die Eskalation * become_ask_pass -> Ob nach einem Passwort gefragt werden soll * become_method -> Die Methode über die die höheren Privilegien erreicht werden sollen (in diesem Fall sudo) ====== inventory ====== * Daher kommen die Managed Hosts gegen die ein Play ausgeführt werden soll * kann eine Datei sein (es gibt auch Plugins für andere Quellen) * kann ein Verzeichnis mit mehreren Dateien sein * die Dateien können verschiedene Formate haben oder sogar Scripte sein * hat keinen spezifischen Namen * ist im ini-Format oder yaml-Format (sind die unterstützten Default-Formate -> weitere gehen über Plugins, auch andere Quellen) * yaml-Format ist besser verständlich/einfacher zu erfassen Als ini-Datei: 10.1.55.13 [Mailserver] mail1.somewhere.de mail2.somewhere.de [DNSServer] ns1.somewhere.de ns2.somewhere.de [webserver] web[1:10].somweher.de [production:children] DNSServer Mailserver [debianserver] mail1.somewhere.de 10.1.53.13 * ManagedHost können in oder außerhalb von Gruppen stehen * eine Gruppe ist ein Abschnitt in einer ini-Datei mit [Name] eingeleitet * Managed Host-Namen können Bereiche beinhalten * siehe web[1:10] -> dies erzeugt eine Liste von Hosts mit den Namen web1.somewhere.de, web2.somewhere.de usw. * Gruppen können aus anderen Gruppen bestehen * Gruppenname hat dann den Suffix :children * siehe [production:children] * in der Gruppe stehen dann die Namen der Kind-Gruppen * Managed Hosts können Teil von mehreren Gruppen sein * zum Beispiel geordnet nach Funktion, Ort, Betriebssystem usw. Als yaml-File: ungrouped: hosts: 10.1.55.13: Mailserver: hosts: mail1.somewhere.de: mail2.somewhere.de: DNSServer: hosts: ns1.somewhere.de: ns2.somewhere.de: webserver: hosts: web[1:10].somweher.de: production: children: DNSServer: Mailserver: debianserver: hosts: mail1.somewhere.de: 10.1.53.13: mixed: children: DNSServer: hosts: 10.1.35.55 * im Gegensatz zu ini-Dateien können Children und Hosts in der gleichen Gruppe verwendet werden (siehe mixed-Gruppe) * Es gibt 2 impliziert Gruppen * all -> alle Einträge * ungrouped -> Einträge die keiner Gruppe angehören * spielt nur bei ini-Dateien eine Rolle, bei yml-Dateien gibt es keine Einträge außerhalb von Gruppen **ansible-inventory** ist das zu den Inventories gehörende Werkzeug. ansible-inventory -i Actions: * --list -> gebe das gesamte Inventory aus. Wird genutzt um Inventory an ansible zu übergeben * --graph -> gebe die Inventory-Struktur als Graph aus * --host -> gebe die Daten über einen bestimmten Managed Host aus ^Option ^Beschreibung ^ |--yaml %%|%% --toml | Gibt die Daten wahlweise im Yaml- oder TOML-Format aus. \\ JSON ist das Format wenn nichts angegeben wird. \\ \\ Dadurch lassen sich Dateien auch konvertieren| ====== playbook ====== * wird in yaml-Dateien definiert * ein Playbook definiert was gemacht werden soll * Plays werden seriell (in der Reihenfolge wie sie dort stehen) ausgeführt * das gilt auch für Tasks - name: Name of play 1 hosts: group_or_name_of_hosts tasks: - name: NameofTask1 modulename1: parameter1: value1 parameter2: value2 - name: NameofTask2 modulename2: parameter1: value1 parameter2: value2 - name: Name of play2 hosts: group_or_name_of_hosts tasks: - name: NameofTask1 modulename2: parameter1: value1 parameter2: value2 * Playbook ist eine Liste von Plays * jedes Play ist ein Dictionary * name -> optionaler Name für das Play * hostst -> Ein Host, eine Liste (yaml-Liste) oder eine Gruppe oder Liste von Gruppen (aus dem Inventory) für den dieses Play gültig ist * Tasks -> eine Liste von Tasks die ausgeführt werden sollen * Name -> optional ein Name für den auszüführenden Task * Modulename -> Name des Modules das den Task ausführen soll * Module kann man hier finden: https://docs.ansible.com/ansible/latest/collections/index_module.html * Dictionary definiert Parameter für das Modul ===== ansible-playbook ===== ansible-playbook Führt das entsprechende Playbook aus ansible-playbook ^Option ^Beschreibung ^ |--check-syntax|Prüft die Syntax des Playbooks| ====== Handlers ====== * ermöglichen Aktionen nur auszuführen wenn ein Task in einer Aktion resultiert * also wenn der Zustand den der Task erwartet nicht gegeben ist * werden erst nach dem **alle** Tasks ausgeführt wurden ausgeführt * Reihenfolge ist wie sie in der handlers-Sektion stehen * Jeder Handler wird pro System maximal 1 mal ausgeführt - name: My Play hosts: hosta force_handlers: true tasks: - name: Get kernel notify: Reboot after kernel installation ansible.builtin.apt: name: linux-image-amd64 state: latest handlers: - name: Reboot after kernel installation ansible.builtin.reboot: * Es wird geprüft ob die letztet Version des Paketes linux-image-amd64 installiert ist * wenn nicht wird er installiert * Wenn **alle** Tasks abgearbeitet sind wird die Handler-Sektion der Reihe nach abgearbeitet * der "get Kernel" task sendet eine Notification an Handler "Reboot after kernel installation" wenn der Task tatsächlich etwas tun musste (also nicht wenn der Kernel bereits vorhandeln war) * force_handlers -> Wenn true werden handler auch ausgeführt obwohl ein nachfolgender Task im play fehlgeschlagen ist. * Hat task A ein Notify und Task B schlägt fehl wird normalerweise der Handler von A nicht ausgeführt (trotz Notify). force_handlers sorgt dafür das Handler auch ausgeführt werden (die die eine Notification bis zu dem Zeitpunkt haben) wenn nicht alle Tasks erfolgreich sind * notify -> sendet eine Nachricht an einen Handler wenn der Task tatsächlich etwas ändert (state changed), die Bedingung die der Task sicherstellen soll also nicht gegeben war * state: latest stellt sicher das die letzte Version eines Paketes installiert ist * handlers: Liste von Modulen die aufgerufen werden wenn ein Task eine Notification für sie gesendet hat. * Die Liste wird erst **nach** dem **alle** Tasks im Task-Attribute des Plays abgearbeitet sind aufgerufen * Wenn es also 2 Tasks im Play gibt und der erste eine Notification an einen Handler sendet, wird erst noch Task 2 abgearbeitet, bevor der Handler aufgerufen wird * Handler werden nur für die Hosts aufgerufen wo ein Task "changes" vorgenommen hat * Handler werden nach der Reihenfolge abgearbeitet wie sie in der handler-Sektion stehen * aber jeweils nur einmal pro System (auch wenn mehrere Tasks für das gleiche System und den gleichen Handler Notifies gesendet haben) ====== When ====== * Bedingung * Block oder Task wird nur ausgeführt wenn die Bedingung erfüllt ist * Bedingung ist ein Jinja-2-Ausdruck, ohne die {} - name: My first play tasks: - name: First task hosts: hostA when: ansible_facts['os_family'] == "Debian" ansible.builtin.apt: name: neovim state: latest * Führt den Task nur aus wenn die os_family in den Ansible-Facts Debian ist * kann Sinn machen wenn man zum Beispiel verschiedene Systeme mit verschiedenen Betriebssystemen hat und deswegen verschiedene Module verwenden muss ====== Blocks ====== * gruppieren Tasks * Statements des Blocks werden vererbt an die Tasks -> z.B. Become * when-Statements gelten für den gesamten Block usw. - name: My first play hosts: myhosts tasks: - name: First Block when: ansible_facts['os_family'] == "Debian" become: true become_method: sudo block: - name: First task ansible.builtin.apt: name: neovim state: latest update_cache: True - name: Make a temporary file ansible.builtin.tempfile: prefix: myfile * die Tasks im Block werden nur ausgeführt wenn die os_family=="Debian" ist * when-Statement auf Block-Level * Alle Tasks im Block werden mit root-Rechten ausgeführt * become: true und become_method: sudo auf Blocklevel * Tasks in einem Block erben die Statements auf Blockebene ===== Rescue ===== * Wird ausgeführt wenn einer der Tasks im Block fehlschlägt * wenn ein Task fehlschlägt werden die nachfolgenden Task normalerweise nicht mehr ausgeführt * dient zum Beispiel um Aktionen rückgängig zu machen und das System nicht halbkonfiguriert zurückzulassen * rescue-Attribute enthält Liste von Tasks - name: My first play hosts: myhosts tasks: - name: First Block when: ansible_facts['os_family'] == "Debian" become: true become_method: sudo block: - name: First task ansible.builtin.apt: name: neovim state: latest update_cache: True - name: Make a temporary file ansible.builtin.tempfile: prefix: myfile rescue: - name: Remove the vim package ansible.builtin.apt: name: neovim state: absent purg: true * Im Falle eines Fehlers in block: würde das vim-Paket in rescue-Attribut deinstalliert ===== Always ===== * wird immer ausgeführt * egal ob die Tasks im Block fehlschlagen oder erfolgreich sind - name: My first play hosts: myhosts tasks: - name: First Block when: ansible_facts['os_family'] == "Debian" become: true become_method: sudo block: - name: First task ansible.builtin.apt: name: neovim state: latest update_cache: True - name: Make a temporary file ansible.builtin.tempfile: prefix: myfile always: - name: Clear retrieved packages ansible.builtin.apt: clean: true * Task "Clear retrieved packages" wird immer ausgeführt, unabhängig vom Erfolg oder Fehlschlagen der Tasks im block ====== Tags ====== * Ermöglichen das ausführen nur bestimmter Teile * können auf Handler, Blocks, Plays, Tasks, Roles, includes und imports angewendet werden Folgende Werte sind **reserviert**/haben eine besondere Bedeutung und können in ansible-Dateien auftauchen: * Keyword tags * Wert ist ein einzelnes Keyword oder eine Liste von Keywords ^Tag ^Beschreibung ^ |never|Führe die Statements niemals aus. \\ \\Es sei denn "never" wird in der tags-Option explizit angegeben oder anderer Tag in der Tag-Liste für dieses Element wurde explizit angegeben. \\ Auch nicht bei Angabe von "all" oder wenn kein Tag beim Aufruf von ansible-playbook angegeben | |always | führt den Statements immer aus. \\ \\ Egal welcher Tag auf der Kommandozeile angegeben wurde. \\ Ausnahme --skip-tags always ist as Parameter angegeben| |kein Tag|Wird ausgeführt wenn keine Tags auf der Kommandozeile ausgewählt wurden oder all oder untagged| |Benutzerspezifischer Tag|Wird ausgeführt wenn der **ansible-playbook** hat folgende Parameter für Tags: * --tags * ansible-playbook --tags Tag1,Tag2 playbook.yml * definiert eine Liste von Tags die ausgeführt werden soll * nur statements die diesen Tag haben werden ausgeführt (oder wenn der Tag "always" ist) * --skip-tags * ansible-playbook --skip-tags Tag1,Tag2 playbook.yml * definiert eine Liste von Tags die geskipped (übersprungen) werden sollen * alle Tags (und Tasks die keinen Tag haben) die nicht in der Liste stehen werden ausgeführt * wird --tags und --skip-tags kombiniert, hat --skip-tags Vorrang * hat ein Task ein Tag welches im tags-Parameter angegeben wurde und ein Tag welches in skip-tags steht wird der Task **nicht** ausgeführt * -> skip-tags hat Vorrang Folgende Tags gibt es: ^Tag ^Beschreibung ^ |Never|Kann in --tags angegeben werden um Tags auszuführen die mit "never" markiert sind| |all|Alle Tags, inkl. Task die keine Tags haben. \\ Aber nicht die mit "never" markiert sind. | |tagged|Alle Tasks aus die ein tag haben. \\ Außer mit "never" getagte| |untagged|Nur Tasks die keinen Tag haben| |Custom-Tag|Ein beliebiges Tag| |ohne --tags|Alles (auch getaggte), außer in der tags-Liste steht "never" (auch dann nicht wenn noch andere Tags vorkommen| **Einfaches Tag** - name: My first play hosts: myhosts tasks - name: Install vim tags: - vim ansible.builtin.apt: name: neovim state: latest update_cache: True - name: Make a temporary file ansible.builtin.tempfile: prefix: myfile Task "Install vim" würde ausgeführt wenn * kein Tag angegeben wurde * --tags vim angegeben wurde * --tags tagged angeben wurde * --tags all angeben wurde ** Tag + never:** - name: My first play hosts: myhosts tasks - name: Install vim tags: - vim - never ansible.builtin.apt: name: neovim state: latest update_cache: True - name: Make a temporary file ansible.builtin.tempfile: prefix: myfile Task "Install vim" würde ausgeführt wenn * --tags vim angegeben wurde * wegen "never" würde es nicht ausgeführt * wenn kein tag-Option angegeben wurde * wenn "all" in der Tag-Option steht * wenn "tagged" in der Tag-Option steht ** always:** - name: My first play hosts: myhosts tasks - name: Install vim tags: - always ansible.builtin.apt: name: neovim state: latest update_cache: True - name: Make a temporary file ansible.builtin.tempfile: prefix: myfile Task "Install vim" würde immer ausgeführt (egal welcher Tag, egal ob kein Tag). \\ Wir nur nicht ausgeführt wenn --skip-tags always ====== Modules ====== * werden von Tasks aufgerufen und sind die eigentlichen Aktionen * sind idempotent * sie prüfen vorher ob der Status den sie herstellen sollen schon gegeben sind und tun dann nichts * letzten Endes stellen sie sicher das ein bestimmter Zustand gegeben ist (zum Beispiel ein Dienst gestartet) * können hier gefunden werden https://galaxy.ansible.com/ui/ * Dokumentation findet man hier: https://docs.ansible.com/ansible/2.8/modules/list_of_all_modules.html * Version in URL beachten ===== Module ===== * Einige öfter genutzte Module ^Modul ^Beschreibung ^ |copy|Kopiert vom ansible-Controller (lokale Maschine) auf einen Managed Host oder innerhalb eines Managed Hosts| |fetch|Kopiert Dateien von einem managed Host auf den Ansible-Controller| ===== ansible-doc ===== * Dokumentation für installierte Module ^Befehl ^Beschreibung ^ ||Gibt die Dokumentation (und die Parameter) für ein installiertes Modul aus| |-l -t module|Erlaubt die Angabe eines Modul-Typs| ====== Variablen ====== * können an verschiedenen Stellen und mit verschiedenen Gültigkeitsbereichen definiert werden * abhängig davon wo sie definiert werden überschreiben sie ggf. andere Definitionen * https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html **Im Inventory**: mygroup: vars: myvar: 5 hosts: 85.206.62.161: myvar: "Coming from 56.108.82.247 inventory host config" 57.17.117.156: * Die vars-Sektion unterhalb der Gruppe definiert die Variable (myvar) für alle Hosts dieser Gruppe * myvar unterhalb des Hosts definiert myvar für diesen Host-Eintrag * das überschreibt für diesen Host den Wert der in der Gruppe definiert ist. Während für 57.17.117.156 weiterhin der Wert der Gruppe genutzt wird **In var-Directories**: * hat Vorrang vor Inventory-Einträgen * unterhalb des Verzeichnisses wo das playbook liegt * für Gruppen * group_vars//beliebigerDateiname.yml * group_vars/dnsservers/vars.yml * für einzelne Hosts * host_vars//belieberdateiname.yml * host_vars/192.168.2.13/vars.yml Inhalt der Datei sind key-Value-Pairs: : package: apache2 **In Playbooks**: * Plays können eine vars-Sektion haben - name: Play-Name hosts: myhostlist vars: myvar: myvalue tasks: - name: sometaskt ansible.builtin.debug: msg: "{{myvar}}" * das Play hat ein vars-Dictionary in dem myvar definiert wird * Variablen können über Jinja2-Syntax genutzt werden {{Variable}} * es empfiehlt sich wenn sie in Strings genutzt werden diese in "" zu setzen - name: Play-Name hosts: myhostlist tasks: - name: sometask vars: myvar: someothervalue ansible.builtin.debug: msg: "{{myvar}}" ====== Roles ====== * Fassen Tasks zusammen um eine größere Aufgabe zu erledigen * Machen die Wiederverwendbarkeit von Abläufen einfacher * können aus Playbook aufgerufen werden * Konfiguration erfolgt über Variablen - name: Play-Name hosts: myhostlist roles: - ===== ansible-galaxy ===== * Tool zum Verwalten von Rollen ====== Collections ====== Roles und Modules sind in Collections zusammengefasst, die heruntergeladen werden können (von ansible oder woanders). Wenn ein Modul: ansible.builtin.debug heißt, dann ist "ansible.builtin" die Collection. ===== ansible-galaxy ===== * Ist das Tool zum verwalten und managen von Collections ^Befehl ^Beschreibung ^ |install |Installiert eine bestimmte Collection| ====== Plugins ====== * Plugins sind Erweiterungen von Ansible * Module sind eine Unterkategorie von Plugins * befinden sich in Collections und können über ansible-galaxy installiert werden * können hier gefunden werden https://galaxy.ansible.com/ui/ * Dokumentation findet man hier: https://docs.ansible.com/ansible/2.8/modules/list_of_all_modules.html * Version in URL beachten ===== ansible-doc ===== * Liefert Dokumentation für installierte Module ^Option ^Beschreibung ^ |-l|Listet alle installierten Plugins| |-l -t |Listet alle Plugins eines bestimmten Typs. \\ \\ Zum Beispiel: * module -> Listet alle Module * inventory -> alle Inventory-Plugins * become -> alle Become-Plugins | ====== Befehle ====== ^Befehl ^Beschreibung ^ |ansible-config|Alles was mit der ansible.cfg zu tun hat. \\ * meisten Befehle kennen -t all * listet zustätzlich die Konfigurationsparameter für Plugins (mit all für alle) ^Option ^Beschreibung^ |ansible-config list|Listet alle möglichen Konfigurationsparameter + einer kurzen Erklärung auf.| |ansible-config dump|Dumped die aktuell aktive Konfiguration| |ansible-config init|Gibt ein Config-File mit allen möglichen Konfigurationsoptionen aus. \\ Per Default auf das Terminal, per > kann es in eine Datei geschrieben werden. \\ \\ * -t all -> gibt zusätzlich auch alle Konfig-Optionen für die Plugins mit aus| * --disabled -> gibt alle Optionen kommentiert aus (also deaktiviert) | |