Zwölf Erfolgsprinzipien für Cloud Native Apps

Zwölf Erfolgsprinzipien für Cloud Native Apps

In der Vergangenheit haben sich bei der Entwicklung von Anwendungen, die schnell skalieren, zuverlässig und konsistent gewartet und released werden können, zwölf Prinzipien als essentiell herauskristallisiert.

Diese Prinzipien sind unter dem Begriff The Twelve-Factor App von Adam Wiggins publiziert worden. Vor allem bei der Entwicklung von Anwendungen, die für den Cloudbetrieb ausgelegt sind, kommt man an diesen Prinzipien nicht vorbei.

Wir stellen Dir diese nachfolgend vor und gehen auf zwei davon genauer ein.

1. Codebasis

Das erste Prinzip besagt, dass es genau eine versionsverwaltete Codebasis pro Anwendung geben soll. Diese Codebasis muss alle Artefakte enthalten, die notwendig sind, um die Anwendung zu bauen, installieren, betreiben und überwachen.

Diese Codebasis muss der Entwicklung, den Tester:innen, dem Continuous Integration/Delivery Server und dem IT-Betrieb zugänglich sein.

Wenn es mehr als eine Codebasis gibt, dann ist es keine Anwendung, sondern ein verteiltes System. Jede Komponente in einem verteilten System ist eine Anwendung, die für sich genommen den 12 Prinzipien genügen muss.

Mehrere Anwendungen, die denselben Code teilen, verstoßen gegen die 12 Factor Prinzipien. Die Lösung besteht darin, gemeinsam genutzten Code in Bibliotheken einzubinden, die über den Abhängigkeitsmanager eingebunden werden können.

Codebasis und Einwirkungen

2. Abhängigkeiten

Das zweite Prinzip betrachtet die externen Abhängigkeiten und legt fest, dass alle externen Abhängigkeiten explizit und separat vom Source Code definiert werden. Nur der einzigartige und für den Zweck der Anwendung benötigte Anwendungscode und die Deklaration der Abhängigkeiten soll in der Codebasis verwaltet werden. Externe Artefakte wie Node.js Pakete oder Java .jar files gehören nicht in die Codebasis.

Codebasis mit Büchern

Maven Konfiguration mit Abhängigkeiten(gekürzt):

3. Konfiguration

Das dritte Prinzip legt fest, dass die Konfiguration vom Anwendungscode getrennt sein muss. Man kann die Konfiguration der Anwendung entweder als Umgebungsvariable in die Laufzeitumgebung injizieren oder in einer separaten Konfigurationsdatei deklarieren.

Der Vorteil dieser Trennung ist, dass die Konfiguration für die unterschiedlichen Entwicklungsumgebungen einfach angepasst werden kann.

Anhand einer Spring Boot Applikation soll das hier verdeutlicht werden.

Hier ein Beispiel für eine Konfiguration, in der im Code die Datenbankverbindung fest verdrahtet ist:

spring:

    datasource:

        url: jdbc:mysql://mydbserver:12324/12factors

        username: someuser

        password: highsecuritypassword

Auch wenn Spring Boot das Überschreiben der Properties erlaubt, wäre die folgende application.yaml besser für eine 12factor-App geeignet.

spring:

    datasource:

        url: ${MYSQL_CONNECTION}

        username: ${MYSQL_USERNAME}

        password: ${MYSQL_PASSWORD}

In Kubernetes kann jetzt eine sogenannte Configmap definiert werden, die die obigen Daten enthält, wie die MySQL Verbindungsdaten, Benutzername und Passwort.

Kubernetes ConfigMap

apiVersion : v1

kind : ConfigMap

metadata:

    name : mysqlconfig

data:

    connection: jdbc:mysql://mydbserver:12324/12factors

    username: someuser

    password: highsecuritypassword

Obiges Beispiel dient zur Illustration des Konzepts. In einer realen Anwendung würde man aus Sicherheitsgründen Kubernetes Secrets für Username und Passwort nehmen.

