In der Welt von Ansible sind Playbooks ein zentrales Werkzeug zur Automatisierung von IT-Aufgaben. Sie bestehen aus sogenannten "plays", die eine Sammlung von Aufgaben (Tasks) definieren, die gegen definierte Hosts ausgeführt werden. Doch bei der Ausführung komplexer Playbooks stellt sich häufig die Frage: Wie beeinflusst Ansible die Reihenfolge, in der diese Aufgaben auf den Hosts ausgeführt werden? Diese Frage wird besonders relevant, wenn eine bestimmte Reihenfolge oder Einschränkung der Ausführung gewünscht ist.
Standardmäßig folgt Ansible der Reihenfolge, wie Hosts im Inventar definiert sind. In den meisten einfachen Szenarien wird die Reihenfolge der Hosts beibehalten, die im Inventar angegeben ist. In komplexeren Fällen jedoch verwendet Ansible möglicherweise andere Algorithmen, um die Hosts auszuwählen, was zu einer unvorhersehbaren Reihenfolge führen kann. Hier bietet die order-Eigenschaft eine Möglichkeit, diese Reihenfolge explizit festzulegen. Sie ermöglicht es, die Ausführungsreihenfolge der Hosts auf verschiedene Arten zu beeinflussen:
-
inventory: Dies ist der Standardmodus und entspricht der Reihenfolge im Inventar.
-
reverse_inventory: Hier wird die Reihenfolge des Inventars umgekehrt.
-
sorted: Die Hosts werden alphabetisch nach ihrem Namen sortiert.
-
reverse_sorted: Die Hosts werden in umgekehrter alphabetischer Reihenfolge ausgeführt.
-
shuffle: Eine zufällige Reihenfolge wird bei jeder Ausführung verwendet.
Ein Beispiel zur Konfiguration der order-Eigenschaft könnte folgendermaßen aussehen:
Doch was passiert, wenn nur bestimmte Hosts eine Aufgabe ausführen sollen? In einigen Szenarien, etwa bei der Aktualisierung von Datenbankschemas, möchte man sicherstellen, dass eine Aufgabe nur auf einem einzigen Host innerhalb eines Clusters ausgeführt wird. Ansible bietet dafür die run_once-Eigenschaft, die die Aufgabe nur einmal pro Hosts-Batch ausführt. Ein Beispiel für den Einsatz von run_once wäre:
Das run_once: true sorgt dafür, dass der Befehl nur auf einem einzelnen Host innerhalb des Batches ausgeführt wird, was insbesondere bei Datenbankoperationen wichtig sein kann. Es gibt jedoch auch die Möglichkeit, die Aufgabe auf einem spezifischen Host statt auf dem ersten Host im Batch auszuführen. Dies wird durch die delegate_to-Eigenschaft ermöglicht:
In diesem Fall wird der Befehl auf dem Host db1.example.com ausgeführt. Eine wichtige Anmerkung: Aufgaben, die mit run_once markiert sind, werden innerhalb jedes Batches nur einmal ausgeführt. Wenn beispielsweise serial auf 5 gesetzt ist und das Inventar 10 Hosts enthält, gibt es zwei Batches, sodass der Befehl zweimal ausgeführt wird, und zwar für den ersten Host jedes Batches. Um dieses Verhalten zu vermeiden und eine Aufgabe nur einmal auszuführen, unabhängig von der Batchgröße, sollte die when-Bedingung verwendet werden.
Ein weiteres wichtiges Konzept in Ansible ist das Throttle-Schlüsselwort, das verwendet wird, um die Anzahl der parallelen Arbeitsprozesse für eine bestimmte Aufgabe zu beschränken. Dies kann bei ressourcenintensiven Aufgaben wie CPU- oder Speicheroperationen erforderlich sein, bei denen nur eine begrenzte Anzahl von Prozessen gleichzeitig ausgeführt werden sollte. Ein Beispiel:
Dies stellt sicher, dass nur ein Worker gleichzeitig die Aufgabe ausführt.
Die Struktur von Playbooks ist ebenfalls entscheidend für ihre Wartbarkeit und Wiederverwendbarkeit. Ein Playbook besteht in der Regel aus mehreren Teilen, die es ermöglichen, eine Vielzahl von Aufgaben effizient zu automatisieren. Ein einfaches Beispiel für ein Playbook könnte wie folgt aussehen:
Ein solches Playbook enthält nicht nur Aufgaben, sondern auch Variablen, Rollen und Handler, die es ermöglichen, den Playbook-Code zu strukturieren und wiederverwendbar zu machen. Variablen wie username und password ermöglichen eine dynamische Anpassung des Playbooks, während Rollen und Handler für wiederkehrende Aufgaben wie die Installation von Java oder das Neustarten eines Dienstes zuständig sind. Zudem können Aufgaben durch tags kategorisiert werden, sodass sie gezielt ausgeführt oder übersprungen werden können.
Ein weiteres zentrales Element von Ansible Playbooks sind Variablen. Sie ermöglichen es, dynamische Parameter zu definieren, die dann im Playbook verwendet werden. Diese Variablen können zur Laufzeit über die Kommandozeile gesetzt oder aus den Ergebnissen von Aufgaben ermittelt werden. Mit der Option --extra-vars kann beispielsweise der Wert einer Variablen überschrieben werden, was die Flexibilität von Playbooks deutlich erhöht.
Ein weiteres fundamentales Konzept in Ansible sind Rollen. Diese erlauben es, wiederkehrende Aufgaben zu bündeln und sie in verschiedenen Playbooks wiederzuverwenden. Dies spart nicht nur Zeit, sondern trägt auch zur Vereinheitlichung und besseren Wartbarkeit von Playbooks bei. Eine Rolle könnte beispielsweise die Installation eines bestimmten Datenbankmanagementsystems oder Webservers umfassen, die dann in verschiedenen Projekten eingesetzt werden kann.
Wie man mit Bedingungsausdrücken in Ansible arbeitet und ihre Anwendung in Playbooks versteht
In Ansible wird eine der zentralen Komponenten zur Steuerung des Ablaufs von Playbooks der Bedingungsausdruck ("conditional"). Er ermöglicht es, Aufgaben nur dann auszuführen, wenn bestimmte Bedingungen erfüllt sind. Diese Ausdrücke sind besonders nützlich, um Aufgaben an die jeweilige Systemumgebung anzupassen, wie etwa beim Installieren von Software auf verschiedenen Distributionen oder beim Ausführen von Aufgaben basierend auf dem Erfolg oder Misserfolg früherer Aufgaben.
Ein häufiger Einsatzbereich für Bedingungsausdrücke ist das Verwalten von Softwareinstallationen, die je nach Betriebssystem unterschiedlich sein können. Ein Beispiel könnte die Installation von Nginx auf verschiedenen Linux-Distributionen sein. So könnte ein Playbook in Ansible aussehen, das je nach Betriebssystem entweder den Paketmanager dnf für Fedora oder apt für Debian verwendet:
In diesem Beispiel überprüft Ansible die Variable ansible_facts['distribution'], die die Distribution des Zielsystems enthält. Auf dieser Grundlage wird dann entschieden, welcher Paketmanager zum Einsatz kommt. Dies ist ein einfaches, aber sehr effektives Beispiel für den Einsatz von Bedingungsausdrücken in Ansible.
Ein weiteres häufiges Szenario ist die Verwendung von Bedingungsausdrücken mit registrierten Variablen. Diese Variablen speichern das Ergebnis von Aufgaben, und anhand dieses Ergebnisses können nachfolgende Aufgaben bedingt ausgeführt oder übersprungen werden. Wenn zum Beispiel eine Datei existiert, soll eine nachfolgende Aufgabe sie kopieren, andernfalls wird die Aufgabe übersprungen.
In diesem Beispiel wird mit register das Ergebnis der Aufgabe in der Variablen file_exists gespeichert. Falls die Datei nicht existiert, wird die Bedingung when: file_exists is failed wahr und die Datei wird kopiert. Wäre die Datei bereits vorhanden, würde die Aufgabe übersprungen werden. Der Einsatz von ignore_errors: yes sorgt dafür, dass die Ausführung fortgesetzt wird, selbst wenn die Überprüfung fehlschlägt.
Neben registrierten Variablen kann man auch mit Standardvariablen Bedingungen definieren. Ein einfaches Beispiel könnte sein, eine Aufgabe nur dann auszuführen, wenn eine bestimmte Bedingung erfüllt ist. Zum Beispiel, wenn ein Wert einer Variablen special auf false gesetzt ist:
Wenn die Variable special den Wert false hat, wird die Aufgabe ausgeführt. Sollte die Variable jedoch auf true gesetzt werden, wird die Aufgabe übersprungen. Dies kann durch Übersteuerung der Variablen mit der Option --extra-vars beim Ausführen des Playbooks erfolgen.
Neben einfachen Aufgaben können Bedingungen auch in Imports und Includes von Playbooks verwendet werden. Wenn man beispielsweise ein Playbook nur dann importieren möchte, wenn eine bestimmte Bedingung erfüllt ist, könnte dies folgendermaßen aussehen:
Hier wird das Playbook db_tasks.yaml nur dann eingebunden, wenn die Bedingung erfüllt ist, dass host_type den Wert db hat. Bei der Verwendung von include_tasks wird die Bedingung nur auf den einzelnen Task angewendet, nicht jedoch auf die gesamten Aufgaben des importierten Playbooks:
Eine weiterführende Anwendung von Bedingungen findet sich bei der Verwendung von Rollen. Rollen sind eine weitere Möglichkeit, Aufgaben in Ansible zu organisieren, und auch bei der Zuweisung von Rollen kann eine Bedingung zum Einsatz kommen. So kann eine Rolle nur dann angewendet werden, wenn ein bestimmter Hosttyp vorliegt:
Darüber hinaus unterstützt Ansible Jinja2-Ausdrücke in Bedingungen. Diese Ausdrücke ermöglichen komplexere Vergleiche und Logik. Zum Beispiel:
-
==vergleicht zwei Objekte auf Gleichheit -
!=vergleicht zwei Objekte auf Ungleichheit -
>prüft, ob der linke Wert größer als der rechte ist -
<=prüft, ob der linke Wert kleiner oder gleich dem rechten Wert ist
Auch logische Operatoren wie and, or und not können verwendet werden, um komplexe Bedingungen zu bilden. So könnte man beispielsweise sicherstellen, dass sowohl der Name als auch das Alter eines Benutzers bestimmte Anforderungen erfüllen:
Ansible bietet auch spezielle Operatoren wie in (um zu testen, ob ein Element in einer Liste vorhanden ist) oder is (um den Typ eines Objekts zu überprüfen). Auch Filter können in Jinja2-Ausdrücken verwendet werden, um beispielsweise IP-Adressen aus einer Liste zu extrahieren.
Abschließend lässt sich sagen, dass Bedingungsausdrücke in Ansible ein äußerst mächtiges Werkzeug darstellen, um die Ausführung von Aufgaben und Playbooks präzise zu steuern. Sie ermöglichen eine hohe Flexibilität und Anpassungsfähigkeit, die in komplexeren Automatisierungsszenarien unverzichtbar sind. Ein gutes Verständnis der verschiedenen Arten von Bedingungen und deren Anwendung in unterschiedlichen Kontexten ist für die effiziente Nutzung von Ansible unerlässlich.
Wie verwalte ich Konfigurationsdateien mit Ansible?
Die Verwaltung von Konfigurationsdateien auf mehreren Hosts ist eine der häufigsten Aufgaben, mit denen Administratoren und DevOps-Teams konfrontiert sind. In Ansible gibt es verschiedene Module, die das Manipulieren von Dateien ermöglichen, etwa das Hinzufügen, Löschen oder Ändern von Zeilen in Konfigurationsdateien. Zu diesen Modulen gehören lineinfile, blockinfile, und die Verwendung von Templates, um flexibel und umgebungsspezifisch Konfigurationen zu generieren.
Das lineinfile-Modul ist eine der einfachsten Methoden, um eine einzelne Zeile in einer Datei hinzuzufügen oder zu löschen. Zum Beispiel könnte der folgende Task eine Zeile in eine Datei einfügen, wenn diese noch nicht vorhanden ist:
Dieser Task fügt den Text "Hallo Alexandra" in die Datei welcome.txt ein, falls sie noch nicht existiert. Wenn man eine Zeile entfernen möchte, kann man dies ebenfalls leicht mit dem lineinfile-Modul tun, indem man den state-Parameter auf absent setzt:
Die oben gezeigten Beispiele modifizieren eine Datei durch das Hinzufügen oder Entfernen von Zeilen. Manchmal ist es jedoch notwendig, eine Zeile an einer bestimmten Stelle in einer Datei einzufügen. Ein häufiges Beispiel hierfür sind INI-Dateien, in denen man zum Beispiel einen neuen Parameter für eine Datenbankverbindung direkt nach der server-Zeile einfügen möchte:
Das insertafter-Attribut stellt sicher, dass die neue Zeile nach der server-Zeile eingefügt wird. Wenn man stattdessen eine Zeile vor einer bestimmten Zeile einfügen möchte, kann man den Parameter insertbefore verwenden.
Für komplexere Aufgaben, bei denen mehrere Zeilen in einer Datei eingefügt werden müssen, kommt das blockinfile-Modul zum Einsatz. Mit diesem Modul lässt sich mehrzeiliger Text in eine Datei einfügen, der durch benutzerdefinierte Marker umschlossen wird. Ein Beispiel für das Hinzufügen eines mehrzeiligen Blocks könnte folgendermaßen aussehen:
Der Parameter block definiert den einzufügenden Text, wobei der |-Operator signalisiert, dass es sich um mehrzeilige Eingaben handelt. Falls der Text nicht am Ende der Datei eingefügt werden soll, können die Parameter insertafter oder insertbefore verwendet werden, um die Position des Blocks zu steuern.
Ein weiteres nützliches Feature des blockinfile-Moduls ist die Möglichkeit, benutzerdefinierte Marker zu setzen. Standardmäßig verwendet Ansible Marker wie # BEGIN/END ANSIBLE MANAGED BLOCK, doch durch den Parameter marker kann man diese Bezeichner nach eigenen Wünschen anpassen.
Neben diesen beiden Modulen gibt es eine Reihe gemeinsamer Parameter, die in vielen Ansible-Modulen verwendet werden, wie etwa owner, group und mode, aber auch spezifische Parameter wie backup (für die Erstellung eines Backups der Datei vor Änderungen) oder validate (für eine Validierung vor dem Kopieren der Datei) sind von Bedeutung. Diese Parameter bieten eine zusätzliche Flexibilität und Kontrolle beim Arbeiten mit Dateien.
Während die lineinfile- und blockinfile-Module sehr nützlich sind, wenn es darum geht, einfache Änderungen an Konfigurationsdateien vorzunehmen, wird ihre Anwendung bei komplexeren oder größeren Dateien möglicherweise unübersichtlich. In solchen Fällen bietet Ansible eine elegantere Lösung: Templates. Templates ermöglichen es, Konfigurationsdateien mit Platzhaltern zu erstellen, die zur Laufzeit durch Variablen oder Ansible-Fakten ersetzt werden.
Ein Vorteil von Templates ist die Möglichkeit, dieselbe Vorlage für unterschiedliche Umgebungen zu verwenden. So kann man beispielsweise eine application.properties-Datei für verschiedene Umgebungen wie Produktion und Testumgebung nutzen, indem man lediglich unterschiedliche Werte für bestimmte Variablen bereitstellt.
Ein einfaches Beispiel für ein Template könnte folgendermaßen aussehen:
In diesem Template werden Ansible-Fakten wie ansible_date_time.iso8601 und ansible_hostname sowie benutzerdefinierte Variablen wie username und password verwendet. Das Template wird während der Ausführung des Playbooks gerendert, wobei die Platzhalter durch die tatsächlichen Werte ersetzt werden.
Ein entscheidender Vorteil von Templates ist die zentrale Verwaltung von Konfigurationsdateien. Anstatt für jede Umgebung separate Dateien zu pflegen, reicht es aus, die Template-Datei einmal zu erstellen und für jede Umgebung nur die entsprechenden Variablen anzupassen. Dies vereinfacht die Verwaltung und reduziert das Risiko von Fehlern.
Die Verwendung von Templates kann jedoch auch Herausforderungen mit sich bringen. Es ist wichtig, sicherzustellen, dass alle benötigten Variablen korrekt definiert sind, damit die gerenderten Konfigurationsdateien korrekt funktionieren. Darüber hinaus ist es sinnvoll, die Templates in einem Versionierungssystem zu verwalten, um Änderungen nachverfolgen zu können.
Zusammenfassend lässt sich sagen, dass Ansible eine breite Palette an Möglichkeiten bietet, um Konfigurationsdateien effizient zu verwalten. Die Wahl des richtigen Moduls hängt dabei von der Komplexität der Datei und den Anforderungen der Umgebung ab. Ob einfache Zeilenänderungen mit lineinfile, das Hinzufügen von mehrzeiligem Text mit blockinfile oder die Nutzung von Templates für flexible und wiederverwendbare Konfigurationen – Ansible bietet für jede Herausforderung eine Lösung.
Wie man mit Ansible Hosts verwaltet: Einblicke und praktische Anwendung
Ansible ist ein weit verbreitetes Automatisierungswerkzeug, das für die Konfiguration und Verwaltung von Systemen verwendet wird. Es vereinfacht komplexe Aufgaben durch eine deklarative Sprache und bietet eine hohe Flexibilität. In diesem Abschnitt werden wir uns auf die wesentlichen Bestandteile von Ansible konzentrieren, insbesondere auf die Verwaltung von Hosts und die Verwendung von Inventardateien.
Wenn man mit Ansible arbeitet, gibt es grundlegende Elemente, die man kennen muss, um die Automatisierung effektiv anzuwenden. Dazu gehören die Hosts, die eine zentrale Rolle spielen. Grundsätzlich unterscheidet man in Ansible zwischen zwei Arten von Hosts: dem Steuer-Host und den verwalteten Hosts. Der Steuer-Host ist der Rechner, auf dem die Ansible-CLI ausgeführt wird. Es kann sich dabei um eine lokale Maschine, einen Server oder auch eine CI/CD-Umgebung handeln. Die verwalteten Hosts, auch als Knoten bezeichnet, sind die Server oder Geräte, die Sie mit Ansible konfigurieren möchten.
Ein weiteres zentrales Konzept von Ansible sind die Inventardateien. Diese Dateien definieren die verwalteten Hosts und deren Gruppen. Durch die Gruppierung von Hosts können spezifische Aufgaben automatisiert werden, ohne diese manuell für jeden einzelnen Host auszuführen. Zum Beispiel, wenn Sie ein Softwarepaket auf mehreren Hosts installieren möchten, müssen Sie dies nicht für jeden Host einzeln tun. Stattdessen können Sie dies für eine ganze Gruppe von Hosts tun, die Sie in einer Inventardatei definiert haben.
Die Inventardatei von Ansible kann in verschiedenen Formaten geschrieben werden, wobei das INI-Format am häufigsten verwendet wird. Hosts werden dabei entweder über ihren DNS-Namen, ihren Hostnamen oder ihre IP-Adresse definiert. Wenn Sie beispielsweise mit Vagrant virtuelle Maschinen erstellt haben, können Sie deren IP-Adressen in einer Inventardatei hinterlegen und so direkt mit Ansible auf diese Maschinen zugreifen.
Ein Beispiel einer einfachen Inventardatei könnte folgendermaßen aussehen:
In diesem Beispiel sind keine Gruppen definiert, was bedeutet, dass beide Hosts unter der Standardgruppe „ungrouped“ zusammengefasst werden. In Ansible gibt es zwei implizite Gruppen: „all“ und „ungrouped“. Alle Hosts, die in der Inventardatei definiert sind, gehören zur „all“-Gruppe. Hosts ohne spezifische Gruppe gehören zur „ungrouped“-Gruppe.
Es ist jedoch häufig notwendig, Hosts in Gruppen zu unterteilen, um unterschiedliche Aufgaben auf verschiedenen Systemen auszuführen. Wenn zum Beispiel der Host 192.168.1.92 ein Webserver und der Host 192.168.1.93 ein Datenbankserver ist, könnten Sie diese Hosts in zwei Gruppen einteilen: „webservers“ und „dbservers“. In einer INI-Datei würde dies folgendermaßen aussehen:
Diese Gruppierung ermöglicht es, spezifische Playbooks oder Aufgaben nur auf bestimmte Gruppen von Hosts anzuwenden, was die Verwaltung und Automatisierung erheblich vereinfacht. So könnten Sie beispielsweise eine Software nur auf den Webservern installieren und eine andere auf den Datenbankservern.
Die gleiche Inventardatei könnte auch im YAML-Format geschrieben werden:
Gruppen können beliebig viele Hosts enthalten, und ein Host kann auch mehreren Gruppen zugeordnet sein. In einem größeren System könnte ein Host sowohl als Webserver als auch als Datenbankserver fungieren, sodass er in beiden Gruppen erscheint. Dies bietet eine enorme Flexibilität bei der Verwaltung komplexer Infrastrukturen.
Ein weiterer wichtiger Aspekt von Ansible ist die Verwendung von Variablen innerhalb der Inventardateien. Variablen können verwendet werden, um das Verhalten von Aufgaben oder Playbooks zu beeinflussen. Sie können spezifische Variablen für jede Gruppe oder sogar für einzelne Hosts festlegen. Zum Beispiel könnte man eine Variable für die IP-Adresse oder für spezifische Konfigurationsparameter definieren. In Ansible sind Variablen ein wesentliches Mittel, um wiederverwendbare, anpassbare und skalierbare Automatisierungslösungen zu erstellen.
Zusätzlich zur Verwaltung von Hosts und Variablen können Sie Ansible dazu verwenden, verschiedene Aufgaben auf den definierten Hosts auszuführen. Eine typische Ansible-Aufgabe könnte beispielsweise das Installieren von Software, das Konfigurieren von Netzwerkeinstellungen oder das Anpassen von Dateien sein. Dank der Inventardatei und der Gruppen können Sie all diese Aufgaben auf einer Vielzahl von Maschinen gleichzeitig ausführen, wodurch Sie den Verwaltungsaufwand und mögliche Fehlerquellen reduzieren.
In Ansible sind auch der Umgang mit Verzeichnissen und Dateien von zentraler Bedeutung. Während der Automatisierung können Sie beispielsweise festlegen, dass bestimmte Verzeichnisse synchronisiert oder spezielle Shell-Skripte ausgeführt werden. In der Praxis ist es von entscheidender Bedeutung, dass Sie vor der Automatisierung alle Verzeichnisse und Dateien auf den verwalteten Hosts korrekt konfigurieren. Andernfalls könnte es zu unerwarteten Fehlern kommen, die die Funktionsweise der Automatisierung beeinträchtigen.
Darüber hinaus ist es wichtig zu betonen, dass Ansible eine idempotente Automatisierung bietet. Dies bedeutet, dass Sie eine Aufgabe mehrfach ausführen können, ohne dass dies zu unerwünschten Nebeneffekten führt. Wenn beispielsweise eine Software bereits installiert ist, wird Ansible diese nicht erneut installieren, sondern den Status überprüfen und sicherstellen, dass der gewünschte Zustand erreicht wurde.
Eine wesentliche Voraussetzung für den erfolgreichen Einsatz von Ansible ist die Sicherstellung einer stabilen Netzwerkverbindung zu den verwalteten Hosts. Ohne eine funktionierende Verbindung können keine Konfigurationen oder Automatisierungsaufgaben durchgeführt werden. Aus diesem Grund sollten Sie vor der Durchführung von Aufgaben sicherstellen, dass Sie mit den Hosts über SSH kommunizieren können. Dies lässt sich einfach testen, indem Sie sich mit den IP-Adressen der Hosts verbinden und sicherstellen, dass die Verbindung problemlos funktioniert.
Nachdem Sie alle Ihre Hosts und Gruppen definiert haben, können Sie mit der Verwaltung und Automatisierung Ihrer Infrastruktur beginnen. Wenn Sie keine weiteren Aufgaben mehr mit den virtuellen Maschinen ausführen möchten, können Sie diese sicher herunterfahren und bei Bedarf zerstören, um Speicherplatz auf Ihrem lokalen System freizugeben. Dies geschieht mithilfe von Ansible- und Vagrant-Befehlen wie „vagrant halt“ oder „vagrant destroy“.
Was bedeutet es, in schwierigen Momenten über sich hinauszuwachsen?
Wie können somatische Übungen chronische Verspannungen nachhaltig lösen?
Warum sind 2D-Nanomaterialien für die nächste Generation von Energiespeichern und elektronischen Geräten so wichtig?
Wie man karamellisierte Rhabarber-Shortbread-Riegel zubereitet und welche Techniken beim Backen von Fruchtschnitten entscheidend sind
Welche groß angelegten Lösungen können den Klimawandel wirksam bekämpfen?
Wie die amerikanische Außenpolitik unter Trump den Iran und China betrachtet: Eine Analyse der wichtigsten Säulen
Wie erkennt man seine Herkunft?

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский