ayedo Edge-Cloud: Die unterschätzte Architektur moderner Anwendungen
Katrin Peter 10 Minuten Lesezeit

ayedo Edge-Cloud: Die unterschätzte Architektur moderner Anwendungen

Wenn wir über den Betrieb einer Anwendung sprechen, denken wir fast automatisch an das Rechenzentrum. An virtuelle Maschinen, Kubernetes-Cluster, Datenbanken, Container oder Storage-Systeme. Unsere Architekturdiagramme beginnen häufig genau dort: irgendwo innerhalb einer Cloud-Region, hinter einer Firewall, dort, wo Compute-Ressourcen bereitgestellt und Anwendungen ausgeführt werden.

Moderne Anwendungen beginnen nicht mehr im Rechenzentrum

Es gibt einen Gedanken, der sich hartnäckig hält, obwohl moderne Software ihn längst widerlegt hat.

Wenn wir über den Betrieb einer Anwendung sprechen, denken wir fast automatisch an das Rechenzentrum. An virtuelle Maschinen, Kubernetes-Cluster , Datenbanken, Container oder Storage-Systeme. Unsere Architekturdiagramme beginnen häufig genau dort: irgendwo innerhalb einer Cloud-Region, hinter einer Firewall, dort, wo Compute-Ressourcen bereitgestellt und Anwendungen ausgeführt werden.

Selbst die Sprache, die wir verwenden, verrät dieses Denken. Wir sprechen davon, Anwendungen zu deployen, Cluster zu betreiben oder Plattformen zu skalieren. Die eigentliche Infrastruktur beginnt für uns in dem Moment, in dem der erste Container gestartet wird.

Doch genau dort beginnt sie längst nicht mehr.

Vielleicht hat sie dort nie begonnen.

Die Vorstellung, dass eine Anwendung mit ihrem ersten Prozess oder ihrem ersten Pod beginnt, stammt aus einer Zeit, in der Software und Infrastruktur nahezu deckungsgleich waren. Wer einen Webserver betrieb, stellte einen Server ins Rack, installierte ein Betriebssystem, konfigurierte einen Webserver und verband ihn mit dem Internet. Zwischen dem Browser eines Benutzers und der eigentlichen Anwendung lagen vergleichsweise wenige technische Schichten. Routing, Transport und Anwendung bildeten eine Einheit, die sich noch mit einem einzigen Architekturdiagramm erklären ließ.

Heute wirkt dieses Bild beinahe naiv.

Nicht, weil moderne Anwendungen grundsätzlich komplizierter geworden wären, sondern weil sich ihre eigentliche Komplexität verlagert hat.

In den vergangenen anderthalb Jahrzehnten haben wir enorme Fortschritte dabei gemacht, Anwendungen selbst zu abstrahieren. Virtuelle Maschinen lösten physische Server ab. Container reduzierten die Unterschiede zwischen Entwicklungs- und Produktionsumgebungen. Kubernetes entkoppelte Anwendungen von einzelnen Hosts und machte Infrastruktur zunehmend deklarativ. GitOps, Infrastructure as Code und automatisierte Deployment-Pipelines sorgten schließlich dafür, dass selbst hochkomplexe Plattformen reproduzierbar aufgebaut und betrieben werden können.

Es wäre jedoch ein Irrtum anzunehmen, diese Entwicklung habe Infrastruktur einfacher gemacht.

Sie hat sie lediglich an einen anderen Ort verschoben.

Während die Komplexität innerhalb unserer Plattformen kontinuierlich reduziert wurde, entstand außerhalb dieser Plattformen eine vollkommen neue Architekturebene, die heute einen erheblichen Teil dessen übernimmt, was früher selbstverständlich Bestandteil eines einzelnen Webservers war.

Ein Benutzer, der eine Anwendung aufruft, verbindet sich längst nicht mehr direkt mit einem Server.

Er erreicht zunächst eine Infrastruktur, deren eigentliche Aufgabe nicht darin besteht, Anwendungen auszuführen, sondern darüber zu entscheiden, ob, wo und unter welchen Bedingungen eine Anwendung überhaupt erreicht werden darf.

Diese Unterscheidung erscheint zunächst subtil.

Tatsächlich verändert sie jedoch unseren gesamten Blick auf moderne Systeme.

Denn bevor eine einzige Zeile Anwendungscode ausgeführt wird, bevor Kubernetes den passenden Pod auswählt oder ein Service eine Anfrage an das richtige Backend weiterleitet, hat bereits eine Vielzahl von Systemen Entscheidungen getroffen, die den weiteren Verlauf dieser Anfrage maßgeblich beeinflussen.

Welcher Netzwerkpfad wird verwendet?

