Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Forward vs. Reverse Engineering

By EvgenyJan 7, 20228 min read

Diese Seite ist auch in English, Español, Français, Italiano, 日本語 und Português verfügbar.

Vor Kurzem habe ich einen Vortrag über Configuration-Management-Tools und -Techniken gesehen, der einen Gedanken angestoßen hat, den es sich lohnt weiterzudenken.

Alle sind sich einig, dass Tools für Infrastructure-as-Code-Konfigurationsmanagement unverzichtbar und wertvoll sind – und doch ist die Frustration im Umgang mit ihnen erstaunlich groß. Was wäre, wenn die heutigen Mechanismen für Configuration Management oder Infrastructure-as-Code nicht länger ein solches Chaos und derart mühsam in der Anwendung wären? Wie sähe das aus?

Die Karte ist nicht das Gebiet – und doch werden beide gerne verwechselt

Dieser Artikel zeigt, wie DevOps und Softwareentwicklung im Allgemeinen davon profitieren, Provisioning und Konfiguration von Systemen aus einem neuen Blickwinkel zu betrachten – indem vertraute Begriffe in einem neuen Licht erklärt werden.

Beginnen wir mit ein paar Begriffen, die helfen, die Welt um uns herum besser zu verstehen und einige der Probleme anzugehen, mit denen so viele kämpfen.

Begriffe erklärt

Operations: die Disziplin, dafür zu sorgen, dass Softwaresysteme zuverlässig laufen und die Bedürfnisse der Nutzer erfüllen. Operations Engineers schreiben in der Regel weniger neuen Code; sie konzentrieren sich vor allem darauf, wie sich bestehende Software in einem bestehenden System verhält.

Mit diesen beiden Begriffen im Gepäck können wir nun erklären, worin sich "Forward Engineering" und "Reverse Engineering" unterscheiden.

Forward Engineering

Forward Engineering bedeutet, ein System auf Grundlage eines Modells dessen aufzubauen, was in diesem System existieren soll. Beim FE wird zuerst das Modell erstellt und anschließend diese Vorlage in den Betrieb überführt und konfiguriert. Die Erwartung: Das tatsächlich entstehende System entspricht weitgehend dem Modell.

In vielen Fällen ist das deklarierte Modell jedoch mehrdeutig, und das System verhält sich womöglich auf eine Weise, die so nie beabsichtigt war. Das ist bereits eine erhebliche Hürde beim Einsatz solcher Techniken – gerade für Einsteiger.

Erschwerend kommt hinzu: Das System weicht durch die Interaktion mit seiner Umgebung häufig vom Modell ab – etwa, wenn mehrere Komponenten gegenseitig ihre Konfiguration verändern. Oder wenn Ad-hoc-Eingriffe von Engineers das System in alle Richtungen verschieben.

Beim Forward Engineering gibt es kein grundlegendes Konzept einer Rückkopplung an das ursprüngliche Modell. Das Modell wird zuerst "in Stein gemeißelt" und dann ausgerollt. Rückmeldungen, die später vom System zu seinem Verhalten kommen, lassen sich allenfalls für künftige Modellversionen und Deployments nutzen.

Reverse Engineering

Reverse Engineering bedeutet, aus einem bestehenden System ein partielles Modell abzuleiten und dieses als Grundlage für Systemänderungen zu verwenden. Es gibt kein Ausgangsmodell; erst der aktuelle Zustand des Systems lässt erkennen, wie die Dinge eigentlich funktionieren sollten.

Änderungen an einem solchen System werden vielfach ad hoc direkt am System selbst vorgenommen, oft ohne vollständiges Verständnis des Gesamtsystems. Das Feedback ist hier unmittelbar, und ein System wird vor allem dadurch erkundet, dass man daran rüttelt und beobachtet, wie es reagiert.

Wo begegnet uns Reverse Engineering? Sie haben sicher schon gehört, dass Sicherheitsexperten RE-Praktiken nutzen, um sich in bestehende Software hineinzugraben und Sicherheitslücken aufzuspüren. Sie scannen etwa Netzwerkdienste oder den Speicher, um auffälliges Verhalten zu finden, und nutzen dieses aus, indem sie das System zu unbeabsichtigtem Verhalten bringen.

