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 [29.06.2020 21:38. ] – [Script ausführen] 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}} \\ \\ 
  
-<WRAP center round todo 55%> +<WRAP center round alert 60%> 
-**Seite in der Entstehung, noch nicht aktuell! Wird laufend aktualisiert!**+Artikel befindet sich aktuell in der Überarbeitung!
 </WRAP> </WRAP>
  
  
-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.  
- 
-===== 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. 
- 
-{{page>centos:ansible:hosts&nofooter&showheader}} 
- 
- 
-==== ~/ansible/hosts.yml ==== 
-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 der Ansible-Konfigurationsdatei **''/etc/ansible/ansible.cfg''** zeigt zu Beginn der default-Eintrag auf die vorgenannte Datei **[[#etc_ansible_hosts|/etc/ansible/hosts]]**. 
- 
-<code> ... 
- 
-[defaults] 
- 
-# some basic default values... 
- 
-#inventory      = /etc/ansible/hosts 
-... 
-</code> 
- 
-Unsere erweiterte YAML-Konfigurationsdatei für die Hosts wolen wir aber künftig in der Ansible-Administationsumgebung unseres Admin-Users vorhalten und pflegen. Im Beispiel unseres Adminusers **django** wäre dies entsprechend der Pfad **''/home/django/ansible/hosts.yml''** 
- 
-Wir hinterlegen also dort, dass zukünftig die Inventory-Datei **''hosts.yml''** eingelesen und ausgewertet werden soll. 
-   # vim /etc/ansible/ansible.cfg 
- 
-<code>[defaults] 
- 
-# some basic default values... 
- 
-# Django : 2020-01-01  
-# default: #inventory      = /etc/ansible/hosts 
-inventory      = /home/django/ansible/hosts.yml 
-</code> 
- 
-=== inventory - Beispiel === 
-Dort legen wir uns unsere erweiterte Host-Datei im YAML-Format an. 
-   $ vim /home/django/ansible/hosts.yml> 
- 
-<file bash /home/django/ansible/hosts.yml>--- #YAML start syntax (optional)  
-all: 
-  hosts:                                                                       # nicht zugeordnete Hosts 
-    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:                                                                    # Variablen, die 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  
-          hostname: ffplieninggbwegod                                          # Hostspezifische Informationen / Variablen 
-          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 
-          hostname: ffplieninggbwogod                                          # Hostspezifische Informationen / Variablen 
-          pretty_hostname: ff_pliening_gbw_ogod 
-          latitude: 48.198699460 
-          longitude: 11.798053090 
-          branch: stable 
-          domain: ffmuc_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 
-           hostname: ffplieninggbwdgod                                         # Hostspezifische Informationen / Variablen 
-           prettyhostname: ff_pliening_gbw_dgod 
-           latitude: 48.198671230 
-           longitude: 11.798122820 
-           branch: stable 
-           domain: ffmuc_muc_ost 
-           director: ffmuc_muc_ost 
-           modell: Ubiquiti UniFi-AC-MESH 
-           ansible_ssh_host: 2001:608:a01:102:1ae8:29ff:fec6:c8eb 
- 
-        ff_pliening_gbw_cpod:                                                  # Host 
-           hostname: ffplieninggbwcpod                                         # Hostspezifische Informationen / Variablen 
-           pretty_hostname: ff_pliening_gbw_cpod 
-           latitude: 48.198726280 
-           longitude: 11.798159030 
-           branch: stable 
-           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 
-           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> 
- 
- 
-Die YAML-Konfigurationsdatei enthält entsprechende Bemerkungen, die die einzelnen Blöcke und Funktionen ausreichend beschreiben. Wie können so individuelle und Anwendungsspezifische Lösungen abbilden.  
- 
-<WRAP center round info 100%> 
-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.  
-</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.*/ 
- 
-Zum Testen, ob die definierten Hosts in unserem **inventory**-File auch erreichbar ist, können wir mit dem Befehl **''ansible -m ping all''** überprüfen. 
- 
-=== playbook === 
-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. 
-   $ ~/ansible/08_set_location.yml 
- 
-<file bash ~/ansible/08_set_location.yml> 
---- 
-- hosts: ffmucgluon 
-  gather_facts: False 
- 
-  tasks: 
-    - name: "Set GEO location of our own ffmuc-nodes" 
-      #https://docs.ansible.com/ansible/latest/modules/raw_module.html 
-      raw: uci 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> 
- 
-=== 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: 
-   $ ansible-playbook -v 08_change_contact.yml 
- 
-<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:  
- 
-PLAY [ffmucgluon] ********************************************************************************************************************** 
- 
-<font style="color: rgb(0, 0, 0)">TASK [Update new contact-address on own ffmuc-nodes] ***********************************************************************************</font> 
-<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": []} 
-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 === 
-Alle unsere eigenen definierten Freifunk Knoten haben nun auf der **[[https://map.ffmuc.net/#!/de/map/18e829a922ed|Freifunk München Karte]]** die aktualisierten GeoDaten. 
- 
-==== Komplexere und größere Umgebungen ==== 
-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! 
- 
-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: 
- 
-  * **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. 
-  * **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**. 
- 
-In unserem Konfigurationsbeispiel haben wir folgende Komponenten und (Betriebs-)Systeme im Einsatz, woraus sich unterschiedliche Gruppenkonstellationen ergeben, die im Betrieb zum Tragen kommen bzw. verwendet werden. 
-  - **Gruppe** aller WiFi-AccessPoints mit **Gluon** **''ffmuc''**: 
-    * 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. 
-  
-{{ :centos:ansible:inventory.png?direct&900 |Bild: Übersicht einer möglichen (Infra)Struktur}} 
- 
- 
-=== inventory - Beispiel === 
-Die **Inventory**-Datei **''inventory.yml''** unseres Beispiels legen wir im Arbeitsverzeichnis unseres Ansible-Administrationshost ab. 
-   $ vim ~/ansible/inventory.yml 
- 
-<file bash ~/ansible/inventory.yml>--- #Inventory - YAML syntax  
-all: 
-  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 Host- und 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.  
- 
-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. 
- 
-Wir legen also die beiden Verzeichnisse an. 
-   $ mkdir ~/ansible/inventory/host_vars 
-   $ mkdir ~/ansible/inventory/group_vars 
- 
-Somit haben wir dann aktuell folgende Verzeichnisstruktur auf unserem Admin-/Ansible-Host. 
-<code>. 
-├── authkeys 
-├── files 
-│   ├── CentOS7 
-│   └── CentOS8 
-├── includes 
-├── inventory 
-│   ├── group_vars 
-│   └── host_vars 
-├── playbooks 
-└── templates 
-    └── chrony-client</code> 
- 
-Je **Gruppe** speichern wir also eine individuelle Datei im Verzeichnis **''~/ansible/inventory/group_vars''** ab. 
-   $ vim ~/inventory/group_vars/ffmuc.yml 
- 
-<file bash ~/inventory/group_vars/ffmuc.yml>ffmuc: 
-  ansible_ssh_port: 22 
-  ansible_ssh_user: root 
-  ansible_ssh_private_key_file: /home/django/.ssh/id_rsa4096_freifunk_2014.pub 
-  contact_info: 'Django [BOfH] | django@nausch.org | chat -> @django' 
-</file> 
- 
-Für die anderen Gruppe(n) verfahren wie ebenso. 
- 
-Je **Host** speichern wir dann jeweils eine individuelle Datei im Verzeichnis **''~/ansible/inventory/hosts_vars''** ab. 
-   $ vim ~/ansible/inventory/host_vars/ff_pliening_gbw_egod.yml 
- 
-<file bash ~/ansible/inventory/host_vars/ff_pliening_gbw_egod.yml>ff_pliening_gbw_egod: 
-  hostname: ffplieninggbwegod 
-  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</file> 
- 
-Auch für die anderen Hosts legen wir entsprechende Dateien mit den Variablen an. 
- 
-=== playbook === 
-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. 
-   $ ~/ansible/playbooks/09_set_location.yml 
- 
-<file bash ~/ansible/playbooks/09_set_location.yml> 
---- 
-- hosts: ffmuc 
-  gather_facts: False 
- 
-  tasks: 
-    - name: "Set GEO location of our own ffmuc-nodes" 
-      #https://docs.ansible.com/ansible/latest/modules/raw_module.html 
-      raw: uci 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> 
- 
-=== Script antesten === 
-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''**. 
-   $ ansible-playbook -v ~/ansible/playbooks/09_set_location.yml --list-hosts 
- 
-<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)">playbook: /home/django/ansible/playbooks/09_set_location.yml 
- 
-  play #1 (ffmuc): ffmuc TAGS: [] 
-    pattern: ['ffmuc'] 
-    hosts (6): 
-      ff_pliening_gbw_egod 
-      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 === 
-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: 
-   $ ansible-playbook -v ~/ansible/playbooks/09_set_location.yml 
- 
-<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:  
- 
-PLAY [ffmuc] *************************************************************************************************************************** 
- 
-<font style="color: rgb(0, 0, 0)">TASK [Update new contact-address on own ffmuc-nodes] ***********************************************************************************</font> 
-<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": []} 
-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 === 
-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 GeoDaten. Zum anderen ist der Administrative Aufwand entsprechend überschaubar. 
- 
-<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 Host: 1.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/ 
-https://gerardnico.com/infra/ansible/start */ 
- 
-===== Module ===== 
-==== Grundlagen ==== 
-Bevor wir nun in die Welt der **roles** bei Ansible eintauchen, werfen wir kurz noch einen Blick aufzwei gängige Szenarien: 
-  * **Bsp. 1**: \\ Hat man nur eine Aufgabe, wie z.B. den **[[centos:ansible:ffmuc-rpb4-ol|automatisierten Bau eines Freifunk-Offloaders auf Basis eines Raspberry 4B]]** zu bewältigen, liegt es natürlich nahe, ein Playbook anzulegen, in dem alle Schritte nacheinander aufgeführt werden, die zum Erledigen der Aufgabe nötig sind. Ehe man sich's vbersieht hat man am Ende ein **[[centos:ansible:ffmuc-rpb4-ol#raspi_offloader_menuyml|Playbook]]** vor Augen welches **//390//** Zeilen umfasst. Sowas kann natürlich alsbald doch sehr umfangreich und vor allem pflegeintensiv werden. 
- 
-  * **Bsp. 2**: \\ In ambitionierteren Umgebungen hat man es meist mit einer Vielzahl unterschiedlicher Systeme, wie z.B. Web-, Datenbank-, Mail-, Infrastrukturserver und/oder Loadbalancer-Systeme zu tun. In Ihren Aufgabestellungen unterscheiden sich diese doch erheblich, haben aber jedoch in aller Regel eine grundlegende Basisinstallation und Konfiguration. Die sind z.B. Definitionen zu Admin-Acounts, NTP-Client-Definitionen oder z.B. beim MTA-Relayhost. Nun könnte man natürlich auch hier pragmatisch vorgehend und ein Playbook mit diesen grundlegenden Einzelaufgaben wie z.B. **[[centos:ansible:playbooks1#benutzer_anlegen|Userkontenanlage]]** oder **[[centos:ansible:playbooks1#ntp-daemon_chrony_installieren_und_konfigurieren|NTP-Clientinstallation und -konfiguration]]** als Vorlage erstellen wollen. So eine Vorlage könnte man dann entsprechend vervielfältigen und mit den Hostspezifischen Installations- und Konfigurationsanweisung anreichern. \\ \\ Aus folgenden Gründen ist so ein Vorgehen aber nicht zu empfehlen: 
-    - Bei Änderungen an grundlegenden gemeinsamen Punkte, wie z.B. neuer Mitarbeiter, müsste man später jedes einzelne Playbook anfassen und anpassen. 
-    - Je nach Freunde am Umgang mit Ansible, kann im Arbeitsverzeichnis des Ansible-Nutzers es durch die vielen playbooks und/oder includierten Konfigurationsdateien sehr schnell unübersichtlich werden.  
-    - Daten wie Aufgaben (tasks), Variablen (vars) oder "Spezielle Aufgaben" (handlers) sind so mehrfach definiert und vorhanden, was eine fortlaufende Pflege mehr als erschwert. 
-    - Da es keine Trennung zwischen variablen Daten und den Aufgaben (tasks  und handlers) gibt, ist es sehr schwierig unser spezielles Ansible-Playbook oder auch Teile daraus wiederzuverwenden oder mit anderen zu teilen bzw. weiterzugeben. In aller Regel sind nämlich die Daten eines Playbook organisations- und firmenspezifisch, der dazu verwendete Code natürlich allgemeingültig und allgemein an- und verwendbar. Sind die Daten und der Code nun in einer großen Datei (Playbook) zusammengefasst, ist es damit nicht mehr möglich Inhalte zu teilen oder wiederzuverwenden! 
- 
-Wenn wir das Thema nun nüchtern und wertfrei betrachten werden wir feststellen, dass wir so eine Vielzahl von Systemen nicht auf dauer ohne große Aufwände mit Ansible verwalten können. Um nun diese Herausforderungen elegant zu lösen bringt uns Ansible die Funktion der Rollen (**[[https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse.html#playbooks-reuse|roles]]**) mit.  
- 
-Rollen sind im Grunde nichts anderes als Verzeichnisse, die auf eine bestimmte Art und Weise angelegt sind. Rollen folgen vordefinierten Verzeichnis-Layout-Konventionen und erwarten, dass sich debei die zugehörigen Komponenten in dem für sie vorgesehenen Verzeichnispfad befindet. Bei der Grundkonfiguration unseres Ansible-Hosts hatte wir bereits diese Verzeichnisstruktur beim Anlegen des **[[centos:ansible:first#ansibledirectory_layout|Ansible: Directory Layout]]** angelegt. 
- 
-<code>/home/ansible/ansible/roles/ 
-└── roles                          # Verzeichnis für die einzelnen (unterschiedlichen) Rollen 
-    └── common                     # Verzeichnis "role" common mit seinen entsprechenden Definitionen - Vorlage zum Kopieren 
-        ├── defaults               # Verzeichnis "defaults" 
-        │   └── main.yml           # Standardvariablen mit niedrigerer Priorität für diese Rolle 
-        ├── files                  # Verzeichnis "files" 
-        │   └── main.yml           # (Skript-)Dateien zur Verwendung als Kopier- bzw. Script-Rressource 
-        ├── handlers               # Verzeichnis "handlers" 
-        │   └── main.yml           # Datei mit den Definitionen zu den rollenspezifischen "handlers" 
-        ├── library                # Verzeichnis für benutzerdefinierte Module einer der Rolle (role) "common" 
-        ├── lookup_plugin          # Verzeichnis für weitere Arten von Plugins, wie in diesem Fall "lookup" 
-        ├── meta                   # Verzeichnis "meta" für Rollenspezifische Definitionen/Abhängigkeiten 
-        │   └── main.yml           # Datei mit Rollenspezifischen Definitionen 
-        ├── module_utils           # Verzeichnis "module_utils", die benutzerdefinierte module_utils der Rollen enthalten könnte 
-        ├── tasks                  # Verzeichnis "tasks" für kleinere Aufgabendateien 
-        │   └── main.yml           # Datei für kleinere Aufgaben, falls diese benötigt werden würden  
-        ├── templates              # Verzeichnis mit den Templates 
-        │   └── main.j2            # Template-Datei mit dem Dateisuffix/-Ende .j2 
-        └── vars                   # Verzeichnis "vars", mit den zu dieser Rolle zugeordneten Variablen 
-            └── main.yml           # Datei mit den Rollenspezifischen Variablen 
-</code> 
-Diese Kopiervorlage **''common''** brauchen wir nur noch für jede entsprechende Rolle dann kopieren, so z.B. für die Rolle **''postfix''** 
-   $ cd ~/ansible/roles 
-   $ cp -avr common/ postfix/ 
  
 ==== Konfigurationsbeispiel ==== ==== Konfigurationsbeispiel ====
Zeile 487: Zeile 12:
 === Aufgabenstellung === === 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. 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.
-</WRAP>+
  
 === Lösung === === Lösung ===
Zeile 896: Zeile 421:
  
 <WRAP center round tip 80%> <WRAP center round tip 80%>
-Abschließend kann man sich nun berechtigter Weise die Frage stzellen, 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. +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. 
 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! 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!
 </WRAP> </WRAP>
Zeile 946: Zeile 471:
 </html> </html>
  
 +==== Rollen (Beispiele) ====
 +  * **[[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//
  
-\\ \\ \\  +====== Links ====== 
- +  * **[[centos:ansible:first|zurück zum Kapitel "Erste Schritte Rund um Ansible"]] <= ** 
-FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME  +  * ** [[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 */