Wolkenarchitektur
Cloudserver automatisiert bestellen und einrichten
Wer heute eine gute Idee für ein Online-Angebot hat, braucht keine eigenen Server und kein Rechenzentrum, wohl aber einen Schlachtplan für den Weg in die Cloud. Viele kleine und größere Probleme müssen Start-ups und große Unternehmen gleichermaßen lösen, bevor der eigene Code in gemieteter Umgebung läuft.
Am Anfang steht die Idee: Eine App und eine Website sollen entstehen, über die man Fotos hochladen und mit Freunden teilen kann. Das Entwicklungsteam ist klein: Einer kümmert sich um die mobilen Apps, einer um das Web-Frontend und ein Dritter baut das Backend, das Bilder und Benutzerinformationen speichert und wieder anzeigt. So oder so ähnlich sind viele IT-Start-ups personell aufgestellt, für eine ganze Abteilung, die sich um den Betrieb eigener Server kümmert, ist weder Geld noch Platz im Co-Working-Bürogebäude da. Außerdem soll sich die App bestenfalls gegen Instagram, Twitter und Facebook durchsetzen und zum weltweiten Erfolg werden – dann wäre ein einziges Rechenzentrum in Deutschland zu wenig und zu unflexibel.
Also entscheiden sich die Start-up-Gründer dafür, die Anwendung von Anfang an auf gemieteter Infrastruktur zu betreiben. Das Start-up, das sich diese Anwendung ausgedacht hat, heißt Piqup Ventures und ist rein fiktiv. Dieser Artikel vermittelt einen Eindruck, welche Probleme die Entwickler auf dem Weg zu einer skalierbaren Cloud-Anwendung lösen müssen: Von DNS über Containerisierung, automatische Updates, skalierbaren Speicherplatz bis hin zu Monitoring gibt es viel einzurichten. Auf den nächsten Seiten geht es zunächst um ein Rezept für einen einzelnen Server – wie man es schafft, dass beliebig viele gemietete Server im Verbund arbeiten, erfahren Sie in einer der nächsten Ausgaben.
Dieser Überblick sollte nicht als Schritt-für-Schritt-Anleitung zum Nachbauen verstanden werden – einige der vorgestellten Werkzeuge erfordern durchaus eine längere Einarbeitungszeit. Wie immer in der IT führen bei jedem Teilproblem zahlreiche Wege zum Ziel und es gibt immer gute Gründe, andere als die hier beschrittenen Pfade zu wählen. Wenn Sie Ideen aus diesem Artikel für die eigene Cloud-Strategie übernehmen wollen, finden Sie das beschriebene Rezept über ct.de/yyc4.
Reproduzierbar und flexibel
Wichtig ist den fiktiven Unternehmern von Piqup, dass die gesamte Einrichtung ihrer Infrastruktur ohne Handarbeit funktioniert. Die Entwickler träumen davon, mit nur einem Befehl neben der produktiven Umgebung app.piqup.de schnell eine baugleiche Testumgebung unter der Adresse testing.piqup.de hochzufahren und der Geschäftsführer würde gern auf Knopfdruck eine Demo-Umgebung für Produktpräsentationen starten können. Damit das klappt, sollen alle Schritte reproduzierbar sein und in einem Rezepte-Ordner liegen. Im einfachsten Fall könnte das eine Sammlung von Bash-Skripten sein.
Bequemer wird die Arbeit mit dem populären Werkzeug Ansible. Eine ausführliche Einführung in das Open-Source-Programm haben wir bereits veröffentlicht [1]. Die Grundidee: In sogenannten Playbooks im YAML-Format definiert man, welche Konfigurationsschritte Ansible erledigen soll. Über Plug-ins kann Ansible zum Beispiel mit den APIs von Cloudanbietern sprechen und Ressourcen einkaufen, es kann sich aber auch per SSH mit Servern verbinden und dort Einrichtungsschritte vornehmen und so auch komplexeste Anwendungen einrichten. Der große Vorteil: Die Einrichtungsschritte sind idempotent – das bedeutet, dass man das Rezept ohne Schaden immer wieder ausführen kann. Ansible achtet darauf, dass nur Änderungen umgesetzt werden und die mehrfache Ausführung eines Rezepts keine negativen Folgen hat. Vereinfacht gesagt: Wenn man schon drei Server bestellt hat und gerne noch einen vierten hätte, muss man nur im Rezept eine 3 in eine 4 ändern und das Rezept erneut ausführen.
DNS-Automation
Der erste Kontakt des Nutzers mit der vom Beispiel-Start-up entwickelten Anwendung führt immer über das DNS (Domain Name System). Ein Hostname wie app.piqup.de muss zu einer IP-Adresse aufgelöst werden, unter der einer der Webserver zu erreichen ist. Dafür braucht das Unternehmen Piqup einen sogenannten Provider, der die Domain piqup.de bei der deutschen Registrierungsstelle Denic registriert und dort die Adresse zu einem Nameserver hinterlegt. Viele Hoster bieten ihren Kunden diese Dienste im Paket mit anderen Dienstleistungen an. Gerade in klassischen Webhoster-Paketen oder bei virtuellen Servern im langfristigen Tarif ist eine Domain oft im Preis enthalten und der Hoster stellt auch den DNS-Server bereit.
Es gibt aber gute Gründe, die Aufgaben von Provider und DNS-Anbieter von Anfang an zu trennen und die eigene Domain nicht an ein vermeintlich günstiges Paket vom Hoster zu binden. Solche in Webhosting integrierten DNS-Verwaltungen kann man meist nur über eine Weboberfläche steuern – in der schnelllebigen Cloud-Welt möchte man aber nicht jede IP-Adresse jedes Mietservers per Hand dort eintippen. Wenn man sich für einen unabhängigen Dritten als reinen Domainverwalter entscheidet, erspart man sich außerdem Probleme, die entstehen können, wenn man sich irgendwann einem anderen Anbieter für die Server zuwendet.
Die Start-up-Gründer sind daher gut beraten, sich einen Provider zu suchen, der Domains als lose Ware zum Stückpreis anbietet. Der Betreiber des DNS-Servers kann davon völlig unabhängig sein. Viele setzen für die DNS-Verwaltung ihrer Domains mittlerweile auf das US-Schwergewicht Cloudflare: Dessen Schwerpunkt ist die Abwehr von DDoS-Attacken, ganz nebenbei betreiben sie aber auch DNS-Server – wenn man keine Extras braucht, ist das Angebot kostenlos.
Bei einem deutschen Domainhändler bestellen die Piqup-Admins daher nur die Domain und hinterlegen dort die Adressen zu zwei Nameservern von Cloudflare. Der große Vorteil: Alle Funktionen der Weboberfläche von Cloudflare kann man auch per API fernsteuern und damit gut skripten. Bestenfalls nutzt man die Weboberfläche nur einmalig, um das API-Token zu generieren, und arbeitet dann mit reproduzierbaren Rezepten per API. Besonders komfortabel wird das mit Ansible – weil Cloudflare weit verbreitet ist, gibt es ein Plug-in für Ansible, das die API-Kommunikation abstrahiert. Mit wenigen Zeilen entsteht ein Rezept für den A-Record (app.piqup.de) der Piqup-App:
- name: Create A record community.general.cloudflare_dns: zone: piqup.de record: app type: A value: "<IP-Adresse>" account_email: john.doe@piqup.de account_api_key: "<API-Token>" register: record
Fertige Server, bitte
Für einen DNS-Eintrag fehlt bisher noch ein entscheidendes Detail: die IP-Adresse. Die bekommt man vom Cloud-Hoster erst, wenn man einen Server bestellt, und beim Umgang mit Netzwerkkonfiguration und Firewall unterscheiden sich die Hoster stark. Teilweise muss man eine externe IP zusätzlich konfigurieren. Der Einfachheit halber hat sich Piqup für einen Anbieter entschieden, der jedem gemieteten Server für den Mietzeitraum eine öffentliche IPv4-Adresse zuteilt.
Als Entwickler, der jetzt ein Ansible-Rezept schreiben soll, beginnt man mit einem Blick in die Weboberfläche des Serververmieters und verschafft sich einen Überblick, welche Produkte und Optionen es überhaupt gibt. In der Oberfläche hinterlegt man dann seine Zahlungsdaten und erzeugt ein API-Token, das Ansible für die Kommunikation erwartet. Anschließend muss man sich mit der Syntax des Ansible-Moduls vertraut machen, über das man mit seinem Hoster kommuniziert. In der Tabelle auf Seite 66 erfahren Sie, wie Sie die vorgestellten Anbieter per Ansible fernsteuern.
Als Beispiel hält ein Server vom Typ CX11 des deutschen Anbieters Hetzner her, für den es ein Ansible-Plug-in gibt:
- name: create a server hetzner.hcloud.hcloud_server: name: "server1" server_type: cx11 location: fsn1 image: ubuntu-20.04 ssh_keys: - piqup-ansible state: present api_token: "<API-Token>" register: server
Passende Werte (etwa für den Standort des Rechenzentrums oder die installierbaren Betriebssysteme) muss man sich aus Dokumentation und schlimmstenfalls aus Forenbeiträgen zusammensuchen. Beim Zusammenbau der Ansible-Rezepte sollte man nicht geizig sein, sie durchaus mal mutig ausführen, die Server wieder löschen und solange neu bauen, bis alles rund läuft. Bei Stundenpreisen im Centbereich kann man problemlos mal ein paar Testmaschinen starten und kurz darauf vernichten. Wichtig ist nur, am Ende des Arbeitstages mit einem Blick in die Weboberfläche sicherzustellen, dass man keine Kostenverursacher vergessen hat.
Im obigen Beispiel wird direkt ein SSH-Schlüssel hinterlegt, mit dem sich Ansible in weiteren Schritten am neuen Server anmelden kann. Den Public Key muss man vorher beim Anbieter hinterlegen, das private Gegenstück muss auf der Entwicklermaschine liegen, auf der Ansible ausgeführt wird. Abgerundet wird der obige Ansible-Schnipsel mit dem Befehl register: server. Ansible speichert damit die Rückgabewerte des APIs in der Variable server, die man zum Beispiel hervorragend nutzen kann, um im zweiten Schritt einen DNS-Eintrag bei Cloudflare mit der gerade vergebenen IP-Adresse anzulegen:
value: "{{ server.hcloud_server.ipv4_address }}"
Bei aller Flexibilität und Abstraktion muss man sich bewusst sein, dass ein Umzug zu einem anderen Hoster mit etwas Arbeit verbunden ist: Die Zeilen im Ansible-Rezept, die in diesem Beispiel für Hetzner ausgelegt sind, müsste man ersetzen, wenn man zum Beispiel zu OVH wechseln will. Vergleichsweise einfach ist ein Umzug unter allen Anbietern, die im Hintergrund OpenStack einsetzen und das OpenStack-API zur Steuerung öffentlich zugänglich machen.
Tücken lauern auch bei der eingangs gelobten Idempotenz: Nicht jeden Wert kann man nach dem Erstellen einer Ressource noch ändern. Wenn Sie gehofft hatten, nur den Namen des Rechenzentrums in der Ansible-Datei austauschen zu müssen, um einen Server umziehen zu lassen, werden Sie meist enttäuscht. In diesem Fall muss man den Server löschen und einen neuen anlegen – sofern er automatisch eingerichtet wird, ist das aber kein Problem.
Containerisierung
Server und DNS-Einträge sind jetzt fertig und ein Rezept kann die Linux-Maschinen mit Software ausstatten. Mit nur drei Zeilen in einem Playbook kümmert sich Ansible zum Beispiel darum, dass der Webserver Nginx per Apt aus den Paketquellen installiert wird:
- name: Install nginx apt: name: nginx
Grundsätzlich spricht nichts dagegen, Cloudserver auf diese Weise einzurichten. Es gibt jedoch überzeugende Argumente dafür, einem der größten IT-Trends der letzten Jahre zu folgen und die Anwendungen in Container zu stecken. Im einfachsten Fall startet man solche mit Docker; wenn man größere Umgebungen plant, setzt man auf Kubernetes.
Vorteile von Containerisierung gibt es viele: Weil ein Container alle Abhängigkeiten in der genau passenden Version mitbringt, kann man auch mehrere Versionen derselben Software auf einem Server betreiben. Außerdem verschwinden Container nach dem Löschen spurlos. Der größte Vorteil: Eine Zusammenstellung aus denselben Container-Abbildern verhält sich immer gleich (Ausnahmen bestätigen auch hier die Regel). Die Entwickler können ganz ohne Aufwand mit virtuellen Maschinen eine exakt identische Testumgebung auf ihren Laptops starten.
Die Piqup-Gründer entscheiden sich, zunächst einen Prototyp mit Docker auf einem einzigen Mietserver zu starten und heben sich den Umzug auf eine redundante und skalierbare Umgebung für später auf. Das ist eine empfehlenswerte Herangehensweise: Versuchen Sie nicht, alles auf einen Schlag zu erzwingen und das perfekte System zu entwerfen. Sammeln Sie zunächst Erfahrungen mit einem einzelnen Docker-Host. Beim redundanten Betrieb im Cluster wird alles schlagartig komplexer. Docker für Linux bekommt man mit Ansible zügig auf die Maschine, das komplette Ansible-Rezept zur Docker-Installation (etwa 40 Zeilen YAML) finden Sie über ct.de/yyc4.
Container-Zusammenstellungen für Docker beschreibt man ebenfalls im YAML-Format für das Kommandozeilenprogramm Docker-Compose. Darin definieren die Piqup-Entwickler die Container, die für ihre Anwendung zusammenarbeiten müssen: eine Datenbank, ein Container mit dem Backend und einen mit der Weboberfläche. Außerdem einen HTTP-Router, der den eingehenden Verkehr abwickelt und sich um ein TLS-Zertifikat von Let’s Encrypt kümmert. Eine Einführung in den Open-Source-Router Traefik finden Sie in [2].
Damit die von den Piqup-Entwicklern hergestellten Container-Abbilder installiert werden können, müssen sie irgendwie in eine Registry gelangen. Lange Zeit war die Docker Registry die erste Wahl, um eigene Abbilder abzulegen. Weil die PiqupEntwickler ihren Code ohnehin bei GitHub verwalten, entscheiden sie sich, die GitHub-Registry zu nutzen und die Container automatisch von GitHub Actions bauen lassen [3]. Ein Umzug in eine eigene Registry (zum Beispiel ein selbst gehostetes GitLab) ist später kein großer Aufriss.
Die Docker-Compose-Datei legen die Entwickler zusammen mit ihren Ansible-Dateien in einem Rezepteordner ab. Um die Zusammenstellung zu starten, muss niemand per Hand auf der Kommandozeile docker-compose up eintippen. Zum Starten von Compose-Zusammenstellungen gibt es ein Ansible-Modul:
community.docker.docker_compose: project_src: /srv/piqup remove_orphans: true
Seinem Ziel, reproduzierbare Umgebungen bei Cloud-Providern zu erzeugen, ist das Start-up bereits sehr nahe gekommen. Kombiniert man all diese Bausteine zu einem Playbook, reicht am Ende ein Befehl wie
ansible-playbook -i inventory site.yml
Danach kann man etwa fünf Minuten lang Ansible bei der Arbeit zusehen. Am Ende läuft, ganz ohne Benutzerinteraktion, ein Cloudserver mit installiertem Docker, es gibt einen DNS-Eintrag, auf dem Server läuft die Anwendung, veröffentlicht per HTTPS.
Datenhalde
In schicken Whitepapern und werblichen Konferenzvorträgen endet die Erzählung hier. In Sekunden, so das Versprechen, das man dort liest und hört, läuft eine „stateless application“. Was dabei unterschlagen wird: Nur die allerwenigsten Anwendungen sind „stateless“, produzieren also keinerlei Nutzdaten, die dauerhaft gespeichert werden müssen. Das trifft eigentlich nur auf statische Websites zu – schon ein einfaches Blog mit einem CMS-Backend ist nicht stateless, sondern braucht zwei Formen von Speicherplatz: ein Dateisystem für hochgeladene Bilder und Dokumente sowie eine (SQL-)Datenbank. Und genau dort wird es kompliziert, wenn die Software auf mehreren Servern redundant laufen soll und die Daten überall aktuell sein müssen. Wie die Piqup-Entwickler an Loadbalancer, skalierbaren Speicherplatz und eine replizierende Datenbank kommen, lesen Sie in einer der nächsten Ausgaben. (jam@ct.de)
Ansible-Beispiel: ct.de/yyc4