Beim Reverse Engineering geht es darum, ein bestehendes System oder eine Software zu betrachten und auf Basis dessen, was sie in der Praxis tut, zu verstehen, wo Lücken zur ursprünglichen Intention bestehen.

Wo finden wir diese Ideen in der DevOps-Welt wieder?

Infrastructure as Code

Seit der ersten Version von CFEngine aus dem Jahr 1993 hat die Idee, Infrastruktur als Code zu modellieren, in der Software-Engineering-Branche einen rasanten Popularitätsschub erlebt. Sie begann damit, zu deklarieren, wie der Inhalt eines Server-Betriebssystems aussehen soll, und wurde rasch dafür adaptiert, heute Aufbau und Konfiguration von Cloud-Ressourcen zu beschreiben. Im Laufe der Jahre kamen und gingen Unternehmen und Tools wie Puppet, Chef, Salt, Ansible, CloudFormation, Terraform, CDK, Pulumi sowie zahlreiche Eigenentwicklungen.

Eines haben die meisten dieser Tools gemeinsam: Sie sind deklarativ. Deklarative Tools erlauben uns lediglich anzugeben, wie die Dinge sein sollen, ohne explizit zu beschreiben, welche Schritte dorthin führen. In den letzten Jahren sind einige Tools aufgetaucht, die für sich beanspruchen, imperativer zu sein. Im Kern bleiben sie jedoch deklarativ und unterscheiden sich klar von klassischen imperativen Programmiersprachen.

Warum sind die meisten dieser Tools deklarativ?

Die einfache Antwort: weil das der bequemste Weg ist, Karten, Modelle und Vorlagen zu erstellen. Engineers müssen nur deklarieren, wie die Dinge aussehen sollen und wo jedes Element seinen Platz hat – die Schwerstarbeit, jedes Element in die richtige Form zu bringen, lässt sich delegieren. Das ermöglicht eine schrittweise Verbesserung über die Zeit und führt am Ende zu robusteren, stabileren Systemen.

Ein weiterer typischer Vorteil deklarativer Infrastructure-as-Code-Tools ist die Idempotenz. Idempotenz bedeutet, dass eine Aktion mehrfach ausgeführt werden kann und stets zum gleichen Ergebnis führt. Wenn man ein idempotentes Tool nutzt, um ein System mehrfach zu verändern, gelangt es schließlich in den durch die Vorlage deklarierten Zustand. Wendet man danach dieselbe Vorlage erneut an, hat das keine weiteren Auswirkungen mehr. Idempotenz ist die Eigenschaft, die es erlaubt, das Modell mehrfach anzuwenden und das System nur dann zu verändern, wenn Abweichungen vom Modell vorliegen.

Ein imperativer Ansatz würde verlangen, zunächst alle Unterschiede zwischen Modell und System zu finden und dann jeden notwendigen Schritt für jede Änderung umzusetzen. Deklarative Infrastructure-as-Code-Tools erreichen dies, ohne dass Entwickler all diese Aktionen selbst schreiben müssen.

Infrastructure-as-Code-Tools sind beliebt und essenziell; sie sparen Tausende Personenstunden, indem sie wiederverwendbare Vorlagen schaffen und mit minimalem Mehraufwand nahezu identische Systeme über verschiedene Umgebungen hinweg replizieren.

Infrastructure-as-Code verspricht: Eine schrittweise Verbesserung des Modells über die Zeit führt zu robusten, stabilen Systemen auf Basis dieses Modells.

In einem früheren Artikel über Konfiguration für mehrere Systeme habe ich erläutert, warum nahezu identische Systemkopien für ein Softwareunternehmen ein klarer Vorteil sind.

Aber! Diese Tools folgen einer Forward-Engineering-Denkweise – sie sind deklarativ und besitzen keinen Mechanismus, um Feedback aus einem laufenden System zurückzunehmen. Aus diesem Ansatz sind über die Jahre zahlreiche Probleme und Klagen seitens der Anwender entstanden, die wir uns ansehen können.

Probleme mit reinem Forward Engineering bei Infra-as-Code

Haben Sie schon einmal vom Configuration Drift gehört? Er beschreibt den Zustand, in dem das deklarierte Modell nicht mehr mit dem tatsächlichen Zustand eines Systems übereinstimmt. Jedes System wird nach genügend Updates fast immer von dem Modell abweichen, mit dem es ursprünglich erstellt wurde.

