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
Nächste ÜberarbeitungBeide Seiten der Revision
centos:ansible:detail [11.01.2020 21:44. ] – [Ergebnis] djangocentos:ansible:detail [29.06.2020 21:42. ] – Ansible - Erweiterte Konfigurationsbeispiele django
Zeile 152: Zeile 152:
  
 /* 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.*/ /* 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 === === playbook ===
Zeile 202: Zeile 204:
 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: 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 ausgerdrückt Standard-WLAN-Access-Points((**A**cess **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.+  * **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**.   * **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**.
  
Zeile 433: Zeile 435:
  
 https://ansible-tips-and-tricks.readthedocs.io/en/latest/ansible/inventory/ 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.
  
-FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME +  * **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 ====
 +In folgendem Konfigurationsbeispiel wollen wir uns zu folgendem Szenario eine handelbare Lösung genauer betrachten. Wir gehen dabei von folgendem Einsatzszenario aus:
 +
 +=== 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.
 +</WRAP>
 +
 +=== Lösung ===
 +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.
 +
 +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 werden. So 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.
 +
 +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''**     
 +
 +----
 +
 +== 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 bzw. importiert.
 +   $ vim ~/ansible/site.yml 
 +
 +<file yml ~/ansible/site.yml>--- # Start des systemweiten Playbooks site.yml
 +- import_playbook: web.yml # Playbook zum Konfigurieren unseres Webservers einbinden
 +
 +... # Ende unseres systemweiten Playbooks
 +</file>
 +
 +----
 +
 +== 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 
 +
 +<file yml web.yml>--- # Start des Playbooks für den Web-Server
 +- hosts: www
 +
 +  roles:
 +    - base   # Basiskonfiguration (User anlegen)
 +    - chrony # Installation und Konfiguration NTP-Client
 +    - www    # Installation und Konfiguration Apache Webserver
 +
 +... # Start des Playbooks für den Web-Server
 +</file>
 +
 +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.
 +   $ cd ~/ansible/roles
 +   $ cp -avr common/ base/
 +
 +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''**
 +   $ vim ~/ansible/roles/base/tasks/main.yml
 +
 +<file yml ~/ansible/roles/base/tasks/main.yml>--- # Grundlegende Konfiguration für alle Hosts
 +  - name: "***base*** : Gruppe für (WEB-Entwickler) '{{ createuser }}' erstellen"
 +    group: # https://docs.ansible.com/ansible/latest/modules/group_module.html
 +      name: '{{ createuser }}'
 +      gid: '{{ createguid }}'
 +      state: present
 +
 +  - name: "***base*** : WEB-Admin Nutzerkonto für den User '{{ createuser }}' mit frn zugehörigen UID '{{ createguid }}' anlegen un der Gruppe '{{ createuser }}' zuordnen."
 +    user: # https://docs.ansible.com/ansible/latest/modules/user_module.html
 +      name: '{{ createuser }}'
 +      comment: '{{ createusername }}'
 +      uid: '{{ createguid }}'
 +      group: '{{ createuser }}'
 +      state: present
 +
 +  - name: "***base*** : Initiales Passwort für den WEB-Admin '{{ createuser }}' hinterlegen"
 +    shell: # https://docs.ansible.com/ansible/latest/modules/shell_module.html
 +      cmd: usermod -p $(echo '{{ createpassword }}' | openssl passwd -1 -stdin) {{ createuser }}
 +</file>
 +
 +Wie wir sehen, beinhaltet diese Datei nur noch die Definition der **tasks** aber keine Sitespezifischen Variablen, da wir diese in eine separate Date auslagern werden. Wir könnten als jederzeit diese Date auf andere Installationsumgebungen portieren oder an interessierte Adminkollegen weitergeben!
 +
 +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 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/
 +
 +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.
 +   $ vim ~/ansible/roles/chrony/tasks/main.yml
 +
 +<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>
 +
 +Die vier **tasks** hinterlegen wire dann anschließend in der zugehörigen YML-Datei.
 +   $ vim ~/ansible/roles/chrony/tasks/install.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>
 +
 +   $ vim ~/ansible/roles/chrony/tasks/config-backup.yml
 +<file yml ~/ansible/roles/chrony/tasks/config-backup.yml>---
 +  - name: "***chrony*** : 1) Überprüfen ob das Backup der Konfigurationsdatei '{{ config_file }}' bereits existiert"
 +    stat: # https://docs.ansible.com/ansible/latest/modules/stat_module.html 
 +      path: /etc/chrony.conf.orig
 +    register: stat_result
 +
 +  - name: "***chrony*** : 2) Von der bestehenden originalen Konfigurationsdatei '{{ config_file }}' ein Backup '{{ config_file }}'.orig erstellen"
 +    copy: # https://docs.ansible.com/ansible/latest/modules/copy_module.html
 +      remote_src: yes
 +      src: '{{ config_file }}'
 +      dest: /etc/chrony.conf.orig
 +    when: stat_result.stat.exists == False
 +</file>
 +
 +   $ vim ~/ansible/roles/chrony/tasks/configure.yml
 +<file yml ~/ansible/roles/chrony/tasks/configure.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>
 +
 +Das zugehörige Template für die Konfigurationsdatei legen wir im zugehörigen Verzeichnis **''~/ansible/roles/chrony/templates''** ab.
 +   $ vim ~/ansible/roles/chrony/templates/chrony-client.conf.j2
 +
 +<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 }}
 +
 +# Ignore stratum in source selection
 +{{ chrony_stratumweight }}
 +
 +# Record the rate at which the system clock gains/losses time.
 +driftfile /var/lib/chrony/drift
 +
 +# Allow the system clock to be stepped in the first three updates
 +# if its offset is larger than 1 second.
 +makestep 1.0 3
 +
 +# Enable kernel synchronization of the real-time clock (RTC).
 +rtcsync
 +
 +# In first three updates step the system clock instead of slew
 +# if the adjustment is larger than 10 seconds.
 +{{ chrony_makestep }}
 +
 +# Enable hardware timestamping on all interfaces that support it.
 +#hwtimestamp *
 +
 +# Increase the minimum number of selectable sources required to adjust
 +# the system clock.
 +#minsources 2
 +
 +# Allow NTP client access from local network.
 +#allow 192.168.0.0/16
 +
 +# Serve time even if not synchronized to a time source.
 +#local stratum 10
 +
 +# Specify file containing keys for NTP authentication.
 +keyfile /etc/chrony.keys
 +
 +# Get TAI-UTC offset and leap seconds from the system tz database.
 +leapsectz right/UTC
 +
 +# Specify directory for log files.
 +logdir /var/log/chrony
 +
 +# Select which information is logged.
 +#log measurements statistics tracking
 +</file>
 +
 +Der **task** zum Starten des Daemon legen wir im Verzeichnis **''task''** ab.
 +   $ vim ~/ansible/roles/chrony/tasks/service.yml
 +<file yml ~/ansible/roles/chrony/tasks/service.yml>---
 +  - name: "***chrony*** : Sicherstellen dass der  Daemon '{{ daemon_name }}' (beim Systemstart) gestartet wird und läuft"
 +    service: # https://docs.ansible.com/ansible/latest/modules/service_module.html 
 +      name: chronyd 
 +      state: started 
 +      enabled: yes
 +</file>
 +
 +Zu guter letzt benötigen wir auch hier eine zur Rolle gehörige Parameter-Datei mit den Definitionen der Variablen.
 +   $ 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>
 +
 +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!
 +
 +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.
 +   $ cd ~/ansible/roles
 +   $ 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
 +- include: install.yml       # Installation
 +- include: config-backup.yml # original-Konfig sichern
 +- include: configure.yml     # Konfiguration
 +- include: content.yml       # Initiale Webseite befüllen
 +- include: service.yml       # Service starten
 +</file>
 +
 +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
 +
 +<file yml ~/ansible/roles/www/tasks/install.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>
 +
 +Ähnlich verfahren wir mit dem **task** zum Sichern der originalen Konfigurationsdatei **''config-backup.yml''** sowie zum Konfigurieren des Daemon **''configure.yml''**.
 +   $ cp ~/ansible/roles/chrony/tasks/config-backup.yml ~/ansible/roles/www/tasks/config-backup.yml
 +   $ vim ~/ansible/roles/www/tasks/config-backup.yml
 +<file yml ~/ansible/roles/www/tasks/config-backup.yml>---
 +  - name: "***www*** : 1) Überprüfen ob das Backup der Konfigurationsdatei '{{ config_file }}' bereits existiert"
 +    stat: # https://docs.ansible.com/ansible/latest/modules/stat_module.html 
 +      path: '{{ backup_file }}'
 +    register: stat_result
 +
 +  - 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>
 +
 +   $ cp ~/ansible/roles/chrony/tasks/configure.yml ~/ansible/roles/www/tasks/configure.yml
 +   $ vim ~/ansible/roles/www/tasks/configure.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>
 +
 +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
 +<file yml ~/ansible/roles/www/vars/main.yml>--- # Definition der rollenspezifische Variablen zum Apache-Webserver httpd
 +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>
 +
 +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.
 +   $ cp ~/ansible/roles/chrony/tasks/service.yml ~/ansible/roles/www/tasks/service.yml
 +   $ vim ~/ansible/roles/www/tasks/service.yml
 +<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 
 +      name: httpd
 +      state: started
 +      enabled: yes
 +
 +  - name: "***www*** : Paketfilter anpassen und Port 80 (HTTP) öffnen"
 +    firewalld: # https://docs.ansible.com/ansible/latest/modules/firewalld_module.html
 +      service: http
 +      permanent: yes
 +      state: enabled
 +</file>
 +
 +Wir haben also ein modular aufgebautes Installationsplaybook für unseren Webserver, mit 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''**.
 +
 +<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>
 +
 +<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. 
 +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>
 +
 +----
 +=== Script ausführen ===
 +Zum Schluss rufen wir unser erstes **role**-based Playbook auf uns installieren und konfigurieren unseren Webserver.
 +   $ ansible-playbook site.yml 
 +
 +<html><pre class="code">
 +<font style="color: rgb(0, 0, 0)">BECOME password: 
 +
 +PLAY [demo] *************************************************************************************************************************
 +
 +TASK [Gathering Facts] **************************************************************************************************************</font>
 +<font style="color: rgb(25, 100, 5)">ok: [demo]</font><br>
 +<font style="color: rgb(0, 0, 0)">TASK [***base*** : Gruppe für (WEB-Entwickler) 'ruben' erstellen] *******************************************************************</font>
 +<font style="color: rgb(196, 160, 0)">changed: [demo]</font><br>
 +<font style="color: rgb(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>
 +<font style="color: rgb(196, 160, 0)">changed: [demo]</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(196, 160, 0)">changed: [demo]</font><br>
 +<font style="color: rgb(0, 0, 0)">TASK [***chrony*** : Installation des Deamon 'chrony' (in der aktuellsten Version)] *************************************************</font>
 +<font style="color: rgb(25, 100, 5)">ok: [demo]</font><br>
 +<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(25, 100, 5)">ok: [demo]</font><br>
 +<font style="color: rgb(0, 0, 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)">changed: [demo]</font><br>
 +<font style="color: rgb(0, 0, 0)">TASK [***chrony*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen] **********************************</font>
 +<font style="color: rgb(196, 160, 0)">changed: [demo]</font><br>
 +<font style="color: rgb(0, 0, 0)">TASK [***chrony*** : Sicherstellen dass der  Daemon 'chrony' (beim Systemstart) gestartet wird und läuft] ***************************</font>
 +<font style="color: rgb(25, 100, 5)">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(0, 0, 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(196, 160, 0)">changed: [demo]</font><br>
 +<font style="color: rgb(0, 0, 0)">TASK [***www*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen] *************************************</font>
 +<font style="color: rgb(196, 160, 0)">changed: [demo]</font><br>
 +<font style="color: rgb(0, 0, 0)">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>
  
 +====== 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 */