linux:ansible:playbook_example_11

Ansible - Erweiterte Konfigurationsbeispiel: Roles

Bild: Ansible Logo

Bevor wir nun in die Welt der roles bei Ansible eintauchen, werfen wir kurz noch einen Blick auf zwei gängige Szenarien:

  • Bsp. 1:
    Hat man nur eine Aufgabe, wie z.B. den 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 versieht hat man am Ende ein Playbook vor Augen welches 390 Zeilen umfasst. So was 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. Userkontenanlage oder 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:
    1. Bei Änderungen an grundlegenden gemeinsamen Punkte, wie z.B. neuer Mitarbeiter, müsste man später jedes einzelne Playbook anfassen und anpassen.
    2. Je nach Freunde am Umgang mit Ansible, kann im Arbeitsverzeichnis des Ansible-Nutzers es durch die vielen Playbooks und/oder inkludierten Konfigurationsdateien sehr schnell unübersichtlich werden.
    3. Daten wie Aufgaben (tasks), Variablen (vars) oder „Spezielle Aufgaben“ (handlers) sind so mehrfach definiert und vorhanden, was eine fortlaufende Pflege mehr als erschwert.
    4. 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 (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 dabei 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 Ansible: Directory Layout angelegt.

/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

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/

In folgendem Konfigurationsbeispiel wollen wir uns zu folgendem Szenario eine handelbare Lösung genauer betrachten. Wir gehen dabei von folgendem Einsatzszenario aus:

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 Sicherheitszone zutreffen. Nach der Installation des Webserver-Daemon apache soll dieser konfiguriert, die initiale Homepage Hello World installiert und zum Schluss der Webserver gestartet werden.

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 liegenden 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 definieren 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 erledigt wird
          • apache Installation und Konfiguration des Apache Webservers mit Hilfe von tasks, files und handlers

Systemweite Host/Playbook-Definition : site.yml

Zunächst erstellen und befüllen wir der Playbook-Konfigurationsdatei site_generation.yml. 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 spezifischen Playbooks werden dann hier nur noch inkludiert bzw. importiert.

 $ vim ~/ansible/playbooks/site_generation.yml 
~/ansible/playbooks/site_generation.yml
--- # Start des systemweiten Playbooks site_generation.yml
- import_playbook: web.yml # Playbook zum Konfigurieren unseres Webservers einbinden
 
... # Ende unseres systemweiten Playbooks

Webserver Host/Playbook-Definition : web_server.yml

Für die Konfiguration des Webservers an sich verwenden wir dann die Konfigurationsdatei web_server.yml; die wir in der zuvor angelegten systemweiten Konfigurationsdatei site_generation.yml inkludiert hatten. Da die Konfiguration auf allen WEB-Hosts erfolgen soll, geben wir beim Parameter 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/playbooks/web.yml 
web_server.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

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 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
~/ansible/roles/base/tasks/main.yml
--- # Grundlegende Konfiguration für alle Hosts
  - name: "***base*** : Gruppe für (WEB-Entwickler) '{{ createuser }}' erstellen"
    ansible.builtin.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."
    ansible.builtin.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"
    ansible.builtin.shell: # https://docs.ansible.com/ansible/latest/modules/shell_module.html
      cmd: usermod -p $(echo '{{ createpassword }}' | openssl passwd -1 -stdin) {{ createuser }}

Wie wir sehen, beinhaltet diese Datei nur noch die Definition der tasks aber keine Sitespezifischen Variablen, da wir diese in eine separate Date i auslagern werden. Wir könnten als jederzeit diese Datei auf andere Installationsumgebungen portieren oder an interessierte Adminkollegen weitergeben!

Natürlich benötigen wir nun die Definition der Rollenspezifischen Variablen, die je Rolle hier ~/ansible/roles/base/vars/main.yml abzulegen sind.

 $ vim ~/ansible/roles/base/vars/main.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!)

Da wir dort ein Passwort vorhalten, werden wir Dank unserer Ansible-Vault-Konfiguration diese Datei nun verschlüsseln.

 $ ansyble-vault encrypt ~/ansible/roles/base/vars/main.yml

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 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 inkludieren werden.

 $ vim ~/ansible/roles/chrony/tasks/main.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

Die vier tasks hinterlegen wir dann anschließend in der zugehörigen YML-Datei.

 $ vim ~/ansible/roles/chrony/tasks/install.yml
~/ansible/roles/chrony/tasks/install.yml
---
  - name: "***chrony*** : Installation des Deamon '{{ daemon_name }}' (in der aktuellsten Version)"
    ansible.builtin.dnf: 
    #https://docs.ansible.com/ansible/latest/modules/dnf_module.html
      name: '{{ daemon_name }}'
      state: latest
 $ vim ~/ansible/roles/chrony/tasks/config-backup.yml
~/ansible/roles/chrony/tasks/config-backup.yml
---
  - name: "***chrony*** : 1) Überprüfen ob das Backup der Konfigurationsdatei '{{ config_file }}' bereits existiert"
    ansible.builtin.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"
    ansible.builtin.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
 $ vim ~/ansible/roles/chrony/tasks/configure.yml
