centos:ansible:detail

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
Letzte ÜberarbeitungBeide Seiten der Revision
centos:ansible:detail [12.01.2020 12:25. ] – [Komplexere und größere Umgebungen] djangocentos:ansible:detail [24.09.2022 14:12. ] – [Module] django
Zeile 1: Zeile 1:
 ====== Ansible - Erweiterte Konfigurationsbeispiele ====== ====== Ansible - Erweiterte Konfigurationsbeispiele ======
-{{:centos:ansible:ansible_logo.png?nolink&125|Bild: Ansible Logo}} \\ \\ 
  
-Nachdem wir uns bereits eingehend mit den **[[centos:ansible:start#grundlagen|Grundlagen]]**, mit der **[[centos:ansible:start#installation|Installation von Ansible]]** und auch schon mit der Grundkonfiguration beschäftigt sowie erste Erfahrungen mit **[[centos:ansible:first#playbook_-_beispiele|Playbooks]]** gesammelt haben, wollen wir uns nun mit der tiefergehenden Konfiguration von Ansible beschäftigen. +<WRAP center round alert 60%> 
 +Artikel befindet sich aktuell in der Überarbeitung! 
 +</WRAP>
  
-===== Inventory ===== 
-Zur Verwaltung/Inventarisierung  von mehreren Knoten oder Hosts in unserer Infrastrukturumgebung verwendet Ansible Listen oder eine Gruppe von Listen, die man als **Inventory** bezeichnet. Im einfachsten Fall beschreibt solch eine Inventory-Datei lediglich Hosts und/oder deren Hostnamen  bzw. IP-Adressen. Auf der anderen Seite kann man aber auch komplexe Landschaften abbilden und Eigenschaften einzelnen Hosts und /oider Gruppe zuordnen. 
  
-Im Kapitel **[[centos:ansible:first#remote_user-anpassung_via_inventory_hostsyml|erweiterte Konfiguration - Anpassungen "Inventory hosts.yml"]]** hatten wir uns schon einmal kurz mit dem Thema **Inventory** beschäftigt. In den nachfolgenden Beispielen wollen wir  nun intensiver auf Details dazu eingehen. 
  
-Im Kapitel **[[https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html|How to build your inventory]]** der Ansible-Onlinedoku finden sich dazu vile tiefergehende Informationen.+==== Konfigurationsbeispiel ==== 
 +In folgendem Konfigurationsbeispiel wollen wir uns zu folgendem Szenario eine handelbare Lösung genauer betrachten. Wir gehen dabei von folgendem Einsatzszenario aus:
  
-{{page>centos:ansible:hosts&nofooter&showheader}}+=== Aufgabenstellung === 
 +Es ist ein Webserver mit Hilfe von Ansible zu erstellen. Am Host soll sich der verantwortliche WEB-Admin **ruben** anmelden können und der Host soll sich des NTP-Servers im der eigenen Zone bedienen. Dies sind Standardkonfigurationsaufgaben, die auf jedem Server in der betreffenden Sicherheitszonezutreffen. Nach der Installation des Webserver-Daemon **apache** soll dieser konfiguriert, die initiale Homepage **//Hello World//** installiert unde zum Schluß der Webserver gestartet werden.
  
  
-==== ~/ansible/hosts.yml ==== +=== Lösung === 
-Im Kapitel **[[centos:ansible:first#remote_user-anpassung_via_inventory_hostsyml|erweiterte Konfiguration - Anpassungen "Inventory hosts.yml"]]** hatten wir uns schon einmal kurz mit dem Thema **Inventory** beschäftigt+Als erstes zerlegen wir die Aufgabenstellung in einzelne Arbeitspakete und unterteilen diese Pakete in einzelne Aufgaben, als da wären: 
 +  * **Basiskonfiguration** 
 +    * Gruppe für den Webentwickler **ruben** anlegen (unter CentOS ist dabei die Gruppe gleich dem Benutzernamen). 
 +    * User(konto) für den Webentwickler **ruben** anlegen. 
 +    * Initiales Passwort für den Webentwickler **ruben** setzen. 
 +    * **NTP**-Client 
 +      * Installation des NTP-clients **chrony** 
 +      * Sichern der originalen chrony-Konfigurationsdatei 
 +      * Konfiguration von chrony 
 +      * Starten des NTP-Clients/-Daemon und Sicherstellen dass dieser auch bei einem Systemneustart gestartet wird. 
 +  * **Host-/Aufgabenspezifische Installation:** Apache-Webserver 
 +    Installation des **http**-Daemon 
 +    * Sichern der originalen Apache-Konfigurationsdatei 
 +    * Konfigurieren des Apache Webservers 
 +    * Kopieren der initialen Webseite nach **''DOCUMENT_ROOT''** des Apache-Webservers 
 +    * Starten des Webserver/-Daemon und sicherstellen dass dieser auch bei einem Systemneustart gestartet wird.
  
-In der Ansible-Konfigurationsdatei **''/etc/ansible/ansible.cfg''** zeigt zu Beginn der default-Eintrag auf die vorgenannte Datei **[[#etc_ansible_hosts|/etc/ansible/hosts]]**.+Um möglichst für die Zukunft flexibel zu sein, werden wir unser Ansible Playbook oder bessere gesagt den darunter liogenden Code, möglichst flexibel halten. Das bedeutet, dass wir sowohl für die Grundkonfiguration (User/Gruppe anlegen, wie installation des Chrony-Daemon) wie auch für die spätere Host-/Aufgabenspezifische Installation des Webservers (Apache) eigene Rollen defionieren werdenSo können wir später die Rollen mühelos erweitern, wenn wir z.B. weitere Dienste wie z.B. einen PHP-Interpreter oder die zum Apachen zugehörige TLS-Konfiguration vornehmen werden.
  
-<code> ...+Folgende Struktur soll definiert werden: 
 +  * **''site.yml''** 
 +    * beinhaltet alle Site-spezifischen Playbooks, wie z.B. 
 +      * Datenbank **''db.yml''** (//spätere erweiterte Konfiguration//
 +      * Mailserver **''postfix.yml''** (//spätere erweiterte Konfiguration//
 +      * ... 
 +      * Webserver **''web.yml''** 
 +        * sein zugehöriges Playbook **''web.yml''** bedient sich der Rollen: 
 +          * **''base''** über die die Benutzeranlage erfolgt 
 +          * **''chrony''** mit Hilfe deren die NTP-Client-Konfiguration erlediggt wird 
 +          * **''apache''** Installation und Konfiguration des Apache Webservers mit Hilfe von **''tasks''**, **''files''** und **''handlers''**     
  
-[defaults]+----
  
-some basic default values...+== Systemweite Host/Playbook-Definition : site.yml == 
 +Zunächst befüllen/editieren wir die Konfigurationsdatei **''site.yml''**, die wir automatisiert bei der Grundkonfiguration von **[[centos:ansible:first#ansibledirectory_layout|Ansibles Directory Layout]]** erzeugt hatten. Diese Datei wird später alle Definitionen unserer Systemumgebung enthalten, also nicht nur die für den Apache-Webserver, sondern auch für den Datenbank-, Mail- und sonstige Server. Die spezisfischen Playbooks werden dann hier nur noch includiert bzwimportiert. 
 +   $ vim ~/ansible/site.yml 
  
-#inventory      = /etc/ansible/hosts +<file yml ~/ansible/site.yml>--- # Start des systemweiten Playbooks site.yml 
-... +- import_playbook: web.yml # Playbook zum Konfigurieren unseres Webservers einbinden
-</code>+
  
-Unsere erweiterte YAML-Konfigurationsdatei für die Hosts wolen wir aber künftig in der Ansible-Administationsumgebung unseres Admin-Users vorhalten und pflegenIm Beispiel unseres Adminusers **django** wäre dies entsprechend der Pfad **''/home/django/ansible/hosts.yml''**+... # Ende unseres systemweiten Playbooks 
 +</file>
  
-Wir hinterlegen also dort, dass zukünftig die Inventory-Datei **''hosts.yml''** eingelesen und ausgewertet werden soll. +----
-   # vim /etc/ansible/ansible.cfg+
  
-<code>[defaults]+== Webserver Host/Playbook-Definition : web.yml == 
 +Für die Konfiguration des Webservers an sich verwenden wir dann die Konfigurationsdatei **''web.yml''**; die wir in der zuvor angelegten systemweiten Konfigurationsdatei **''site.yml''** includiert hatten. Da die Konfiguration auf allen WEB-Hosts erfolgen soll, geben wir beim Parametewr **''hosts''** den Namen der Hostgruppe aus unserer Inventory-Definition an. Bei der Definition der Rollen geben wir die drei **''roles''** an, die wir in unseren zuvor angestellten Überlegungen gewählt hatten. 
 +   $ vim ~/ansible/web.yml 
  
-some basic default values...+<file yml web.yml>--- Start des Playbooks für den Web-Server 
 +- hosts: www
  
-# Django 2020-01-01  +  roles: 
-default: #inventory      = /etc/ansible/hosts +    base   # Basiskonfiguration (User anlegen) 
-inventory      = /home/django/ansible/hosts.yml +    - chrony Installation und Konfiguration NTP-Client 
-</code>+    - www    # Installation und Konfiguration Apache Webserver
  
-=== inventory Beispiel === +... # Start des Playbooks für den Web-Server 
-Dort legen wir uns unsere erweiterte Host-Datei im YAML-Format an. +</file>
-   $ vim /home/django/ansible/hosts.yml>+
  
-<file bash /home/django/ansible/hosts.yml>--- #YAML start syntax (optional)  +Unser Kopiervorlage **''common''** für die Rollen kopieren wir nun für die gewählten Arbeitspakete (**roles**)als erstes also für  die Rolle **''base''**, bei der wir den verantwortlichen Web-Admin anlegen werden
-all: +   $ cd ~/ansible/roles 
-  hosts:                                                                       # nicht zugeordnete Hosts +   $ cp -avr common/ base/
-    n3r0.intra.nausch.org: +
-    g33k.intra.nausch.org: +
-  children:                                                                    # Untermenge/-gruppe aller Hosts  +
-    centos8:                                                                   # Gruppe der definierten CentOS 8 Hosts +
-      vars:                                                                    # Variablen, die für die ganze Gruppe gelten +
-        ansible_ssh_port: 22 +
-        ansible_ssh_user: ansible +
-        ansible_ssh_private_key_file: /home/django/.ssh/id_ed25519_ansible +
-      hosts:                                                                   # Liste aller Hosts die dieser gruppe zugehören +
-        www8.dmz.nausch.org: +
-          ansible_ssh_host: 10.0.0.90                                          # Hostspezifische Ansible-Systemvariable +
-    centos7:                                                                   # Gruppe der definierten CentOS 7 Hosts +
-      vars:                                                                    # Variablen, die für die ganze Gruppe gelten +
-        ansible_ssh_port: 22 +
-        ansible_ssh_user: ansible +
-        ansible_ssh_private_key_file: /home/django/.ssh/id_rsa_ansible        +
-      hosts:                                                                   # Liste aller Hosts die dieser gruppe zugehören +
-        www7.dmz.nausch.org: +
-          ansible_ssh_host: 10.0.0.97                                          # Hostspezifische Ansible-Systemvariable +
-                                                                               # optische Abtrennung zu nachfolgenden Definitionen +
-    ffmucgluon:                                                                # Definition der Gruppe aaler Freifunk Knoten/Hosts +
-      vars:                                                                    # Variablendie für die ganze Gruppe gelten +
-        ansible_ssh_port: 22 +
-        ansible_ssh_user: root +
-        ansible_ssh_private_key_file: /home/django/.ssh/id_rsa4096_freifunk_2014 +
-        contact_info: 'Django [BOfH] | django@nausch.org | chat -> @django' +
-      hosts:                                                                   # Liste aller Hosts die dieser gruppe zugehören +
-        ff_pliening_gbw_ug:                                                    # Host +
-          hostname: ff_pliening_gbw_ug                                         # Hostspezifische Informationen / Variablen +
-          latitude: -48.19861319429455 +
-          longitude: -168.2017571420684 +
-          branch: stable +
-          domain: ffmuc_muc_ost +
-          director: ffmuc_muc_ost +
-          modell: TP-Link TL-WDR4300 v1 +
-          ansible_ssh_host: 2001:608:a01:102:32b5:c2ff:fe56:62b1+
  
-        ff_pliening_gbw_egod                                                 # Host  +Unser **[[centos:ansible:playbooks1#benutzer_anlegen|Playbook-Beispiel 01]]** passen wir nun an und speichern dieses im Verzeichnis **''~/ansible/roles/base/tasks/''** unter den Namen **''main.yml''** 
-          hostnameffplieninggbwegod                                          Hostspezifische Informationen Variablen +   $ vim ~/ansible/roles/base/tasks/main.yml
-          pretty_hostname: ff_pliening_gbw_egod +
-          latitude: 48.198652080 +
-          longitude: 11.797969940 +
-          branch: stable +
-          domain: ffmuc_muc_ost +
-          director: ffmuc_muc_ost +
-          modell: Ubiquiti UniFi-AC-MESH +
-          ansible_ssh_host: 2001:608:a01:102:1ae8:29ff:fea9:22ed+
  
-        ff_pliening_gbw_ogod:                                                  Host +<file yml ~/ansible/roles/base/tasks/main.yml>--- Grundlegende Konfiguration für alle Hosts 
-          hostnameffplieninggbwogod                                          # Hostspezifische Informationen / Variablen +  - name"***base*** Gruppe für (WEB-Entwickler) '{{ createuser }}' erstellen" 
-          pretty_hostnameff_pliening_gbw_ogod +    group# https://docs.ansible.com/ansible/latest/modules/group_module.html 
-          latitude48.198699460 +      name'{{ createuser }}' 
-          longitude11.798053090 +      gid'{{ createguid }}' 
-          branchstable +      statepresent
-          domainffmuc_muc_ost +
-          director: ffmuc_muc_ost +
-          modell: Ubiquiti UniFi-AC-MESH +
-          ansible_ssh_host: 2001:608:a01:102:1ae8:29ff:fec0:aaae+
  
-        ff_pliening_gbw_dgod                                                 # Host +  - name"***base*** : WEB-Admin Nutzerkonto für den User '{{ createuser }}' mit frn zugehörigen UID '{{ createguid }}' anlegen un der Gruppe '{{ createuser }}' zuordnen." 
-           hostnameffplieninggbwdgod                                         Hostspezifische Informationen Variablen +    user: # https://docs.ansible.com/ansible/latest/modules/user_module.html 
-           prettyhostname: ff_pliening_gbw_dgod +      name'{{ createuser }}' 
-           latitude: 48.198671230 +      comment'{{ createusername }}' 
-           longitude: 11.798122820 +      uid'{{ createguid }}' 
-           branchstable +      group'{{ createuser }}' 
-           domainffmuc_muc_ost +      statepresent
-           directorffmuc_muc_ost +
-           modellUbiquiti UniFi-AC-MESH +
-           ansible_ssh_host: 2001:608:a01:102:1ae8:29ff:fec6:c8eb+
  
-        ff_pliening_gbw_cpod                                                 # Host +  - name: "***base*** Initiales Passwort für den WEB-Admin '{{ createuser }}' hinterlegen" 
-           hostnameffplieninggbwcpod                                         Hostspezifische Informationen Variablen +    shell: # https://docs.ansible.com/ansible/latest/modules/shell_module.html 
-           pretty_hostname: ff_pliening_gbw_cpod +      cmdusermod -p $(echo '{{ createpassword }}' | openssl passwd -1 -stdin) {{ createuser }} 
-           latitude: 48.198726280 +</file>
-           longitude: 11.798159030 +
-           branchstable +
-           domain: ffmuc_muc_ost +
-           director: ffmuc_muc_ost +
-           modell: Ubiquiti UniFi-AC-MESH +
-           ansible_ssh_host: 2001:608:a01:102:1ae8:29ff:fec6:c8dd+
  
-        ff_pliening_gbw_kvm_ol:                                                # Host +Wie wir sehen, beinhaltet diese Datei nur noch die Definition der **tasks** aber keine Sitespezifischen Variablen, da wir diese in eine separate Date auslagern werdenWir könnten als jederzeit diese Date auf andere Installationsumgebungen portieren oder an interessierte Adminkollegen weitergeben!
-           hostname: ffplieninggbwkvmol                                        # Hostspezifische Informationen / Variablen +
-           pretty_hostname: ff_pliening_gbw_kvm_ol +
-           latitude: 48.198646720 +
-           longitude: 11.798047720 +
-           branch: stable +
-           domain: ffmuc_muc_ost +
-           director: ffmuc_muc_ost +
-           modell: Red Hat KVM +
-           ansible_ssh_host: 2001:608:a01:102:5054:ff:fe9e:b358+
  
-... #YAML end syntax</file>+Natürlich benötigen wir nun die Definition der Rolenspezifischen Variablen, die je Rolle hier **''~/ansible/roles/base/vars/main.yml''** abzulegen sind.
  
 +   $ vim ~/ansible/roles/base/vars/main.yml
 +<file yml ~/ansible/roles/base/vars/main.yml>--- # Definition der rollenspezifische Variablen
 +createguid    : '1010'                        # GID/UID des Benutzers00
 +createuser    : 'ruben'                       # Username
 +createusername: 'Ruben Nausch'                # Vollständiger Name
 +createpassword: 'M31nP4p4157d3r4113r83573!'   # Initialpasswort (ungecrypted!)
 +</file>
  
-Die YAML-Konfigurationsdatei enthält entsprechende Bemerkungen, die die einzelnen Blöcke und Funktionen ausreichend beschreibenWie können so individuelle und Anwendungsspezifische Lösungen abbilden+Die nächste Rolle, die wir konfigurieren müssen, ist die für den NTP-Daemon **''chrony''**Auch hier kopieren wir zunächst das Default-role-template **common**. 
 +   $ cd ~/ansible/roles 
 +   $ cp -avr common/ chrony/
  
-<WRAP center round info 100%> +Auch hier greifen wir wieder auf das bereits bekannte **[[centos:ansible:playbooks1#ntp-daemon_chrony_installieren_und_konfigurieren|Playbook-Beispiel 05]]** zurück, passen dieses an und speichern es im Verzeichnis **''~/ansible/roles/chrony/tasks/''** unter den Namen **''main.yml''**. Bei diesem Konfigurationsbeispiel besteht das playbook aber lediglich aus vier **tasks**, die wir als eigenständige Dateien auslagern und hier nur includieren werden
-Natürlich gilt zu bedenken, dass das gezeigte Beispiel mit nur 8 Hosts und überschaubaren Variablen doch schon recht umfangreich geworden ist, wenn dies alles in eine Inventory-Datei gepackt wird. Bei Dutzenden oder Hunderten von Maschinen wird dies dann daraus schwer zu handeln - von verschachtelten Gruppen in Gruppen, oder Host die Mitglied in mehreren Gruppen sein sollen, sprechen wir dann besser gar nicht. Hier werden wir später auf eine **[[#inventarisierung_groesserer_umgebungen|andere/aufgeteilte Lösung]]** einschwenken müssen.  +   $ vim ~/ansible/roles/chrony/tasks/main.yml
-</WRAP>+
  
-/* Viele Hinweise und Beispiel zu den Gruppen finden sich auch hier im Kapitel **[[https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html|How to build your inventory]]** der Ansible Dokumentation enthalten.*/+<file yml ~/ansible/roles/chrony/tasks/main.yml>--- # Hauptinstallations-/Konfigurationsdatei für den Dienst chrony 
 +- include: install.yml       # Installation 
 +- include: config-backup.yml # original-Konfig sichern 
 +- include: configure.yml     # Konfiguration 
 +- include: service.yml       # Service starten 
 +</file>
  
-=== playbook === +Die vier **tasks** hinterlegen wire dann anschließend in der zugehörigen YML-Datei
-Unsere gerade angelegte Inventory-Datei wollen wir nun verwenden um die Geolocation-Daten unserer Freifunk-Knoten zu organisieren. Die Geodaten sind in der obigen Inventory-Datei in den beiden Variablen **''latitude''** und **''longitude''** gespeichert - diese beiden Variablen nutzen wir nun in unserem Playbook. +   $ vim ~/ansible/roles/chrony/tasks/install.yml 
-   $ ~/ansible/08_set_location.yml+<file yml ~/ansible/roles/chrony/tasks/install.yml>--- 
 +  - name: "***chrony*** : Installation des Deamon '{{ daemon_name }}(in der aktuellsten Version)" 
 +    dnf:  
 +    #https://docs.ansible.com/ansible/latest/modules/dnf_module.html 
 +      name: '{{ daemon_name }}' 
 +      state: latest 
 +</file>
  
-<file bash ~/ansible/08_set_location.yml> +   $ vim ~/ansible/roles/chrony/tasks/config-backup.yml 
---- +<file yml ~/ansible/roles/chrony/tasks/config-backup.yml>--- 
-hostsffmucgluon +  name"***chrony*** : 1) Überprüfen ob das Backup der Konfigurationsdatei '{{ config_file }}' bereits existiert" 
-  gather_factsFalse+    stat: # https://docs.ansible.com/ansible/latest/modules/stat_module.html  
 +      path: /etc/chrony.conf.orig 
 +    registerstat_result
  
-  tasks: +  - name: "***chrony*** : 2) Von der bestehenden originalen Konfigurationsdatei '{{ config_file }}' ein Backup '{{ config_file }}'.orig erstellen
-    - name: "Set GEO location of our own ffmuc-nodes+    copy: # https://docs.ansible.com/ansible/latest/modules/copy_module.html 
-      #https://docs.ansible.com/ansible/latest/modules/raw_module.html +      remote_srcyes 
-      rawuci set gluon-node-info.@location[0]="location"; uci set gluon-node-info.@location[0].share_location="1"; uci set gluon-node-info.@location[0].latitude="{{ latitude }}" ; uci set gluon-node-info.@location[0].longitude="{{ longitude }}"; uci commit gluon-node-info</file>+      src: '{{ config_file }}
 +      dest: /etc/chrony.conf.orig 
 +    when: stat_result.stat.exists == False 
 +</file>
  
-=== Script ausführen === +   $ vim ~/ansible/roles/chrony/tasks/configure.yml 
-Nun wollen wir unser ersten Playbook ausführen, um die Geodaten aus der Inventory-Datei auf unseren Freifunk-Knoten abzugleichen; hierzu rufen wir unser Script wie folgt auf+<file yml ~/ansible/roles/chrony/tasks/configure.yml>--
-   $ ansible-playbook -v 08_change_contact.yml+  - name: "***chrony*** Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen" 
 +    template: # https://docs.ansible.com/ansible/latest/modules/template_module.html  
 +      src: templates/chrony-client.conf.j2  
 +      dest: "{{ config_file }}" 
 +</file>
  
-<html><pre class="code"> +Das zugehörige Template für die Konfigurationsdatei legen wir im zugehörigen Verzeichnis **''~/ansible/roles/chrony/templates''** ab. 
-<font style="color: rgb(43, 100, 164)">Using /etc/ansible/ansible.cfg as config file</font> +   $ vim ~/ansible/roles/chrony/templates/chrony-client.conf.j2
-<font style="color: rgb(0, 0, 0)">BECOME password: +
  
-PLAY [ffmucgluon] **********************************************************************************************************************+<file yml ~/ansible/roles/chrony/templates/chrony-client.conf.j2># Use public servers from the pool.ntp.org project. 
 +# Please consider joining the pool (http://www.pool.ntp.org/join.html). 
 +{{ chrony_pool }}
  
-<font style="color: rgb(0, 0, 0)">TASK [Update new contact-address on own ffmuc-nodes] ***********************************************************************************</font> +# Ignore stratum in source selection 
-<font style="color: rgb(196, 160, 0)">changed: [ff_pliening_gbw_egod] => {"changed": true, "rc": 0, "stderr": "Shared connection to 2001:608:a01:102:1ae8:29ff:fea9:22ed closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:1ae8:29ff:fea9:22ed closed."], "stdout": "", "stdout_lines": []} +{{ chrony_stratumweight }}
-changed: [ff_pliening_gbw_kvm_ol] => {"changed": true, "rc": 0, "stderr": "Shared connection to 2001:608:a01:102:5054:ff:fe9e:b358 closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:5054:ff:fe9e:b358 closed."], "stdout": "", "stdout_lines": []} +
-changed: [ff_pliening_gbw_ogod] => {"changed": true, "rc": 0, "stderr": "Shared connection to 2001:608:a01:102:1ae8:29ff:fec0:aaae closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:1ae8:29ff:fec0:aaae closed."], "stdout": "", "stdout_lines": []} +
-changed: [ff_pliening_gbw_ug] => {"changed": true, "rc": 0, "stderr": "Shared connection to 2001:608:a01:102:32b5:c2ff:fe56:62b1 closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:32b5:c2ff:fe56:62b1 closed."], "stdout": "", "stdout_lines": []} +
-changed: [ff_pliening_gbw_dgod] => {"changed": true, "rc": 0, "stderr": "Shared connection to 2001:608:a01:102:1ae8:29ff:fec6:c8eb closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:1ae8:29ff:fec6:c8eb closed."], "stdout": "", "stdout_lines": []} +
-changed: [ff_pliening_gbw_cpod] => {"changed": true, "rc": 0, "stderr": "Shared connection to 2001:608:a01:102:1ae8:29ff:fec6:c8dd closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:1ae8:29ff:fec6:c8dd closed."], "stdout": "", "stdout_lines": []}</font><br> +
-<font style="color: rgb(0, 0, 0)">PLAY RECAP *****************************************************************************************************************************</font> +
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_cpod       </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196, 160, 0)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_dgod       </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196, 160, 0)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_egod       </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196, 160, 0)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_kvm_ol     </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196, 160, 0)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_ogod       </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196, 160, 0)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_ug         </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196, 160, 0)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +
-<br></pre> +
-</html>+
  
-=== Ergebnis === +# Record the rate at which the system clock gains/losses time. 
-Alle unsere eigenen definierten Freifunk Knoten haben nun auf der **[[https://map.ffmuc.net/#!/de/map/18e829a922ed|Freifunk München Karte]]** die aktualisierten GeoDaten.+driftfile /var/lib/chrony/drift
  
-==== Komplexere und größere Umgebungen ==== +# Allow the system clock to be stepped in the first three updates 
-Wie schon im vorhergehenden Beispiel angemerkt, wird es bei einer größeren Anzahl von Hostdefinitionen mit umfangreichen oder verschachtelten (Gruppe in Gruppe) Gruppenzugehörigkeiten mit verschiedensten zugeordneten Variablen sehr schnell "schmutzig"All das in einer einzigsten Konfiguration abbilden zu wollen, wird man vermutlich in die Ecke "Hand zu masochistischen Tendenzen" oder Selbstgeisselung eines Admins einordnen - kurzum hier muss ein anderer Lösungsansatz her!+# if its offset is larger than 1 second. 
 +makestep 1.0 3
  
-In dem nachfolgenden Konfigurationsbeispiel sehen wir uns eine kleinere Installation an, die zwar nicht genau dem Kriterien **"groß"**, aber an Hand dieses Beispiels lässt sich das grundsätzliche Struktur und der Umgang mit verschachtelten Gruppen anschaulich erklären. Wir gehen bei diesem Beispiel von einer mittleren Freifunk-Installation mit folgenden unterschiedlichen Systemkomponenten und -eigenschaften aus aus:+# Enable kernel synchronization of the real-time clock (RTC). 
 +rtcsync
  
-  * **Standard-Nodes**: Dies sind einfach ausgedrückt Standard-WLAN-Access-Points((**A**ccess **P**oint)), die für Endanwender einen Zugang zum Internet bereitstellen. In einfachen Installationen spannen diese einen Tunnel in Richtung des zentralen Gateways auf. Auf diesen Nodes läuft in aller Regel eine Firmware, die auf dem **[[https://github.com/freifunk-gluon/gluon|Gluon-Framework]]** sowie **[[https://openwrt.org/|OpenWrt]]** basiert+In first three updates step the system clock instead of slew 
-  * **Offloader**: Bei entsprechenden Verkehrsmengen (Traffic und Nutzer) nutzt man meist in kleinen vermaschten Netzen sog. Offloader, die leistungsfähigere Hardware verbaut haben um einen Tunnel zum zentralen Gateway der Freifunk Community aufzuspannen. Als Offloader kommen meist **x86-Hardware** in Form von **futro-thinclients**, virtualisierte Systeme **KVM** oder auch **Raspberry 4** Auf letzterem läuft als Betriebssystem ein spezielles Debian, auf den beiden anderen i.d.R. **Gluon**.+# if the adjustment is larger than 10 seconds
 +{{ chrony_makestep }}
  
-In unserem Konfigurationsbeispiel haben wir folgende Komponenten und (Betriebs-)Systeme im Einsatz, woraus sich unterschiedliche Gruppenkonstellationen ergeben, die im Betrieb zum Tragen kommen bzwverwendet werden. +# Enable hardware timestamping on all interfaces that support it
-  - **Gruppe** aller WiFi-AccessPoints mit **Gluon** **''ffmuc''**: +#hwtimestamp *
-    * ff_pliening_gbw_cpod +
-    * ff_pliening_gbw_dod +
-    * ff_pliening_gbw_egod +
-    * ff_pliening_gbw_ogod +
-    * ff_pliening_gbw_ug +
-    * ff_roding_as_nausch  +
-  - **Gruppe** aller Offloader **''olall''**: +
-    * ff_pliening_gbw_client +
-    * ff-django-raspi +
-    * ff_pliening_gbw_futro_mesh +
-    * ff_pliening_gbw_kvm_ol +
-  - **Gruppe** **''gluonall''** aller Gluon-Systeme +
-    * ff_pliening_gbw_cpod +
-    * ff_pliening_gbw_dod +
-    * ff_pliening_gbw_egod +
-    * ff_pliening_gbw_ogod +
-    * ff_pliening_gbw_ug +
-    * ff_roding_as_nausch +
-    * ff_pliening_gbw_futro_mesh +
-    * ff_pliening_gbw_kvm_ol +
-  - **Gruppe** **''olfutro''** der Offloader mit Futro-Hardware: +
-    * ff_pliening_gbw_futro_mesh +
-  - **Gruppe** **''ololkvm''** der KVM virtualisierten Offloader: +
-    * ff_pliening_gbw_kvm_ol +
-  - **Gruppe** **''olgluon''** aller Offloader mit **Gluon** +
-    * ff_pliening_gbw_futro_mesh +
-    * ff_pliening_gbw_kvm_ol +
-  - **Gruppe** **''oldeb''** aller Offloader mit **Debian** +
-    * ff_pliening_gbw_futro_mesh +
-    * ff_pliening_gbw_kvm_ol +
-  - **Gruppe** **''all''** aller Nodes: +
-    * ff_pliening_gbw_cpod +
-    * ff_pliening_gbw_dod +
-    * ff_pliening_gbw_egod +
-    * ff_pliening_gbw_ogod +
-    * ff_pliening_gbw_ug +
-    * ff_roding_as_nausch +
-    * ff_pliening_gbw_client +
-    * ff-django-raspi +
-    * ff_pliening_gbw_futro_mesh +
-    ff_pliening_gbw_kvm_ol+
  
-Nachfolgendes Schaubild visualisiert die einzelnen Gruppen und die entsprechenden Überlappungen+# Increase the minimum number of selectable sources required to adjust 
-  +# the system clock
-{{ :centos:ansible:inventory.png?direct&900 |Bild: Übersicht einer möglichen (Infra)Struktur}}+#minsources 2
  
 +# Allow NTP client access from local network.
 +#allow 192.168.0.0/16
  
-=== inventory - Beispiel === +# Serve time even if not synchronized to a time source
-Die **Inventory**-Datei **''inventory.yml''** unseres Beispiels legen wir im Arbeitsverzeichnis unseres Ansible-Administrationshost ab+#local stratum 10
-   $ vim ~/ansible/inventory.yml+
  
-<file bash ~/ansible/inventory.yml>--- #Inventory - YAML syntax  +# Specify file containing keys for NTP authentication. 
-all: +keyfile /etc/chrony.keys
-  children: +
-    ffmuc: +
-      hosts: +
-        ff_pliening_gbw_cpod: +
-        ff_pliening_gbw_dgod: +
-        ff_pliening_gbw_egod: +
-        ff_pliening_gbw_ogod: +
-        ff_pliening_gbw_ug: +
-        ff_roding_as_nausch: +
-    oldeb: +
-      hosts: +
-        ff_pliening_gbw_client: +
-        ff-django-raspi: +
-    olfutro: +
-      hosts: +
-        ff_pliening_gbw_futro_mesh: +
-    olkvm: +
-      hosts: +
-        ff_pliening_gbw_kvm_ol: +
-    olgluon: +
-      children: +
-        olkvm: +
-        olfutro: +
-    olall: +
-      children: +
-        oldeb: +
-        olgluon: +
-    gluonall: +
-      children: +
-        ffmuc: +
-        olgluon: +
-    ffmucall: +
-      children: +
-        ffmuc: +
-        olall: +
-... #YAML end syntax +
-</file>+
  
-Die Datei ist relativ übersichtlich und doch recht einfach zu verstehen. Würden wir nun aber die Hostund Gruppenspezifischen Variablen mit in die Datei aufnehmen, wäre dies jedoch gänzlich anders. Dabei haben wir hier nur 10 Hosts und noch keine 100 oder noch mehr+# Get TAI-UTC offset and leap seconds from the system tz database. 
 +leapsectz right/UTC
  
-Ansible bietet daher einen skalierbareren Ansatz, um den Überblick über Host- und Gruppenvariablen zu behalten. Man kann für jeden Host und jede Gruppe die Variablen in einer jeweils zugehörigen Datei auslagern. Ansible wir beim Aufruf und Abarbeiten eines Playbooks diese hostspezifischen Dateien im Verzeichnis **''host_vars''** und die gruppenspezifischen Variablen im Verzeichnis **''group_vars''**. Diese Verzeichnisse werden von Ansible entweder im dem Verzeichnis erwartet, in dem das aufgerufene Playbook gespeichert wurde oder alternativ dazu im Verzeichnis in dem das die **Inventory**-Datei gespeichert wurde.+# Specify directory for log files. 
 +logdir /var/log/chrony
  
-Wir legen also die beiden Verzeichnisse an+# Select which information is logged
-   $ mkdir ~/ansible/inventory/host_vars +#log measurements statistics tracking 
-   $ mkdir ~/ansible/inventory/group_vars+</file>
  
-Somit haben wir dann aktuell folgende Verzeichnisstruktur auf unserem Admin-/Ansible-Host+Der **task** zum Starten des Daemon legen wir im Verzeichnis **''task''** ab. 
-<code>+   $ vim ~/ansible/roles/chrony/tasks/service.yml 
-├── authkeys +<file yml ~/ansible/roles/chrony/tasks/service.yml>--- 
-├── files +  - name: "***chrony*** : Sicherstellen dass der  Daemon '{{ daemon_name }}' (beim Systemstart) gestartet wird und läuft" 
-│   ├── CentOS7 +    service: # https://docs.ansible.com/ansible/latest/modules/service_module.html  
-│   └── CentOS8 +      name: chronyd  
-├── includes +      state: started  
-├── inventory +      enabled: yes 
-│   ├── group_vars +</file>
-│   └── host_vars +
-├── playbooks +
-└── templates +
-    └── chrony-client</code>+
  
-Je **Gruppe** speichern wir also eine individuelle Datei im Verzeichnis **''~/ansible/inventory/group_vars''** ab+Zu guter letzt benötigen wir auch hier eine zur Rolle gehörige Parameter-Datei mit den Definitionen der Variablen. 
-   $ vim ~/inventory/group_vars/ffmuc.yml+   $ vim ~/ansible/roles/chrony/vars/main.yml 
 +<file yml ~/ansible/roles/chrony/vars/main.yml>--- # Definition der rollenspezifische Variablen zum Dienst chrony 
 +daemon_name         : chrony 
 +config_file         : /etc/chrony.conf 
 +# chronyd client config-options 
 +chrony_pool         : "server time.dmz.nausch.org iburst" 
 +chrony_stratumweight: "stratumweight 0" 
 +chrony_makestep     : "makestep 10 3" 
 +</file>
  
-<file bash ~/inventory/group_vars/ffmuc.yml>ffmuc: +Alle bisher getroffenen Konfigurationseinstellungen gelten für alle Applikations-Hosts und wir müssen lediglich die beiden Rollen **''base''** und **''chrony''** bei den entsprechenden Playbook-Dateien includieren! 
-  ansible_ssh_port22 + 
-  ansible_ssh_userroot +Nun folgt der Webserverspezifische Teil unseres Ansible-Musterkonfiguration eines Webserversmit der Definition der Role **''www''**. Zunächst benötigen wir natürlich auch für diese Rolle die altbekannte Verzeichnisstruktur. 
-  ansible_ssh_private_key_file/home/django/.ssh/id_rsa4096_freifunk_2014.pub +   $ cd ~/ansible/roles 
-  contact_info'Django [BOfH] | django@nausch.org | chat -> @django'+   $ cp -avr common/ www/ 
 +  
 +Angelehnt an die Rolle **''chrony''** definieren wir auch hier als erstes das playbook mit fünf einzelnen **tasks**, die wir als eigenständige Dateien auslagern und hier nur includieren werden. In dieses Falle sindes fünf **tasks**, also einer mehr wie bei der Rolle **''chrony''**, da wir ja hier unsere initialen Webseite nach **''DOCUMENT_ROOT''** des Apache-Webservers noch kopieren wollen. 
 +   $ vim ~/ansible/roles/www/tasks/main.yml 
 + 
 +<file yml ~/ansible/roles/www/tasks/main.yml>--- # Hauptinstallations-/Konfigurationsdatei für den Apache-Webserver 
 +- includeinstall.yml       # Installation 
 +- includeconfig-backup.yml # original-Konfig sichern 
 +- includeconfigure.yml     # Konfiguration 
 +- includecontent.yml       # Initiale Webseite befüllen 
 +include: service.yml       # Service starten
 </file> </file>
  
-Für die anderen Gruppe(n) verfahren wie ebenso.+Da wir das Rad ja bekanntlicher Weise nicht 2x erfinden müssen, greifen wir bei der Konfiguration der einzelnen **tasks** der Rolle **''www''** auf altbewährtes, nämlich der Konfigurationsvorlage der zuvor erstellten Rolle **''chrony''** zurück. Wir kopieren uns die Datei und verändern diese entsprechend. 
 +   $ cp ~/ansible/roles/chrony/tasks/install.yml ~/ansible/roles/www/tasks/install.yml 
 +   $ vim ~/ansible/roles/www/tasks/install.yml
  
-Je **Host** speichern wir dann jeweils eine individuelle Datei im Verzeichnis **''~/ansible/inventory/hosts_vars''** ab. +<file yml ~/ansible/roles/www/tasks/install.yml>--- 
-   $ vim ~/ansible/inventory/host_vars/ff_pliening_gbw_egod.yml+  - name: "***www*** : Installation des Deamon '{{ daemon_name }}(in der aktuellsten Version)" 
 +    dnf: 
 +    #https://docs.ansible.com/ansible/latest/modules/dnf_module.html 
 +      name: '{{ daemon_name }}' 
 +      state: latest 
 +</file>
  
-<file bash ~/ansible/inventory/host_vars/ff_pliening_gbw_egod.yml>ff_pliening_gbw_egod: +Ähnlich verfahren wir mit dem **task** zum Sichern der originalen Konfigurationsdatei **''config-backup.yml''** sowie zum Konfigurieren des Daemon **''configure.yml''**. 
-  hostnameffplieninggbwegod +   $ cp ~/ansible/roles/chrony/tasks/config-backup.yml ~/ansible/roles/www/tasks/config-backup.yml 
-  pretty_hostnameff_pliening_gbw_egod +   $ vim ~/ansible/roles/www/tasks/config-backup.yml 
-  latitude48.198652080 +<file yml ~/ansible/roles/www/tasks/config-backup.yml>--- 
-  longitude11.797969940 +  - name"***www*** 1) Überprüfen ob das Backup der Konfigurationsdatei '{{ config_file }}' bereits existiert" 
-  branchstable +    stat# https://docs.ansible.com/ansible/latest/modules/stat_module.html  
-  domainffmuc_muc_ost +      path'{{ backup_file }}' 
-  director: ffmuc_muc_ost +    registerstat_result
-  modell: Ubiquiti UniFi-AC-MESH +
-  ansible_ssh_host: 2001:608:a01:102:1ae8:29ff:fea9:22ed</file>+
  
-Auch für die anderen Hosts legen wir entsprechende Dateien mit den Variablen an.+  - name: "***www*** : 2) Von der bestehenden originalen Konfigurationsdatei '{{ config_file }}' ein Backup '{{ backup_file }}' erstellen" 
 +    copy: # https://docs.ansible.com/ansible/latest/modules/copy_module.html 
 +      remote_src: yes 
 +      src: '{{ config_file }}' 
 +      dest: '{{ backup_file }}' 
 +    when: stat_result.stat.exists == False 
 +</file>
  
-=== playbook === +   $ cp ~/ansible/roles/chrony/tasks/configure.yml ~/ansible/roles/www/tasks/configure.yml 
-Die zuvor angelegte Inventory- und auch Host-/Group-Variablendateien wollen wir nun verwenden um die Geolocation-Daten unserer Freifunk-Knoten zu organisieren. Die Geodaten sind in den jeweiligen Host-Dateien in den beiden Variablen **''latitude''** und **''longitude''** gespeichert - diese beiden Variablen nutzen wir nun in unserem Playbook. +   $ vim ~/ansible/roles/www/tasks/configure.yml 
-   $ ~/ansible/playbooks/09_set_location.yml+<file yml ~/ansible/roles/www/tasks/configure.yml>--- 
 +  name: "***www*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen" 
 +    template: # https://docs.ansible.com/ansible/latest/modules/template_module.html  
 +      src: templates/httpd-server.conf.j2 
 +      dest: "{{ config_file }}" 
 +</file>
  
-<file bash ~/ansible/playbooks/09_set_location.yml> +Auch hier benötigen wir eine Datei, in der die Variablen für den Task **www** vorgehalten werden. 
---- +   $ vim ~/ansible/roles/www/vars/main.yml 
-hostsffmuc +<file yml ~/ansible/roles/www/vars/main.yml>--- # Definition der rollenspezifische Variablen zum Apache-Webserver httpd 
-  gather_factsFalse+daemon_name                : httpd 
 +config_file                : /etc/httpd/conf/httpd.conf 
 +backup_file                : /etc/httpd/conf/httpd.conf.orig 
 +# httpd-Server config-options 
 +httpd_server_admin         "ServerAdmin webmaster@nausch.org" 
 +httpd_server_http_header   "ServerTokens Prod\nServerSignature Off\nHeader always unset \"X-Powered-By\"\nHeader unset \"X-Powered-By\"" 
 +httpd_server_extendedstatus: "ExtendedStatus On" 
 +httpd_server_traceenable   : "TraceEnable off" 
 +</file>
  
-  tasks: +Zu guter letzt müssen wir natürlich auch noch Sorge Tragen dass der HTTP-Daemon läuft und beim Systemstart auch geladen wird. Auch hier kopieren wir uns der Einfachheit halber das passende Gegenstück aus unserem Erfahrungsschatz. 
-    - name: "Set GEO location of our own ffmuc-nodes+   $ cp ~/ansible/roles/chrony/tasks/service.yml ~/ansible/roles/www/tasks/service.yml 
-      #https://docs.ansible.com/ansible/latest/modules/raw_module.html +   $ vim ~/ansible/roles/www/tasks/service.yml 
-      rawuci set gluon-node-info.@location[0]="location"; uci set gluon-node-info.@location[0].share_location="1"; uci set gluon-node-info.@location[0].latitude="{{ latitude }}" ; uci set gluon-node-info.@location[0].longitude="{{ longitude }}"; uci commit gluon-node-info</file>+<file yml ~/ansible/roles/www/tasks/service.yml>--- 
 +  - name: "***www*** : Sicherstellen dass der  Daemon '{{ daemon_name }}' (beim Systemstart) gestartet wird und läuft
 +    service: # https://docs.ansible.com/ansible/latest/modules/service_module.html  
 +      namehttpd 
 +      state: started 
 +      enabled: yes
  
-=== Script antesten === +  name: "***www*** : Paketfilter anpassen und Port 80 (HTTP) öffnen" 
-Bevor wir nun das Playbook ausführen wollen wir erst einmal shen, ob auch die richtigen Hosts verwendet werden würden. Hierzu hat der Befehl **''ansible-playbook''** eine entsprechende Option **''--list-hosts''**. +    firewalld: # https://docs.ansible.com/ansible/latest/modules/firewalld_module.html 
-   ansible-playbook -v ~/ansible/playbooks/09_set_location.yml --list-hosts+      service: http 
 +      permanent: yes 
 +      state: enabled 
 +</file>
  
-<html><pre class="code"> +Wir haben also ein modular aufgebautes Installationsplaybook für unseren Webservermit den drei Rollen **base****chrony** und **www** und jeweils abgetrennte lokale individuelle Konfigurationsparameter, sowie das Playbook **''web.yml''** und der übergeordneten Site-Konfiguration **''site.yml''**.
-<font style="color: rgb(43100164)">Using /etc/ansible/ansible.cfg as config file</font>+
  
-<font style="color: rgb(0, 0, 0)">playbook: /home/django/ansible/playbooks/09_set_location.yml+<code>/home/ansible/ansible/ 
 +├── filter_plugins 
 +├── inventories 
 +│   ├── production 
 +│   │   ├── group_vars 
 +│   │   ├── hosts.yml 
 +│   │   └── host_vars 
 +│   └── staging 
 +│       ├── group_vars 
 +│       ├── hosts.yml 
 +│       └── host_vars 
 +├── library 
 +├── module_utils 
 +├── roles 
 +│   ├── base 
 +│   │   ├── defaults 
 +│   │   │   └── main.yml 
 +│   │   ├── files 
 +│   │   │   └── main.yml 
 +│   │   ├── handlers 
 +│   │   │   └── main.yml 
 +│   │   ├── library 
 +│   │   ├── lookup_plugin 
 +│   │   ├── meta 
 +│   │   │   └── main.yml 
 +│   │   ├── module_utils 
 +│   │   ├── tasks 
 +│   │   │   └── main.yml 
 +│   │   ├── templates 
 +│   │   │   └── main.yml 
 +│   │   └── vars 
 +│   │       └── main.yml 
 +│   ├── chrony 
 +│   │   ├── defaults 
 +│   │   │   └── main.yml 
 +│   │   ├── files 
 +│   │   │   └── main.yml 
 +│   │   ├── handlers 
 +│   │   │   └── main.yml 
 +│   │   ├── library 
 +│   │   ├── lookup_plugin 
 +│   │   ├── meta 
 +│   │   │   └── main.yml 
 +│   │   ├── module_utils 
 +│   │   ├── tasks 
 +│   │   │   ├── config-backup.yml 
 +│   │   │   ├── configure.yml 
 +│   │   │   ├── install.yml 
 +│   │   │   ├── main.yml 
 +│   │   │   └── service.yml 
 +│   │   ├── templates 
 +│   │   │   ├── chrony-client.conf.j2 
 +│   │   │   └── main.yml 
 +│   │   └── vars 
 +│   │       └── main.yml 
 +│   ├── common 
 +│   │   ├── defaults 
 +│   │   │   └── main.yml 
 +│   │   ├── files 
 +│   │   │   └── main.yml 
 +│   │   ├── handlers 
 +│   │   │   └── main.yml 
 +│   │   ├── library 
 +│   │   ├── lookup_plugin 
 +│   │   ├── meta 
 +│   │   │   └── main.yml 
 +│   │   ├── module_utils 
 +│   │   ├── tasks 
 +│   │   │   └── main.yml 
 +│   │   ├── templates 
 +│   │   │   └── main.yml 
 +│   │   └── vars 
 +│   │       └── main.yml 
 +│   └── www 
 +│       ├── defaults 
 +│       │   └── main.yml 
 +│       ├── files 
 +│       │   └── main.yml 
 +│       ├── handlers 
 +│       │   └── main.yml 
 +│       ├── library 
 +│       ├── lookup_plugin 
 +│       ├── meta 
 +│       │   └── main.yml 
 +│       ├── module_utils 
 +│       ├── tasks 
 +│       │   ├── config-backup.yml 
 +│       │   ├── configure.yml 
 +│       │   ├── content.yml 
 +│       │   ├── install.yml 
 +│       │   ├── main.yml 
 +│       │   └── service.yml 
 +│       ├── templates 
 +│       │   ├── homepage.conf.j2 
 +│       │   ├── httpd-server.conf.j2 
 +│       │   └── main.yml 
 +│       └── vars 
 +│           └── main.yml 
 +├── site.yml 
 +└── web.yml</code>
  
-  play #1 (ffmuc): ffmuc TAGS: [] +<WRAP center round tip 80%> 
-    pattern: ['ffmuc'] +Abschließend kann man sich nun berechtigter Weise die Frage stellen, warum man nun mehrere Dateien erstellt haben,um den Code und die Variablen dazu, der die Pakete installiert und die Dienste verwaltet, separat zu speichern? Wir sind so sehr leicht in der Lage zum, Beispiel Dienste in mehreren Phasen bereitstellen. In einer ersten Phase können wir so Anwendungen lediglich installieren und konfigurieren und erst in der zweiten Phase dann die Dienste dann starten.  
-    hosts (6): +Natürlich haben es wir so auch leichter Teiel des Codes wiederzu verwenden, als wenn man eine große Datei vernweden würde in der alle Einzelschritte selektiv aufgeführt sind! 
-      ff_pliening_gbw_egod +</WRAP>
-      ff_roding_as_nausch +
-      ff_pliening_gbw_cpod +
-      ff_pliening_gbw_dgod +
-      ff_pliening_gbw_ogod +
-      ff_pliening_gbw_ug</font></pre> +
-</html>+
  
 +----
 === Script ausführen === === Script ausführen ===
-Nun wollen wir unser ersten Playbook ausführen, um die Geodaten aus der Inventory-Datei auf unseren Freifunk-Knoten abzugleichen; hierzu rufen wir unser Script wie folgt auf: +Zum Schluss rufen wir unser erstes **role**-based Playbook auf uns installieren und konfigurieren unseren Webserver. 
-   $ ansible-playbook -v ~/ansible/playbooks/09_set_location.yml+   $ ansible-playbook site.yml 
  
 <html><pre class="code"> <html><pre class="code">
-<font style="color: rgb(43, 100, 164)">Using /etc/ansible/ansible.cfg as config file</font> 
 <font style="color: rgb(0, 0, 0)">BECOME password:  <font style="color: rgb(0, 0, 0)">BECOME password: 
  
-PLAY [ffmuc***************************************************************************************************************************+PLAY [demo] *************************************************************************************************************************
  
-<font style="color: rgb(0, 0, 0)">TASK [Update new contact-address on own ffmuc-nodes] ***********************************************************************************</font> +TASK [Gathering Facts**************************************************************************************************************</font> 
-<font style="color: rgb(1961600)">changed: [ff_pliening_gbw_egod={"changed": true, "rc": 0, "stderr": "Shared connection to 2001:608:a01:102:1ae8:29ff:fea9:22ed closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:1ae8:29ff:fea9:22ed closed."], "stdout": "", "stdout_lines": []} +<font style="color: rgb(251005)">ok: [demo]</font><br
-changed: [ff_pliening_gbw_kvm_ol] => {"changed": true"rc": 0, "stderr": "Shared connection to 2001:608:a01:102:5054:ff:fe9e:b358 closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:5054:ff:fe9e:b358 closed."], "stdout": "", "stdout_lines": []} +<font style="colorrgb(0, 0, 0)">TASK [***base*** Gruppe für (WEB-Entwickler) 'ruben' erstellen*******************************************************************</font> 
-changed: [ff_pliening_gbw_ogod] => {"changed": true"rc": 0, "stderr": "Shared connection to 2001:608:a01:102:1ae8:29ff:fec0:aaae closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:1ae8:29ff:fec0:aaae closed."], "stdout": "", "stdout_lines": []} +<font style="colorrgb(196, 160, 0)">changed: [demo]</font><br> 
-changed: [ff_pliening_gbw_ug] => {"changed": true"rc": 0, "stderr": "Shared connection to 2001:608:a01:102:32b5:c2ff:fe56:62b1 closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:32b5:c2ff:fe56:62b1 closed."], "stdout": "", "stdout_lines": []} +<font style="colorrgb(0, 0, 0)">TASK [***base*** WEB-Admin Nutzerkonto für den User 'ruben' mit frn zugehörigen UID '1010' anlegen un der Gruppe 'ruben' zuordnen.] </font> 
-changed: [ff_pliening_gbw_dgod] => {"changed": true"rc": 0"stderr": "Shared connection to 2001:608:a01:102:1ae8:29ff:fec6:c8eb closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:1ae8:29ff:fec6:c8eb closed."], "stdout": "", "stdout_lines": []} +<font style="colorrgb(196, 160, 0)">changed: [demo]</font><br> 
-changed: [ff_pliening_gbw_cpod] ={"changed": true, "rc": 0, "stderr": "Shared connection to 2001:608:a01:102:1ae8:29ff:fec6:c8dd closed.\r\n", "stderr_lines": ["Shared connection to 2001:608:a01:102:1ae8:29ff:fec6:c8dd closed."], "stdout": "", "stdout_lines": []}</font><br> +<font style="color: rgb(0, 0, 0)">TASK [***base*** : Initiales Passwort für den WEB-Admin 'ruben' hinterlegen] ********************************************************</font> 
-<font style="color: rgb(0, 0, 0)">PLAY RECAP *****************************************************************************************************************************</font> +<font style="color: rgb(196, 160, 0)">changed: [demo]</font><br> 
-<font style="color: rgb(1961600)">ff_pliening_gbw_cpod       </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196160, 0)">changed=1    </font><font style="color: rgb(00, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +<font style="color: rgb(0, 0, 0)">TASK [***chrony*** : Installation des Deamon 'chrony' (in der aktuellsten Version)] *************************************************</font> 
-<font style="color: rgb(196160, 0)">ff_pliening_gbw_dgod       </font><font style="color: rgb(00, 0)">: </font><font style="color: rgb(251005)">ok=1    </font><font style="color: rgb(1961600)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +<font style="color: rgb(251005)">ok: [demo]</font><br> 
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_egod       </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196160, 0)">changed=1    </font><font style="color: rgb(00, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +<font style="color: rgb(0, 0, 0)">TASK [***chrony*** 1) Überprüfen ob das Backup der Konfigurationsdatei '/etc/chrony.conf' bereits existiert] **********************</font> 
-<font style="color: rgb(196160, 0)">ff_pliening_gbw_kvm_ol     </font><font style="color: rgb(00, 0)">: </font><font style="color: rgb(251005)">ok=1    </font><font style="color: rgb(196, 160, 0)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +<font style="color: rgb(25, 100, 5)">ok: [demo]</font><br> 
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_ogod       </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=1    </font><font style="color: rgb(196, 160, 0)">changed=1    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +<font style="color: rgb(00, 0)">TASK [***chrony*** : 2) Von der bestehenden originalen Konfigurationsdatei '/etc/chrony.conf' ein Backup '/etc/chrony.conf'.orig erstellen] *****************************************************************************************************************************</font> 
-<font style="color: rgb(196, 160, 0)">ff_pliening_gbw_ug         </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=   </font><font style="color: rgb(196, 160, 0)">changed=   </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font> +<font style="color: rgb(196160, 0)">changed: [demo]</font><br
-<br></pre>+<font style="color: rgb(00, 0)">TASK [***chrony*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen] **********************************</font> 
 +<font style="color: rgb(196160, 0)">changed[demo]</font><br> 
 +<font style="color: rgb(000)">TASK [***chrony*** : Sicherstellen dass der  Daemon 'chrony' (beim Systemstart) gestartet wird und läuft] ***************************</font> 
 +<font style="color: rgb(251005)">ok: [demo]</font><br> 
 +<font style="color: rgb(0, 0, 0)">TASK [***www*** : Installation des Deamon 'httpd' (in der aktuellsten Version)] *****************************************************</font> 
 +<font style="color: rgb(196, 160, 0)">changed: [demo]</font><br> 
 +<font style="color: rgb(0, 0, 0)">TASK [***www*** 1) Überprüfen ob das Backup der Konfigurationsdatei '/etc/httpd/conf/httpd.conf' bereits existiert] ***************</font> 
 +<font style="color: rgb(25, 100, 5)">ok: [demo]</font><br> 
 +<font style="color: rgb(00, 0)">TASK [***www*** : 2) Von der bestehenden originalen Konfigurationsdatei '/etc/httpd/conf/httpd.conf' ein Backup '/etc/httpd/conf/httpd.conf.orig' erstellen] *************************************************************************************************************</font> 
 +<font style="color: rgb(196160, 0)">changed: [demo]</font><br
 +<font style="color: rgb(00, 0)">TASK [***www*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen] *************************************</font> 
 +<font style="color: rgb(196160, 0)">changed[demo]</font><br> 
 +<font style="color: rgb(000)">TASK [***www*** : default-Homepage an Ort und Stelle kopieren] **********************************************************************</font> 
 +<font style="color: rgb(196, 160, 0)">changed: [demo]</font><br> 
 +<font style="color: rgb(0, 0, 0)">TASK [***www*** : Sicherstellen dass der  Daemon 'httpd' (beim Systemstart) gestartet wird und läuft] *******************************</font> 
 +<font style="color: rgb(196, 160, 0)">changed: [demo]</font><br> 
 +<font style="color: rgb(0, 0, 0)">TASK [***www*** Paketfilter anpassen und Port 80 (HTTPöffnen] *******************************************************************</font> 
 +<font style="color: rgb(196, 160, 0)">changed: [demo]</font><br> 
 +<font style="color: rgb(0, 0, 0)">PLAY RECAP *************************************************************************************************************************************</font> 
 +<font style="color: rgb(196, 160, 0)">demo        </font><font style="color: rgb(0, 0, 0)">: </font><font style="color: rgb(25, 100, 5)">ok=16    </font><font style="color: rgb(196, 160, 0)">changed=11    </font><font style="color: rgb(0, 0, 0)">unreachable=0    failed=0    skipped=0    rescued=0    ignored=0</font><br></pre>
 </html> </html>
  
-=== Ergebnis === +==== Rollen (Beispiele) ==== 
-Nun haben alle unsere eigenen definierten Freifunk Knoten haben nun auf der **[[https://map.ffmuc.net/#!/de/map/18e829a922ed|Freifunk München Karte]]** die aktualisierten GeoDatenZum anderen ist der Administrative Aufwand entsprechend überschaubar. +  **[[centos:rsynd_c8#automatisierter_weg_mit_hilfe_von_ansible|rsync]]**//-Server unter CentOS 8.x einrichten/
- +  * **[[centos:pxe_c8:tftp#automatisierter_weg_mit_hilfe_von_ansible|tftp]]**//-Server unter CentOS 8.x einrichten//
-<WRAP center round info 80%> +
-Zum Thema administrativer Aufwand wollen wir uns kurz noch ein kleines Rechenbeispiel ansehen. Nehmen wir mal an, wie hätten eine etwas größere Installation mit folgenden Eckdaten: +
-  * **145** Zeilen (ohne Variablen): +
-    * mit **76** Hosts +
-    * und **13** Unter-/Gruppen +
- +
-Bei durchschnittlich 15 Variablen pro Host und 5 Variablen pro Gruppe ergäbe das eine Inventory-Datei mit +
-  * **145** Zeilen (ohne Variablen)145 +
-    * mit **76** Hosts ~15 Variablen pro Host1.140  +
-    und **13** Unter-/Gruppen ~5 Variablen je Gruppe: 65  +
-ergäbe dies eine Inventory-Datei mit **__1.350__** Zeilen. 8-o +
-</WRAP> +
- +
- +
- +
-/* +
- +
-https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html +
-https://docs.ansible.com/ansible/latest/plugins/inventory/yaml.html +
- +
-https://ansible-tips-and-tricks.readthedocs.io/en/latest/ansible/inventory/ +
- +
- +
-FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME  +
- +
  
 +====== Links ======
 +  * **[[centos:ansible:first|zurück zum Kapitel "Erste Schritte Rund um Ansible"]] <= **
 +  * ** [[centos:ansible:start|Zurück zur "Ansible"-Übersicht]]**
 +  * **[[wiki:start|Zurück zu >>Projekte und Themenkapitel<<]]**
 +  * **[[http://dokuwiki.nausch.org/doku.php/|Zurück zur Startseite]]**
 /* https://gerardnico.com/infra/ansible/start */ /* https://gerardnico.com/infra/ansible/start */