Der letzte Schritt ist dann die Verbindung zwischen der Anwendung und der ConfigMap. Hier werden dann die Umgebungsvariablen basierend auf den Daten der ConfigMap gesetzt.

apiVersion: v1

kind: Pod

metadata:

  name: 12factorapp

spec:

  containers:

    - name: 12factorapp

      image: 12factorapp:latest

      env:

        - name: MYSQL_CONNECTION

          valueFrom:

            configMapKeyRef:

              name: mysqlconfig

              key: connection

        - name: MYSQL_USERNAME

          valueFrom:

            configMapKeyRef:

              name: mysqlconfig

              key: username

        - name: MYSQL_PASSWORD

          valueFrom:

            configMapKeyRef:

              name: mysqlconfig

              key: password
Konfiguration

4. Externe Anwendungen (Backing Services)

Das vierte Prinzip definiert, dass externe Komponenten wie Datenbanken, Message Broker und ähnliches als angehängte Ressourcen behandelt werden. Diese Vorgehensweise fördert die Flexibilität und Effizienz im Software Entwicklungsprozess.

5. Baue, Release und Lasse laufen

Beim fünften Prinzip wird die Etappentrennung vorgeschrieben: Trenne die Etappen des Installationsprozesses in eine Build-, Release- und Run-Phase.

  • In der Build-Phase wird der Source Code kompiliert, gebaut und in ein Archiv wie Maven Central oder Docker Hub geladen.
  • In der Release-Phase werden die Konfigurationsdateien angewandt.
  • In der Run-Phase wird die Laufzeitumgebung provisioniert und die Anwendung wird samt ihrer Abhängigkeiten dorthin geladen.

6. Prozesse

Das sechste Prinzip erklärt, dass die Anwendung als ein Set von mehreren zustandslosen (stateless) Prozessen ausgeführt werden soll. Das bedeutet konkret, dass die Anwendung keine Informationen über den Session- bzw. Prozess-Status speichern sollte.

Auf diese Weise ist es einfacher, eine Anwendung zu skalieren und man vermeidet unerwünschte und schwer nachzustellende Nebeneffekte.

7. Portbindung

Das siebte Prinzip besagt, dass ein Dienst oder eine Anwendung für das Netzwerk anhand der Portnummer und nicht anhand eines Domänennamens identifizierbar sein soll. Der Grund ist, dass Domainnamen und zugehörige IP-Adressen durch manuelle Manipulation und automatisierte Service-Discovery-Mechanismen on-the-fly zugewiesen werden können. Daher ist es unzuverlässig, sie als Bezugspunkt zu verwenden. Das Prinzip der Portbindung ist zuverlässiger und einfacher zu verwalten. Zudem können potenzielle Probleme aufgrund einer Kollision zwischen der privaten Portnummernzuweisung an das Netzwerk und der öffentlichen Verwendung derselben Portnummer durch einen anderen Prozess durch Portweiterleitung vermieden werden.

Die wesentliche Idee hinter dem Prinzip der Portbindung ist, dass die einheitliche Verwendung einer Portnummer der beste Weg ist, einen Prozess dem Netzwerk zugänglich zu machen. Zum Beispiel haben sich folgende Standards herauskristallisiert: Port 80 für Webserver unter HTTP, Port 443 für HTTPS, Port 22 für SSH, Port 3306 ist der Standardport für MySQL und Port 27017 für MongoDB.

8. Nebenläufigkeit

Das achte Prinzip der Nebenläufigkeit begründet, dass die Prozesse nach ihrem funktionalen Zweck organisiert werden sollen, um unabhängig voneinander skalierbar zu sein. Unterstützung von Nebenläufigkeit bedeutet, dass verschiedene Komponenten einer Anwendung unabhängig von anderen Komponenten öfter ausgeführt werden können oder weniger oft als andere Komponenten. Anwendungen, die Nebenläufigkeit nicht unterstützen, können nur in ihrer Gesamtheit skaliert werden.

9. Verfügbarkeit

Das neunte Prinzip erklärt, dass Anwendungen ordnungsgemäß gestartet und beendet werden sollen. Das heißt konkret, dass alle erforderlichen Vorarbeiten durchgeführt werden müssen, bevor eine Anwendung für Verbraucher zugänglich gemacht wird. Ein ordnungsmäßiger Start stellt bspw. sicher, dass alle Zugriffe auf Ressourcen betriebsbereit sind und alle Konfigurationsarbeiten abgeschlossen wurden.

Im Bezug auf das Herunterfahren empfiehlt das Prinzip sicherzustellen, dass alle Ressourcenzugriffe ordnungsgemäß beendet werden und alle Aktivitäten zum Herunterfahren protokolliert werden.

10. Entwicklung-Produktion-Parität

Kurz zusammengefasst besagt das zehnte Prinzip, dass alle Umgebungen (Entwicklung, Integration, Produktion) so ähnlich wie möglich ausgestattet sein sollten und dass keine der umgebungsspezifischen Phasen aus Punkt 5 übersprungen werden soll.

Konkret bedeutet das zum einen, dass die Bereitstellungspipelines für alle Umgebungen nahezu identisch sein sollen und zum anderen, dass die externen Anwendungen in allen Umgebungen so ähnlich wie möglich sein sollten (dieselbe Datenbank, nur unterschiedliche Instanzen für unterschiedliche Umgebungen; dieselbe Message Queue, usw. ).

Zum dritten heißt das Prinzip auch, dass die Anwendung in jeder Umgebung die umgebungsspezifischen Phasen release und run eigenständig durchlaufen muss. Das Prinzip wäre verletzt worden, wenn man die deployten Artefakte aus der Entwicklungsumgebung in die Integrationsumgebung kopiert.

11. Logs

Das elfte Prinzip befürwortet das Senden von Protokolldaten in einem Stream, auf den eine Vielzahl interessierter Verbraucher:innen zugreifen können. Der Prozess zum Weiterleiten von Protokolldaten muss von der Verarbeitung derer getrennt sein.

Beispielsweise könnte ein Consumer nur an Fehlerdaten interessiert sein, während ein anderer Consumer an Anforderungs-/Antwortdaten interessiert sein könnte. Ein anderer Verbraucher könnte daran interessiert sein, alle Protokolldaten für die Ereignisarchivierung zu speichern.

Ein zusätzlicher Vorteil ist, dass selbst wenn eine App ausfällt, die Protokolldaten noch lange danach weiterleben.

12. Admin Prozesse

Das letzte Prinzip der 12 Factor Apps befürwortet, dass die Admin Prozesse als first-class citizens des Softwareentwicklungs-Lebenszyklus behandelt werden sollen.

Damit ist gemeint, dass für diese Prozesse ebenfalls die oben genannten Prinzipien 1. Codebasis, 5.  und 10. gelten. Sie sollten nicht als etwas Separates, sondern als ein Teil des Softwareentwicklungs-Lebenszyklus betrachtet werden.

Die Nutzung dieser Best Practices ist in der professionellen Softwareentwicklung essentiell, um Anwendungen sicher, skalierbar und wartbar zu programmieren.

Dies führt zu einer höheren Effizienz bei der Entwicklung und dem Betrieb von Anwendungen, was wiederum zu einer besseren Userexperience und einer höheren Zufriedenheit der Kunden führt.

Kurz gesagt, die Anwendung der 12 Faktoren sorgt für eine bessere Qualität und Zuverlässigkeit.

Diese zwölf Faktoren stellen das Fundament für bewährte Praktiken bei der Entwicklung von Cloud Native Anwendungen dar. Mit der Zeit haben sich noch weitere Best Practices herauskristallisiert, die wir in einem Folgebeitrag vorstellen werden.

– Ein Gemeinschaftsbeitrag unseres Standorts Karlsruhe –