An welchem Standort wird die Verbindung entgegengenommen?

Wo endet die TLS-Verbindung?

Ist die Anfrage legitim?

Ist das Zielsystem überhaupt erreichbar?

Soll derselbe Benutzer erneut auf dasselbe Backend geleitet werden?

Oder muss die Anfrage bereits an dieser Stelle verworfen werden?

Bemerkenswert ist dabei nicht, dass diese Entscheidungen existieren.

Bemerkenswert ist, dass sie in den meisten Architekturdiagrammen überhaupt nicht vorkommen.

Wir zeichnen Anwendungen.

Wir zeichnen Datenbanken.

Wir zeichnen Kubernetes-Cluster .

Mit etwas Glück zeichnen wir noch einen Loadbalancer davor.

Der eigentliche Weg, den jede einzelne Anfrage zurücklegt, verschwindet dagegen häufig hinter einer simplen Linie mit der Beschriftung Internet.

Vielleicht liegt genau darin eines der größten Missverständnisse moderner Plattformarchitekturen.

Das Internet ist keine Wolke.

Es ist keine Verbindung zwischen zwei Kästen in einem Diagramm.

Und schon gar kein transparenter Transportkanal, durch den Anfragen einfach hindurchfließen.

Zwischen einem Benutzer und der eigentlichen Anwendung liegt heute eine eigenständige Infrastruktur, die Routingentscheidungen trifft, kryptographische Verbindungen aufbaut, Sicherheitsrichtlinien durchsetzt, Last verteilt, Angriffe erkennt, den Gesundheitszustand von Backends überwacht und kontinuierlich entscheidet, welcher Teil einer Plattform überhaupt sichtbar wird und welcher verborgen bleibt.

Je stärker Anwendungen abstrahiert wurden, desto bedeutender wurde genau diese Schicht.

Paradoxerweise sprechen wir über sie jedoch deutlich seltener als über [Container]-Orchestrierung, Service Meshes oder Observability.

Vielleicht, weil sie ihre Aufgabe besonders gut erfüllt.

Gute Infrastruktur besitzt eine bemerkenswerte Eigenschaft: Sie verschwindet.

Niemand denkt über DNS nach, solange sich eine Domain zuverlässig auflösen lässt.

Niemand beschäftigt sich mit Routingtabellen, solange Webseiten innerhalb weniger Millisekunden laden.

Niemand fragt sich, wie ein TLS-Zertifikat bereitgestellt wurde, solange im Browser das kleine Schlosssymbol erscheint.

Und kaum jemand macht sich Gedanken darüber, welchen Weg eine Anfrage tatsächlich genommen hat, solange die Antwort schnell genug zurückkommt.

Erst wenn eines dieser Systeme ausfällt, erkennen wir, dass sie niemals bloße Nebendarsteller waren.

Sie waren von Anfang an die Bühne, auf der sich jede moderne Anwendung bewegt.

Vielleicht ist es deshalb an der Zeit, unsere Architekturdiagramme an einem anderen Punkt beginnen zu lassen.

Nicht im Rechenzentrum.

Sondern dort, wo jede Anwendung tatsächlich ihren Anfang nimmt.

Am ersten Request aus dem Internet.

Die Reise eines Requests

Jede moderne Anwendung beginnt mit einer erstaunlich unspektakulären Handlung.

Jemand öffnet einen Browser.

Vielleicht sitzt er im Homeoffice in München. Vielleicht arbeitet er in einem Büro in Hamburg oder ruft unterwegs über ein Mobilfunknetz eine API auf. Für ihn spielt das keine Rolle. Er gibt eine URL ein, drückt die Eingabetaste und erwartet, dass innerhalb weniger Augenblicke eine Anwendung erscheint.

Diese Erwartung ist bemerkenswert.

Denn sie setzt voraus, dass eine Vielzahl voneinander unabhängiger Systeme innerhalb kürzester Zeit dieselbe Entscheidung treffen: Dieser Request soll genau diese Anwendung erreichen.

Beginnen wir also dort, wo jede Anfrage tatsächlich beginnt.

Nicht im Rechenzentrum.

Nicht im Kubernetes-Cluster .

Sondern auf einem Laptop irgendwo im Internet.


Der Browser kennt zunächst nur einen Namen.

https://api.example.de

Nicht mehr.

Keine IP-Adresse.

Keinen Server.

Kein Rechenzentrum.

Lediglich einen Namen.

Damit aus diesem Namen überhaupt eine Verbindung entstehen kann, muss der Browser zunächst herausfinden, wohin er sich verbinden soll. Er fragt dazu einen rekursiven DNS-Resolver, der wiederum mehrere Nameserver kontaktiert, bis schließlich eine Antwort gefunden wird.

Aus Sicht des Browsers ist dieser Vorgang denkbar unspektakulär.

Er erhält eine IP-Adresse.

Mehr interessiert ihn nicht.

Was der Browser nicht weiß: Diese IP-Adresse existiert nicht nur an einem einzigen Ort.

Sie wird gleichzeitig an mehreren Standorten veröffentlicht.

Für den Client bleibt sie dennoch eine einzige Adresse.

Immer dieselbe.

Unabhängig davon, ob der Benutzer gerade in Flensburg, Frankfurt oder Freiburg sitzt.

An diesem Punkt beginnt bereits eines der elegantesten Konzepte moderner Netzwerkinfrastruktur.

Denn der Browser verbindet sich nicht mit einem bestimmten Rechenzentrum.

Er verbindet sich lediglich mit einer Adresse.

Das Internet entscheidet anschließend selbst, wo diese Verbindung tatsächlich endet.


Das erste TCP-Paket verlässt nun den Rechner des Benutzers.

Es durchquert den heimischen Router, gelangt zum Internet Service Provider und beginnt eine Reise durch Netze, die verschiedenen Unternehmen gehören und sich dennoch darauf geeinigt haben, Datenpakete gegenseitig weiterzuleiten.

Dabei existiert kein zentraler Verkehrsleiter.

Keine Instanz überwacht den gesamten Datenverkehr.

Keine Datenbank kennt den optimalen Weg.

Stattdessen besitzt jedes Netzwerk nur einen kleinen Ausschnitt des Gesamtbildes und trifft auf dieser Grundlage seine eigenen Entscheidungen.

Genau diese Eigenschaft macht das Internet seit Jahrzehnten erstaunlich robust.

Jeder Netzbetreiber kennt seine direkten Nachbarn.

Jeder entscheidet selbst, welche Wege bevorzugt werden.

Aus unzähligen lokalen Entscheidungen entsteht schließlich ein globales Netzwerk.

Irgendwann erreicht unser Request ein Netzwerk, das dieselbe öffentliche IP-Adresse an mehreren Standorten gleichzeitig kennt.

Jetzt passiert etwas Bemerkenswertes.

Nicht die Anwendung entscheidet, welcher Standort den Benutzer bedient.

Nicht DNS.

Nicht irgendeine Geo-Datenbank.

Sondern das Internet selbst.

Aus Sicht des Routings ist der Point of Presence in Hamburg möglicherweise der kürzeste Weg.

Für einen anderen Benutzer entscheidet sich dieselbe Infrastruktur wenige Millisekunden später für Frankfurt.

Beide Benutzer verwenden dieselbe URL.

Beide erhalten dieselbe IP-Adresse.

Und dennoch landen ihre Verbindungen an unterschiedlichen Orten.

Ohne Redirect.

Ohne neue DNS-Abfrage.

Ohne dass irgendeine Anwendung davon überhaupt Kenntnis besitzt.

Vielleicht ist genau das der eigentliche Zauber von Anycast.

Es ist kein zusätzlicher Dienst.

Es ist eine Eigenschaft des Netzwerks selbst.


Als die Verbindung schließlich einen Point of Presence erreicht, ist von HTTP noch immer keine Rede.

Zunächst muss überhaupt eine TCP-Verbindung entstehen.

Der klassische Three-Way Handshake sorgt dafür, dass sich beide Kommunikationspartner auf eine Verbindung einigen, Sequenznummern austauschen und einen gemeinsamen Übertragungskanal aufbauen.

Erst danach beginnt die nächste Schicht.

Da heute nahezu jede Anwendung verschlüsselt kommuniziert, folgt unmittelbar der TLS-Handschlag.

Zertifikate werden überprüft.

Kryptographische Verfahren ausgehandelt.

Schlüssel erzeugt.

Erst nachdem beide Seiten sicher sind, mit wem sie kommunizieren, beginnt der eigentliche Austausch von Anwendungsdaten.

Interessanterweise endet für viele Menschen genau hier bereits das mentale Modell einer HTTPS-Verbindung.

Der Browser spricht HTTPS.

Der Server antwortet.

Fertig.

Tatsächlich beginnt die eigentliche Arbeit jedoch erst jetzt.

Denn erstmals liegt der Request entschlüsselt vor.

Erstmals kann eine Plattform verstehen, was der Benutzer eigentlich möchte.

Welcher Host wurde aufgerufen?

Welche URL wird angefordert?

Welcher HTTP-Header wurde übertragen?

Welche Cookies enthält die Anfrage?

Welches Backend soll sie bearbeiten?

Vor allem aber:

