An dieser Stelle möchte ich ein Konzept erarbeiten, um meinen Blog mit Hilfe von Ansible[1. Ansible – IT-Automation für Jedermann – My-IT-Brain] [2. Ansible – Wikipedia] auf einem Ubuntu-Server ausbringen zu können.
Dabei hoffe ich auch ein wenig auf eure Unterstützung. Habt ihr Anregungen, konkrete Verbesserungsvorschläge oder auch Fragen, freue ich mich über eure Kommentare. Denn ich selbst bin kein Ansible-Experte und führe dieses Projekt zum Selbststudium und zu Übungszwecken durch.
Die Testumgebung
Die Testumgebung besteht aus der Ansible Control Machine, basierend auf RHEL 7[3. Red Hat Enterprise Linux – Wikipedia] und dem Zielsystem, basierend auf Ubuntu Bionic Beaver[4. Bionic Beaver – wiki.ubuntuusers.de]. Zum Zeitpunkt der Erstellung dieses Artikels nutze ich Ansible in Version 2.4.2.
Zwar wurde bereits die Ansible-Version 2.5 veröffentlicht, in den RHEL-7-Paketquellen ist jedoch noch die Version 2.4.2 enthalten. Ich verwende diese Version auch auf der Arbeit und erhoffe mir so, Erkenntnisse aus diesem Projekt in meine dienstliche Tätigkeit einfließen lassen zu können.
Auf dem Zielsystem existiert ein Benutzer, welcher über volle sudo
-Berechtigung verfügt. Dieser Benutzer muss sich mit seinem Passwort authentisieren, wenn er sudo
verwendet.
Auf der Ansible Control Machine wird ein SSH-Schlüsselpaar[5. Authentifizierung über Public-Keys – wiki.ubuntuusers.de] generiert, dessen privater Schlüssel nicht mit einer Passphrase geschützt ist. Der öffentliche Schlüssel wird auf dem Zielsystem abgelegt. Damit wird sichergestellt, dass die Ansible Control Machine SSH-Zugriff auf das Zielsystem hat.
Die Konfiguration von Ansible (/etc/ansible/ansible.cfg) wird so angepasst, dass standardmäßig das oben erzeugte SSH-Private-Key-File beim Verbindungsaufbau genutzt wird.
Die Installation der benötigten Betriebssysteme und Ansible sind nicht Gegenstand dieses Artikels.
Geplante Vorgehensweise
Um eine Vorgehensweise zu erarbeiten, orientiere ich mich an dem Artikel Testinstanz für einen WordPress-Blog erstellen. In diesem habe ich bereits beschrieben, wie ein Blog auf einem weiteren System als Testsystem aufgesetzt werden kann. Die Vorgehensweise ist ähnlich, mit dem Unterschied, dass sämtliche Schritte nun durch Ansible orchestriert werden sollen.
Danach ergibt sich folgende (vorläufige) Reihenfolge:
- Vom Produktivsystem benötigte Dateien holen
- Sicherstellen, das alle benötigten Pakete auf dem Zielsystem installiert sind
- VirtualHost erstellen
- DocumentRoot aus Backup-Datei erstellen
- Datei-Attribute und Zugriffsrechte korrekt setzen
- Eine
.httpasswd
-Datei erzeugen/ausbringen - Datenbank aus Backup wiederherstellen
- Datenbankbenutzer erstellen
- Troubleshooting
Mit hoher Wahrscheinlichkeit ist die obige Liste noch nicht vollständig. Daher werde ich diese im Laufe des Projekts anpassen, sobald weitere Erkenntnisse vorliegen.
Als Quelldaten für den Blog liegen das DocumentRoot meines Blogs als Tarball[6. tar – Wikipedia] vor. Von der Datenbank wurde ein logisches Backup[7. Logisches Backup – wiki.ubuntuusers.de] erstellt. Auf diese Datensicherung wird zurückgegriffen, um den Blog auf einem neuen Ubuntu-Server auszubringen bzw. wiederherzustellen.
Der erste Versuch
Im ersten Anlauf habe ich eine Ansible-Rolle[8. Directory Layout — Ansible Best Practices] mit folgendem Aufbau erstellt:
/etc/ansible/roles/ └── deploy-my-blog ├── files │ ├── backup-documentroot.tar.bz2 │ ├── dh_params.pem │ ├── db_dump.sql.bz2 │ ├── my-it-brain.vhost │ └── php-fpm-pool.conf ├── handlers │ └── main.yml ├── tasks │ └── main.yml └── vars └── main.yml 5 directories, 8 files
Unterhalb von files wurden Dateien abgelegt, welche vom aktuellen Produktivsystem stammen und für das Deployment auf einem neuen Server benötigt werden.
Im folgenden werde ich zuerst auf die eingesetzten Module eingehen und anschließend das Playbook zum Deployment des Blogs vorstellen.
Verwendete Module
Modul | Status | Verwendung |
---|---|---|
apt | stableinterface | Verwaltet APT-Pakete |
unarchive | preview | Entpackt Archiv-Dateien und kopiert sie ggf. vorher auf das Zielsystem |
copy | stableinterface | Kopiert Dateien auf entfernte Rechner |
file | stableinterface | Erstellt Dateien, Verzeichnisse, symbolische Links und setzt deren Attribute |
mysql_db | preview | Hinzufügen von MySQL-Datenbanken (aus Backup) |
mysql_user | preview | Hinzufügen (und Entfernen) von Benutzern in MySQL-Datenbanken |
Die in der Spalte Status angegebenen Werte stableinterface und preview lassen Rückschlüsse auf die Stabilität der Schnittstellen eines Moduls zu.
So garantieren die Entwickler bei einem stableinterface, dass es in Zukunft keine Änderungen geben wird, die nicht abwärtskompatibel sind. Auch wenn sich keine explizite Angabe findet, wie lange diese Garantie gilt, kann man davon ausgehen, dass man seine Playbooks bei Verwendung dieser Module nicht so schnell aufgrund von Updates anpassen muss. Für Module mit dem Status preview wird genau dies hingegen nicht garantiert. Hier kann es von Version zu Version Änderungen geben, welche Anpassungen an Playbooks erforderlich machen, welche diese Module verwenden. Dadurch entsteht ggf. ein erhöhter Testaufwand, bevor man seine Ansible-Installation aktualisieren kann.
Das Playbook
Den Inhalt der Datei /etc/ansible/roles/deploy-my-blog/tasks/main.yml habe ich unter dem Namen deploy-blog-playbook.yml als Gist veröffentlicht. Um es in diesem Artikel anzeigen zu können, müsst ihr JavaScript in eurem Webbrowser aktiveren.
Die Zeilen 2-11 sorgen dafür, dass die benötigten Pakete auf dem Zielsystem installiert werden. Da es sich dabei um einen Ubuntu-Server handelt, verwende ich das Modul apt.
Die Zeilen 13-16 stellen das DocumentRoot und die SSL-Zertifikate aus dem Dateibackup auf dem Zielsystem wieder her.
In meiner aktuellen Konfiguration verwende ich PHP-FPM mit einem eigenen Pool, welcher in meinem VirtualHost referenziert wird. Um diese Konstellation auch auf dem neuen System nutzen zu können, stelle ich entsprechende Konfiguration mit den Zeilen 18-47 her. Vermutlich können die Zeilen 39-47 entfallen, da PHP-FPM das Logfile automatisch erstellt. Weitere Tests müssen dies noch zeigen. Ich habe diese Zeilen während des Troubleshootings eingefügt. Ursache für den Fehler wird vermutlich das fehlende Log-Verzeichnis gewesen sein, welches ich in den Zeilen 29-37 erzeuge.
Der NGINX auf meinem Produktivsystem verwendet die Datei dh_params.pem, welche ich in den Zeilen 49-57 auch auf den neuen Host kopiere. Anschließend wird in den Zeilen 59-66 die vHost-Datei auf das Zielsystem kopiert und durch die Zeilen 68-77 verlinkt und damit aktiviert.
Die letzten Zeilen kümmern sich um die Einrichtung der Datenbank. Zuerst wird die Dump-Datei auf das Zielsystem kopiert und dort anschließend in die neue Datenbank db_my_it_brain eingespielt. Zum Schluss wird noch der benötigte Datenbank-Benutzer erstellt.
In Zeile 94 und 95 habe ich Variablen eingesetzt, welche in vars/main.yml definiert wurden. Dort habe ich auch eine Variable für den Namen der Datenbank definiert, welche ich gern in Zeile 96 genutzt hätte. Leider ist es mir nicht gelungen, da sowohl priv: '"{{ DBNAME }}".*:ALL'
als auch priv: "{{ DBNAME }}".*:ALL
zu Fehlern führten. Falls hier jemand eine Idee hat, freue ich mich, wenn ihr mir die korrekte Syntax mitteilt.
Erstes Fazit
Das ging leichter als gedacht. Die benötigten Module waren schnell gefunden und ihre Anwendung aufgrund der hinreichend guten Dokumentation nicht schwierig.
Da die aktuell genutzten Variablen sensible Informationen beinhalten, möchte ich diese zukünftig mit Ansible Vault schützen.
Stand heute bin ich jedoch erstmal in der Lage meinen Blog aus der Datensicherung heraus erneut deployen zu können.
Pingback: Erfahrungsbericht zum Deployment meines Blogs mit Ansible | My-IT-Brain
Pingback: Ansible: Wiederherstellung meines Blogs auf Buster und Bullseye in 2021 | My-IT-Brain