Drift kann entstehen, wenn ein Entwickler den Modellcode ändert, ohne alle damit gebauten Systeme nachzuziehen, oder wenn ein Engineer explorative Ad-hoc-Operationen durchführt und ein System verändert, ohne anschließend die Vorlage entsprechend zu aktualisieren. Beide Tätigkeiten sind unverzichtbar: Entwickler tun Ersteres, um Verbesserungen in künftige Deployment-Iterationen einfließen zu lassen; Operations Engineers tun Letzteres häufig, um unbekannte Probleme aufzuspüren und zu beheben.

Configuration Drift ist natürlich eine klassische Tretmine, die nur darauf wartet, hochzugehen – weshalb alle predigen, man solle Configuration Drift vermeiden. Aber ist es realistisch, Operatoren den Betrieb der Systeme zu untersagen, um jegliche Ad-hoc-Exploration auszuschließen? Ja. Manche Unternehmen machen es zur Vorgabe, dass weder Operator noch Entwickler ein "lebendes Produktivsystem" anfassen dürfen. Sie können sich vorstellen, was eine solche Richtlinie mit der Mean-Time-to-Recover solcher Systeme anstellt. Aus eigener Erfahrung: Wenn die Hütte brennt und ein "Produktivsystem" aus irgendeinem Grund streikt, ist diese Regel die Erste, die über Bord geht – und Ad-hoc-Exploration ist sofort für jeden erlaubt, der herausfinden kann, was los ist.

Engineers, die zu Infrastructure-as-Code überredet wurden, beklagen, dass es zu aufwendig ist, ein bestehendes System von Grund auf nachzumodellieren. Es findet sich immer jemand, der ein Tool baut, das dabei helfen soll. Google hat GCP Terraformer, AWS hatte den inzwischen eingestellten AWS CloudFormer, und selbst Azure verstreut sein ARM über die gesamte Cloud-Konsole. Für jede gängige Configuration-Management-Sprache findet sich jemand, der ein solches Tool baut – die Nachfrage ist einfach riesig.

Doch leider sind Engineers nach dem Einsatz eines solchen Tools meist enttäuscht. Das Ergebnis ist entweder zu viel Rauschen, das keinen Sinn ergibt, oder bestenfalls schon einen Tag später überholt. Das Beste, was man mit einer solchen rückwärts erzeugten Vorlage anfangen kann, ist, einzelne Snippets per Copy-and-Paste in eine an anderer Stelle handgeschriebene Vorlage zu übernehmen.

Wie es besser weitergehen kann

Dieser Artikel hat zwei Begriffe definiert und gezeigt, warum reines Forward Engineering für den tatsächlichen Betrieb von Systemen suboptimal ist und warum Reverse Engineering in den meisten Fällen nach wie vor unverzichtbar bleibt, um Probleme zu finden und zu lösen.

Der Vorschlag lautet nun: eine neue Generation von Infrastructure-as-Code-Tools zu schaffen – Tools, die Reverse Engineering ins Zentrum stellen und Feedback aus laufenden Systemen zulassen, um die Modelle zu aktualisieren, aus denen sie hervorgegangen sind. Operatoren können entweder die Ad-hoc-Änderung übernehmen oder sie verwerfen und das System in den Zustand zurückversetzen, der im ursprünglichen Modell deklariert wurde.

Bestehende Industriestandard-Tools versagen darin, Engineers bei den Problemen zu unterstützen, die im Systembetrieb auftreten. Ja, es gibt einige Tools, die Ihre Terraform-Vorlagen prüfen und auf Fehler oder Fehlkonfigurationen hinweisen. Solche Audits sind hilfreich – doch der eigentliche Mehrwert liegt darin, ein bestehendes, lebendes System zu inspizieren, und nicht nur die Vorlage, mit der Engineers es einst erstellt haben.

Soweit ich sehe, gibt es bislang kein wirklich gutes Tool, das Reverse-Engineering-Praktiken sinnvoll in den Arbeitsalltag von Operations Engineers integriert. Auf der einen Seite haben wir eine Vielzahl an Monitoring- und Observability-Tools, auf der anderen jede Menge Infrastructure-as-Code-Tools – und dazwischen klafft eine beträchtliche Lücke.

Haben Sie Ideen, wie wir diese Lücke schließen können? Schreiben Sie es uns!

Coverbild von Tabea Schimpf auf Unsplash.