Soll diese Anfrage überhaupt weitergeleitet werden?

Denn nicht jeder Request stammt von einem Browser.

Nicht jede Anfrage kommt von einem legitimen Benutzer.

Nicht jede Verbindung verfolgt ein legitimes Ziel.

Eine moderne Edge-Plattform betrachtet einen HTTP-Request deshalb nicht lediglich als Datenstrom.

Sie analysiert ihn.

Sie erkennt bekannte Angriffsmuster.

Sie bewertet Header.

Sie prüft Protokollverletzungen.

Sie vergleicht Anfragen mit Regeln der Web Application Firewall und entscheidet innerhalb weniger Millisekunden, ob der Request seine Reise überhaupt fortsetzen darf.

Erst jetzt stellt sich eine Frage, die viele fälschlicherweise für die erste halten.

Welches Backend verarbeitet diese Anfrage?

Diese Entscheidung fällt erstaunlich spät.

Denn bevor überhaupt über Lastverteilung gesprochen werden kann, musste bereits entschieden werden,

ob die Verbindung existieren darf,

an welchem Standort sie endet,

ob sie verschlüsselt wird,

ob sie legitim ist,

und ob das Zielsystem überhaupt erreichbar ist.

Erst danach beginnt das klassische Loadbalancing.

Auf Layer 4 bedeutet dies, eine TCP-Verbindung an ein geeignetes Backend weiterzureichen.

Auf Layer 7 dagegen kennt die Plattform bereits den Inhalt der Anfrage. Sie kann unterschiedliche URLs an verschiedene Anwendungen senden, Sessions zusammenhalten oder Anfragen anhand ihrer Header unterschiedlich behandeln.

Der Unterschied zwischen Layer 4 und Layer 7 besteht deshalb nicht lediglich in einer höheren Zahl.

Er besteht darin, dass die Plattform ab Layer 7 beginnt, das eigentliche Anwendungsprotokoll zu verstehen.

Erst nachdem all diese Entscheidungen getroffen wurden, erreicht unser Request schließlich den Teil der Infrastruktur, den die meisten Architekturdiagramme als ihren Anfang betrachten.

Den Ingress.

Den Kubernetes-Service .

Den ersten Pod.

Oder, einfacher gesagt:

Die eigentliche Anwendung.

Vielleicht erklärt gerade diese Reihenfolge, weshalb moderne Plattformen heute anders gedacht werden müssen als noch vor zehn Jahren.

Die Anwendung ist längst nicht mehr der erste Teil einer Infrastruktur.

Sie ist ihr letztes Glied.

Der öffentliche Eingang einer Anwendung ist heute komplexer als die Anwendung selbst

Betrachten wir für einen Moment zwei Architekturdiagramme.

Das erste könnte aus den frühen 2000er-Jahren stammen.text

Internet │ Firewall │ Webserver │ Datenbank

Das zweite begegnet uns heute nahezu täglich.text

Internet │ DNS │ Anycast │ Edge │ WAF │ Loadbalancer │ Ingress │ Kubernetes │ Service │ Pod │ Datenbank

Beide Diagramme beschreiben im Kern dieselbe Aufgabe.

Ein Benutzer möchte eine Anwendung erreichen.

Und dennoch unterscheiden sie sich grundlegend.

Im ersten Diagramm besteht der eigentliche Aufwand darin, die Anwendung zu entwickeln und zuverlässig auf einem Server auszuführen. Das Netzwerk bildet gewissermaßen den Rahmen, innerhalb dessen diese Anwendung betrieben wird. Es verbindet den Benutzer mit dem Server, übernimmt einige grundlegende Sicherheitsaufgaben und tritt anschließend in den Hintergrund.

Im zweiten Diagramm hat sich diese Gewichtung nahezu umgekehrt.

Natürlich existiert die Anwendung noch immer.

Natürlich müssen Container orchestriert, Datenbanken repliziert und Deployments durchgeführt werden.

Doch betrachtet man den Weg eines einzelnen Requests, fällt auf, dass ein erheblicher Teil seiner Reise stattfindet, bevor überhaupt eine Zeile Anwendungscode ausgeführt wird.

Vielleicht ist genau das eine der größten Veränderungen moderner Plattformarchitekturen.

Die Anwendung selbst ist längst nicht mehr der komplizierteste Teil des Systems.

Sie ist zu einem Baustein innerhalb einer wesentlich größeren Architektur geworden.

Diese Entwicklung erscheint zunächst paradox.

Schließlich investieren wir heute erhebliche Anstrengungen, um Anwendungen einfacher betreiben zu können. Kubernetes abstrahiert Hosts, GitOps

Ähnliche Artikel

Kontakt aufnehmen