Einführung
Ansible Molecule ist ein leistungsstarkes Test-Framework, das den Prozess des Testens von Ansible-Rollen in verschiedenen Szenarien vereinfacht. Dieses Tutorial führt durch den Prozess der Einrichtung und Verwendung von Ansible Molecule, um Ansible-Rollen effektiv zu testen.
Warum Molecule zum Testen von Ansible verwenden?
Gründe für Molecule:
- Automatisiertes Testen: Molecule automatisiert den Testprozess für Ansible-Rollen und ermöglicht die einfache Definition und Ausführung von Testszenarien. Diese Automatisierung hilft, Probleme frühzeitig im Entwicklungszyklus zu erkennen und stellt sicher, dass sich die Rollen wie erwartet verhalten.
- Isolierung von Umgebungen: Molecule verwendet verschiedene Treiber (z. B. Docker, Vagrant), um isolierte Umgebungen für Tests zu schaffen. Dadurch wird sichergestellt, dass die Tests über verschiedene Systeme hinweg konsistent und reproduzierbar sind, was die Wahrscheinlichkeit von umgebungsbezogenen Problemen verringert.
- Mehrere Test-Szenarien: Molecule unterstützt die Definition mehrerer Szenarien, welche es ermöglichen, Rollen unter verschiedenen Bedingungen zu testen. So kannst du beispielsweise verschiedene Betriebssysteme, Ansible-Versionen oder Konfigurationen testen, um die Kompatibilität der Rollen sicherzustellen.
- Continuous Integration (CI): Molecule ist so konzipiert, dass es nahtlos mit CI-Systemen wie Travis CI, Jenkins oder GitLab CI zusammenarbeitet. Dadurch kannst du den Testprozess jedes Mal automatisieren, wenn Änderungen in dein Versionskontrollsystem übertragen werden, und so eine kontinuierliche Qualitätssicherung gewährleisten.
- Unterstützung der Rollenentwicklung: Molecule enthält Tools für die Rollenentwicklung, wie z. B. Rolleninitialisierung, Linting und Abhängigkeitsmanagement. Dies rationalisiert den Entwicklungsworkflow und trägt zur Erhaltung einer konsistenten Codebasis bei.
- Parallele Ausführung: Molecule unterstützt die parallele Ausführung von Tests, was beim Testen mehrerer Szenarien gleichzeitig Zeit sparen kann. Dies ist entscheidend für die Beschleunigung der Feedbackschleife während der Entwicklung.
- Dokumentation und Best Practices: Molecule fördert bewährte Praktiken bei der Rollenentwicklung und beim Testen. Die Dokumentation des Tools bietet klare Anleitungen zur Strukturierung von Rollen, zum Schreiben effektiver Testfälle und zur Einhaltung empfohlener Konventionen.
- Gemeinschaftliche Akzeptanz: Molecule ist in der Ansible-Community weit verbreitet. Viele Ansible-Rollen und -Projekte verwenden Molecule zum Testen, was es zu einer gut unterstützten und zuverlässigen Wahl für Rollenentwickler macht.
Voraussetzungen
Bevor wir uns in die Demonstration stürzen, stelle sicher, dass die folgenden Voraussetzungen erfüllt sind. Für CI-Workloads wird docker
ohne die Notwendigkeit von virtualenv
dringend empfohlen.
Beispiel-Installation unter Ubuntu 20.04 / 22.04
sudo apt update && sudo apt install -y python3 python3-pip libssl-dev python3 -m pip install molecule ansible-core export PATH="$PATH:$HOME/.local/bin" pip3 install python-dateutil ansible-galaxy collection install hetzner.hcloud
- python: Ansible basiert auf Python. Daher ist es die erste Voraussetzung. Python kann entweder mit dem Paketmanager des Betriebssystems oder durch Kompilieren aus den Quellen installiert werden. Python 3 wird dringend empfohlen.
- pip: Pip ist der Paketmanager von Python. Wir installieren Molecule mit pip, da es noch nicht als OS-RPM verfügbar ist.
- ansible: Ansible muss installiert sein. Wie Python kann auch dies entweder mit dem Paketmanager des Betriebssystems oder mit pip installiert werden.
pip3 install ansible
- molecule: Auch Molecule kann mit pip installiert werden.
pip3 install --no-cache-dir molecule[ansible]
- hetzner.hcloud collections (Optional): Dies hängt vom Anwendungsfall ab. Für diese Demo testen wir die Ansible-Rolle auf der
hetzner
-Infrastruktur, indem wir eine VM bereitstellen, uns über SSH verbinden und die Rolle auf der Ziel-VM ausführen. Die Sammlungen installieren wir mit dem Befehlansible-galaxy collection install hetzner.hcloud
.
Schritt 1 – Beispiel-Ansible-Rolle hinzufügen
Eine übliche Ansible-Rollenverzeichnisstruktur würde in etwa wie folgt aussehen:
holu@<your_host>:~/ansible_example_role$ ls -l
total 56
drwxr-xr-x 3 holu staff 96 21 Nov 12:24 defaults
drwxr-xr-x 3 holu staff 96 21 Nov 12:24 files
drwxr-xr-x 3 holu staff 96 21 Nov 12:24 meta
drwxr-xr-x 3 holu staff 96 21 Nov 12:24 tasks
drwxr-xr-x 3 holu staff 96 21 Nov 12:24 vars
In dieser Demo werden wir unsere OS-Hardening-Rolle auf unserer VM-Infrastruktur anwenden. Angenommen die VM-Infrastruktur umfasst eine Mischung verschiedener Betriebssystemversionen, Haupt- und Nebenversionen. Eine kleine Änderung an der Hardening Rolle muss als Teil der Continuous Integration (CI) gründlich auf jeder OS-Variante getestet werden.
In diesem Tutorial wird ein sehr einfaches Beispiel verwendet, das so aussieht:
holu@<your_host>:~/os_hardening_role$ ls -l
drwxr-xr-x 3 holu staff 96 21 Nov 12:24 tasks
holu@<your_host>:~/os_hardening_role/tasks$ ls -l
-rw-rw-r-- 1 holu staff 208 21 Nov 12:30 main.yml
Inhalt von os_hardening_role/tasks/main.yml
:
Dies ist ein sehr einfaches Beispiel, das du verwenden kannst, um dem Tutorial zu folgen.
---
- name: OS Hardening
hosts: localhost
tasks:
- name: OS Hardening task
debug:
msg: "Performing OS hardening tasks for {{ ansible_distribution }} {{ ansible_distribution_version }}"
Schritt 2 – Molecule-Tests zu einer vorhandenen Rolle hinzufügen
Führe im Rollenverzeichnis (in diesem Beispiel ~/os_hardening_role
) den Befehl molecule init scenario
aus. Dadurch wird das neue Unterverzeichnis molecule
erstellt. Das Unterverzeichnis molecule
enthält ein Standardverzeichnis mit Beispieldateien in folgender Struktur:
os_hardening_role/
├── tasks/
│ └── main.yml
└── molecule/
└── <scenario_name>/
├── converge.yml
├── create.yml
├── destroy.yml
└── molecule.yml
Szenarien dienen als Grundlage für eine Vielzahl leistungsstarker Funktionen innerhalb von Molecule. Betrachte ein Szenario als eine dedizierte Testsuite für Rollen oder Playbooks innerhalb einer Sammlung. Du kannst mehrere Szenarien erstellen und Molecule führt diese nacheinander aus.
Schritt 3 - Das Scenario-Layout
File | Purpose |
---|---|
molecule.yml | Dies ist der Schlüsselkonfigurationseinstiegspunkt für Molecule pro Szenario. Mit dieser Datei kannst du jedes Tool konfigurieren, das Molecule beim Testen deiner Rolle verwendet. |
create.yml | Diese Playbook-Datei wird zum Erstellen der Testumgebung verwendet, bevor deine Ansible-Rolle ausgeführt wird. Dies kann das Erstellen von Instanzen, Docker-Containern oder anderer Infrastruktur umfassen, die zum Testen der Ansible-Rolle erforderlich ist. |
converge.yml | Diese Playbook-Datei enthält den Aufruf der Rolle. Molecule ruft dieses Playbook mit ansible-playbook <your_playbook_file> in der Testumgebung auf, die mit create.yml eingerichtet wurde. |
verify.yml | Diese Playbook-Datei validiert die Rolle in der Testumgebung. Es ist mehr oder weniger gleichbedeutend mit assert in Unit-Tests. |
destroy.yml | Diese Playbook-Datei wird zum Zerstören und Entfernen der Testumgebung verwendet, nachdem die Rolle getestet wurde, z. B. Lösche eine Instanz, einen Docker-Container oder eine andere Infrastruktur, die während des Testprozesses erstellt wurde. |
Anwendungsfall (Ein Beispiel)
Die folgenden Beispieldateien erstellen einen neuen Hetzner Cloud Server für die Testumgebung, testen eine Ansible-Beispielrolle namens os_hardening_role
und löschen den Hetzner Cloud Server, sobald der Test abgeschlossen ist.
-
molecule.yml
Gib Informationen zu erforderlichen Einstellungen und Konfigurationen für die Testumgebung an.
--- dependency: name: galaxy driver: name: default platforms: - name: molecule-test-vm-ubuntu22 image: "ubuntu-22.04" - name: molecule-test-vm-ubuntu24 image: "ubuntu-24.04" provisioner: name: ansible connection_options: ansible_ssh_common_args: " -o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey,password -F /tmp/ssh_config -o StrictHostKeychecking=no" verifier: name: ansible scenario: name: default ## Die folgende Testsequenz beginnt mit `destroy`, um eine saubere Infrastruktur sicherzustellen. test_sequence: - destroy - create - converge - verify - destroy # Du kannst den Lint bei Bedarf deaktivieren, es wird jedoch dringend empfohlen, ihn zu aktivieren, da YAML-Linting für die Verbesserung der Codequalitätsprüfungen sehr wichtig ist lint: | ansible-lint --exclude molecule/default/
dependency
Standardmäßig verlässt sich Molecule auf den Galaxy-Entwicklungsleitfaden, um Rollenabhängigkeiten zu handhaben. driver
Standardmäßig verwendet Molecule den Delegated-Treiber, um Aufgaben zur Instanzerstellung auszulagern. platforms
Molecule verwendet diese Informationen, um die Erstellung, Benennung und Gruppierung von Instanzen zu bestimmen. Wenn du deine Rolle anhand verschiedener Ubuntu-Varianten testen möchten (z. B. 18.04, 20.04, 22.04, 24.04 oder sogar mit anderen Distributionen wie CentOS usw.), kannst du diese in diesem Abschnitt definieren. provisioner
Molecule bietet ausschließlich einen Ansible-Provisioner an, der den Instanzlebenszyklus gemäß dieser Konfiguration regelt. verifier
Standardmäßig verwendet Molecule Ansible zum Erstellen gezielter Zustandsprüfungstests (z. B. Deployment-Smoke-Tests) auf der Zielinstanz. scenario
Diese Konfiguration bestimmt die Reihenfolge, in welcher die Szenarien von Molecule ausgeführt werden. -
create.yml
Dadurch wird ein neuer Hetzner Cloud Server erstellt.
Außerdem wird
ssh_config
generiert (weitere Informationen folgen in "Schritt 4"). Ansible benötigt diese Informationen, um sich per SSH mit dem neu erstellten Hetzner Cloud Server zu verbinden.Im Code unten:
- Ersetze
<your_ssh_key>
mit dem Namen des SSH-Keys, den du in der Cloud Console hinterlegt hast. - Ersetze
<your_hetzner_api_token>
durch deinen tatsächlichen API-Token.
--- - name: Create the test servers hosts: localhost connection: local tasks: - name: Create Hetzner cloud server with Ubuntu 24.04 und 22.04 hetzner.hcloud.server: name: "{{ item.name }}" server_type: cx11 image: "{{ item.image }}" location: fsn1 ssh_keys: - <your_ssh_key> api_token: <your_api_token> state: present register: vm_output with_items: - { name: molecule-test-vm-ubuntu24, image: ubuntu-24.04 } - { name: molecule-test-vm-ubuntu22, image: ubuntu-22.04 } - name: Generate ssh_config template: src: ssh_config.j2 dest: /tmp/ssh_config vars: hosts: "{{ vm_output.results }}" - name: Pause for 1 minute to wait for the SSH process to come up pause: seconds: 60
- Ersetze
-
converge.yml
Dadurch wird die Ansible-Beispielrolle
os_hardening_role
auf die Testumgebung angewendet. Mit der obigen Beispieldateicreate.yml
besteht die Testumgebung aus einem Hetzner Cloud Server mit Ubuntu 24.04 und einem Hetzner Cloud Server mit Ubuntu 22.04.Wenn du einen anderen Pfad verwendet hast, ersetze
../../../os_hardening_role/tasks
entsprechend.--- - name: Converge hosts: all become: yes gather_facts: true tasks: - name: "Include os_hardening_role" include_role: name: "../../../os_hardening_role/tasks"
-
verify.yml
Hier kannst du weitere Checks hinzufügen. Für diese Demo stellen wir sicher, dass die
root
-Anmeldung im Rahmen der Absicherung deaktiviert ist.--- - name: Verify OS Hardening Control hosts: all become: true tasks: - name: Ensure root login is disabled command: grep '^\s*#*PermitRootLogin' /etc/ssh/sshd_config register: root_login_config failed_when: "'yes' in root_login_config.stdout" - name: Print root login status debug: msg: "{{ root_login_config.stdout_lines[0] }}"
-
destroy.yml
Dies entfernt den Server, der zuvor erstellt wurde. Der Dateiinhalt ist mehr oder weniger derselbe wie in
create.yml
, außer dass der "state" als "absent" markiert werden muss.Ersetze im unten stehenden Code
<your_api_token>
durch deinen eigenen API-Token.--- - name: Destroy the test servers hosts: all connection: local tasks: - name: Delete Hetzner cloud server with Ubuntu {{ item.image }} hetzner.hcloud.server: name: "{{ item.name }}" api_token: <your_api_token> state: absent with_items: - { name: molecule-test-vm-ubuntu24, image: ubuntu-24.04 } - { name: molecule-test-vm-ubuntu22, image: ubuntu-22.04 }
Schritt 4 - SSH-Konfiguration erstellen
Ansible verlässt sich in erster Linie auf SSH, um eine Verbindung zu einem Zielgerät herzustellen und Aufgaben auszuführen. Da wir für unsere Tests "Wegwerf"-VMs bereitstellen, erstellen wir für jede VM eine SSH-Konfiguration, um das Inventar aufzubauen.
-
Mit create.yml werden die Variablen in
ssh_config.j2
ersetzt und unter/tmp/ssh_config
als neue Datei gespeichert. -
Mit molecule.yml nutzt Ansible die Informationen aus
/tmp/ssh_config
, um eine Verbindung zum neuen Server herzustellen.
Ein einfaches Jinja2-Template würde so aussehen:
Pfad:
<role_name>/molecule/<your-scenario>/ssh_config.j2
Ersetze
~/.ssh/id_ed25519
durch den Pfad zu deinem eigenen privaten SSH-Schlüssel.
holu@<your_host>:~/os_hardening_role$ cat molecule/default/ssh_config.j2
{% for host in hosts -%}
Host {{ host.hcloud_server.name }}
HostName {{ host.hcloud_server.ipv4_address }}
User root
IdentityFile ~/.ssh/id_ed25519
{% endfor %}
Weitere Informationen zur Variable hcloud_server
(z. B. name
und ipv4_address
) findest du in der Ansible-Dokumentation.
Schritt 5 - Molecule ausführen
Molecule bietet Befehle zum manuellen Verwalten des Lebenszyklus der Instanz, des Szenarios, der Entwicklungs- und Testwerkzeuge. Wir können Molecule jedoch auch mitteilen, dies automatisch innerhalb einer Szenariosequenz zu verwalten.
Vollständiger Lebenszyklusablauf von Molecule
└── default
├── dependency
├── cleanup
├── destroy
├── syntax
├── create
├── prepare
├── converge
├── idempotence
├── side_effect
├── verify
├── cleanup
└── destroy
Für das Standardszenario kannst du die vollständige Lebenszyklussequenz im Rollenverzeichnis (in diesem Beispiel ~/os_hardening_role
) mit dem Befehl molecule test
aufrufen.
Wenn du den Namen des Szenarios angeben möchtest, kannst du das mit molecule test --scenario-name <your_scenario>
.
Zusätzliche Lebenszyklus-Szenarien
Das oberenstehende Beispiel beinhaltet idempotence
, was in einigen Fällen wichtig sein kann. Du kannst solche Szenarien in der Datei molecule.yml
einfügen. Ansible wird damit erneut ausgeführt, um sicherzustellen, dass die Rolle die Kriterien für idempotence
erfüllt. Weitere Informationen zu Szenarien findest du unter molecule-scenarios.
Ergebnis
Herzlichen Glückwunsch! Du hast erfolgreich eine Ansible-Rolle mit Molecule eingerichtet und getestet. Wir haben die Grundlagen und Test-Szenarien auf verschiedenen Ubuntu-Versionen behandelt. Erkunde weiter und wende Molecule auf deine Ansible-Projekte an, um robuste und zuverlässige Rollen zu erstellen.
Zusätzliche Ressourcen: