
Einführung
Guten Tag an alle. Ich bin ein Python-Entwickler in einem Unternehmen, das sich mit komplexen Lösungen zur Automatisierung von Geschäftsprozessen, zur Entwicklung einzelner Aufgaben, zur Analyse und Beratung befasst. Zu meinen Aufgaben gehört die Entwicklung und Wartung der Microservice-Architektur. Und heute möchte ich erzählen, wie wir mit Microservices zu kämpfen haben und warum die Vereinheitlichung für sie so wichtig ist.
Es ist kein Geheimnis, dass dieser Ansatz zur Produktentwicklung den Markt zunehmend erobert. Und je mehr wir uns in sie stürzen, desto mehr ist es notwendig, die Grundregeln für die Arbeit mit ihnen nicht zu vergessen. Um unsere Erfahrung beim Schreiben von Microservice-Produkten zu strukturieren, wurde beschlossen, eine Reihe von Artikeln darüber zu verfassen, wie einige Aspekte der Entwicklung auf alle Services verallgemeinert werden können.
Eine solche Regel ist die Vereinigung. In unserem Unternehmen bestehen die meisten Produkte aus einer Reihe bunter Sprachen und Technologien. An diesem Stand müssen Sie darüber nachdenken, wie Sie die Grundprinzipien für alle Microservices verallgemeinern können, um sie einfach zu unterstützen, zu konfigurieren und bequem zu entwickeln. Dies wird in der Reihe dieser Artikel erörtert.
Ich frage alle Interessierten unter Katze.
Das Problem
Vielleicht sind die Konfigurationsmethoden das erste, auf das Sie bei der Entwicklung eines Dienstes stoßen. In der Microservice-Architektur wird dieses Problem noch akuter.
Stellen Sie sich vor, Sie haben zwei Dutzend Dienste und müssen jeweils einen Parameter ändern. Deaktivieren Sie beispielsweise die Verwendung von CORS. Da das System mehrkomponentig ist und auf Mikrodiensten basiert, ist es für eine bequeme Verwaltung am besten, einen einheitlichen Ansatz für die Konfiguration aller Module zu verwenden. Daher müssen Sie beim Einrichten der einzelnen Module denselben Ansatz verwenden.
Sie können sagen, dass der Entwickler jedes Dienstes dies tun sollte, aber was ist, wenn alle Ihre Konfigurationen in denselben Kubernetes gespeichert sind, wo nicht alle Entwickler angegeben werden können? Arme DevOps werden gezwungen sein, viel Zeit damit zu verbringen, nur die Dienste und ihre Konfigurationsmethoden zu lernen. Dieser Vorgang wird mit der Aktualisierung der Dienste wiederholt, insbesondere wenn jemand in den Diensteinstellungen etwas Neues ausprobieren möchte. Mit diesem Ansatz wird das Team ständig einen Teil der Zeit damit verbringen, mit Konfigurationen zu arbeiten und keine neuen Funktionen zu entwickeln, Fehler zu beheben usw.
Nur für diesen Fall ist eine allgemeine Konfigurationsmethode erforderlich, die nicht an eine bestimmte Sprache oder Technologie gebunden ist und es Ihnen ermöglicht, alle Dienste mit minimalen Unterschieden in der allgemeinen Struktur der Konfiguration zu konfigurieren. Für diese Aufgabe haben wir ein System zum Einrichten von „Modulen“ (Diensten) unter Verwendung von Yaml-Dateien entwickelt, mit dem Konfigurationen für verschiedene Phasen (dev / prod / local usw.) gespeichert und das Ganze in verschiedene Blöcke unterteilt werden können, die sich auf bestimmte Dinge beziehen.
Spezifikation
Sie können viel darüber sprechen, wo und wie es verwendet wird, aber ich schlage vor, direkt zur Spezifikation dieser Konfigurationsmethode zu gehen. Wie sie sagen, ist Theorie gut und Praxis noch besser.
Systemanforderungen
Beginnen wir mit der Definition unseres Systems und der Anforderungen dafür.
- Jedes Modul ist eine unabhängige Komponente im Container
- Wir können Umgebungsvariablen an den Container übergeben
- Wir können die Konfiguration nicht im laufenden Betrieb ändern, ohne den Dienst neu zu starten (Erstellen eines neuen Containers).
- Alle Fallback-Aktionen (wie das Wechseln zur Sicherungsdatenbank) werden außerhalb der Komponente ausgeführt und sind für diese transparent.
Anforderungen an die Konfigurationsmethode
Lassen Sie uns nun entscheiden, was wir von unserer Konfigurationsmethode sehen möchten, um alle Anforderungen zu erfüllen.
- Der Typ der Konfigurationsdatei ist die YAML der angegebenen Struktur. YAML wurde von uns aus mehreren Gründen ausgewählt:
- Fähigkeit, Kommentare zu schreiben und eine bequeme Struktur, im Gegensatz zu JSON
- Fähigkeit, Arrays im Gegensatz zu ENV zu beschreiben
- Out of the Box kann für die Aufnahme von values.yaml in helm (Kubernetes) verwendet werden.
- Konfigurationsdateien sollten in den Konfigurationsbaum eingefügt werden
- Die Konfiguration muss stufenspezifisch sein. Jede Stufe hat ihren eigenen kompletten Satz. Hier lohnt es sich, einige Vorbehalte zu machen, um Folgendes zu klären:
- Sie können die Werte von Variablen aus einer anderen Stufe nicht wiederverwenden , mit Ausnahme der Standardstufe, die für Standardwerte reserviert ist.
- Beim Laden der Konfiguration müssen Sie eine rekursive Zusammenführung der Konfigurationsebene von der angegebenen Stufe über die Standardeinstellungen mit der Ebenenpriorität der angegebenen Stufe durchführen. Werte (Arrays usw.) sollten nicht kombiniert werden.
- Wenn für eine Stufe mehrere Konfigurationsdateien vorhanden sind, müssen die darin enthaltenen Schlüssel zusammengeführt und dementsprechend relativ zueinander eindeutig sein.
- Die aktuell verwendete Stufe muss durch den Wert der Umgebungsvariablen „STAGE“ bestimmt werden. Das Ändern einer Variablen in einer laufenden Instanz eines Dienstes ist nicht beabsichtigt.
- Der absolute Pfad zum Konfigurationsverzeichnis sollte durch den Wert der Umgebungsvariablen „CONFIG_PATH“ bestimmt werden. Der Einfachheit halber ist ein Fallback möglich, wenn sich in einem bestimmten Standardpfad keine Variable befindet, was in der Dokumentation für das Modul angegeben werden sollte. In diesem Fall muss der angegebene Pfad relativ zum Stammverzeichnis des Anwendungsverzeichnisses sein.
Konfigurationsbeispiele
Angenommen, wir haben einen Dienst, der Einstellungen für die Verbindung zu Postgres sowie einige Informationen über uns selbst speichern muss
Zuerst müssen Sie eine Konfiguration für STAGE = Defaults definieren. Darin werden wir die allgemeine Struktur beschreiben und Daten unabhängig von der Stufe machen.
Standardeinstellungen
# configuration/defaults/service.yaml defaults: version: 1.0.0 name: "config-example" # configuration/defaults/redis.yaml defaults: redis: host: "host" db: 0 port: 6379 password: "password"
dev
# configuration/dev/redis.yaml dev: redis: host: "localhost" password: "hard_pwd"
Resultierende Konfiguration
version: 1.0.0 name: "config-example" redis: host: "localhost" db: 0 port: 6379 password: "hard_pwd"
Schlussfolgerungen
Auf diese listige Weise haben wir das Problem der Konfiguration von Diensten in unserem Zoo gelöst und alles zu einer gemeinsamen Sichtweise gebracht. Dieses Beispiel ist nur ein Ausgangspunkt und kann an die Besonderheiten Ihres Projekts angepasst werden.
Für diejenigen, die an dieser Konfigurationsmethode in „nackter Form“ interessiert sind:
Unsere Pakete für verschiedene Programmiersprachen Für die Hilfe beim Schreiben ein besonderes Dankeschön an
Roque ,
SMGladkovskiy