~/ansible/roles/chrony/tasks/configure.yml
---
  - name: "***chrony*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen"
    ansible.builtin.template: # https://docs.ansible.com/ansible/latest/modules/template_module.html 
      src: templates/chrony-client.conf.j2 
      dest: "{{ config_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
~/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

Der task zum Starten des Daemon legen wir im Verzeichnis task ab.

 $ vim ~/ansible/roles/chrony/tasks/service.yml
~/ansible/roles/chrony/tasks/service.yml
---
  - name: "***chrony*** : Sicherstellen dass der  Daemon '{{ daemon_name }}' (beim Systemstart) gestartet wird und läuft"
    ansible.builtin.service: # https://docs.ansible.com/ansible/latest/modules/service_module.html 
      name: chronyd 
      state: started 
      enabled: yes

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
~/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"

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
~/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

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
~/ansible/roles/www/tasks/install.yml
---
  - name: "***www*** : Installation des Deamon '{{ daemon_name }}' (in der aktuellsten Version)"
    ansible.builtin.dnf:
    #https://docs.ansible.com/ansible/latest/modules/dnf_module.html
      name: '{{ daemon_name }}'
      state: latest

Ä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
~/ansible/roles/www/tasks/config-backup.yml
---
  - name: "***www*** : 1) Überprüfen ob das Backup der Konfigurationsdatei '{{ config_file }}' bereits existiert"
    ansible.builtin.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
 $ cp ~/ansible/roles/chrony/tasks/configure.yml ~/ansible/roles/www/tasks/configure.yml
 $ vim ~/ansible/roles/www/tasks/configure.yml
~/ansible/roles/www/tasks/configure.yml
---
  - name: "***www*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen"
    ansible.builtin.template: # https://docs.ansible.com/ansible/latest/modules/template_module.html 
      src: templates/httpd-server.conf.j2
      dest: "{{ config_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
~/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"

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
~/ansible/roles/www/tasks/service.yml
---
  - name: "***www*** : Sicherstellen dass der  Daemon '{{ daemon_name }}' (beim Systemstart) gestartet wird und läuft"
    ansible.builtin.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"
    ansible.builtin.firewalld: # https://docs.ansible.com/ansible/latest/modules/firewalld_module.html
      service: http
      permanent: yes
      state: enabled

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.

/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

Script ausführen

Zum Schluss rufen wir unser erstes role-based Playbook auf uns installieren und konfigurieren unseren Webserver.

 $ ansible-playbook site.yml 

BECOME password: 

PLAY [demo] *****************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************
ok: [demo]
TASK [***base*** : Gruppe für (WEB-Entwickler) 'ruben' erstellen] *********************************************************************************************** changed: [demo]
TASK [***base*** : WEB-Admin Nutzerkonto für den User 'ruben' mit frn zugehörigen UID '1010' anlegen un der Gruppe 'ruben' zuordnen.] *************************** changed: [demo]
TASK [***base*** : Initiales Passwort für den WEB-Admin 'ruben' hinterlegen] ************************************************************************************ changed: [demo]
TASK [***chrony*** : Installation des Deamon 'chrony' (in der aktuellsten Version)] ***************************************************************************** ok: [demo]
TASK [***chrony*** : 1) Überprüfen ob das Backup der Konfigurationsdatei '/etc/chrony.conf' bereits existiert] ************************************************** ok: [demo]
TASK [***chrony*** : 2) Von der bestehenden originalen Konfigurationsdatei '/etc/chrony.conf' ein Backup '/etc/chrony.conf'.orig erstellen] ********************* changed: [demo]
TASK [***chrony*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen] ************************************************************** changed: [demo]
TASK [***chrony*** : Sicherstellen dass der Daemon 'chrony' (beim Systemstart) gestartet wird und läuft] ******************************************************* ok: [demo]
TASK [***www*** : Installation des Deamon 'httpd' (in der aktuellsten Version)] ********************************************************************************* changed: [demo]
TASK [***www*** : 1) Überprüfen ob das Backup der Konfigurationsdatei '/etc/httpd/conf/httpd.conf' bereits existiert] ******************************************* ok: [demo]
TASK [***www*** : 2) Von der bestehenden originalen Konfigurationsdatei '/etc/httpd/conf/httpd.conf' ein Backup '/etc/httpd/conf/httpd.conf.orig' erstellen] **** changed: [demo]
TASK [***www*** : Template Konfigurationsdatei an Ort und Stelle kopieren und Variablen setzen] ***************************************************************** changed: [demo]
TASK [***www*** : default-Homepage an Ort und Stelle kopieren] ************************************************************************************************** changed: [demo]
TASK [***www*** : Sicherstellen dass der Daemon 'httpd' (beim Systemstart) gestartet wird und läuft] *********************************************************** changed: [demo]
TASK [***www*** : Paketfilter anpassen und Port 80 (HTTP) öffnen] *********************************************************************************************** changed: [demo]
PLAY RECAP ****************************************************************************************************************************************************** demo : ok=16 changed=11 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

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 Teile des Codes wieder zu verwenden, als wenn man eine große Datei verwenden würde in der alle Einzelschritte selektiv aufgeführt sind!

Links

Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
  • linux/ansible/playbook_example_11.txt
  • Zuletzt geändert: 27.09.2022 15:54.
  • von django