Wie strukturiere ich DevOps-bezogenen Code und Konfigurationen in einem Code-Repository?

10

Wir sind als Unternehmen gewachsen, unsere Produkte expandieren und unsere Aktivitäten und Bemühungen im Zusammenhang mit DevOps nehmen ebenfalls zu. Wir haben mithilfe von Bereitstellungspipelines und anderen Plugins von Bamboo auf flexiblere und konfigurierbarere Jenkins umgestellt. wechselte zu Ansible und begann hier und da intern mit Docker.

All diese Dinge erfordern ein gewisses Maß an Codierung oder Konfiguration - Ansible-Skripte und -Konfigurationen, Jenkins-Groovy-Skripte, Dockerfiles und YAML-Konfigurationen.

Denn jetzt haben wir ein separaten „ops“ Repository mit High-Level - Verzeichnissen für erstellt jenkins, ansible, dockerund other(das ist ein schrecklicher Name, aber für jetzt alle „andere“ DevOps Automatisierung Dinge sind dort).

Unser Ansatz fühlt sich nicht richtig an und lässt sich möglicherweise nicht skalieren. Was sind jedoch die Best Practices und Empfehlungen, um DevOps-bezogenen Code in einem Code-Repository oder in Repositorys zu speichern?

Alecxe
quelle
6
Ich gehe mit der Methode "Jeder Teil ist eine App, ein Repo pro App", in Chefkoch bedeutet das 1 Repo pro Kochbuch.
Tensibai
@ Tensibai richtig, ich hatte Angst, dass ein einzelnes "Ops" -Repo schnell unpraktisch werden würde. Vielen Dank.
Alecxe
1
Das war die Legacy-Form des Kochbuchmanagements in Chefkoch, 1 Repo mit allen Kochbüchern und hat sich in den meisten Fällen als Fußwaffe erwiesen, daher die Änderung, aber ich bin weniger zufrieden damit, zu sagen, dass es auch passen würde, Jenkins Pipelines (wenn v2) und Docker-Dateien sollten mit dem Projekt leben, mit dem sie IMO bearbeiten, und ich habe keine Ahnung, was Sie unter andere stellen, daher kann ich hier keinen wirklichen Rat geben
Tensibai
@ Tensibai hat es verstanden! Andere bestehen hauptsächlich aus Bash- und Python-Dienstprogrammen oder periodisch ausgeführten Skripten für mehrere interne Tools. Sie passen nicht wirklich irgendwo hin und wir könnten uns keinen besseren Ort als "andere" vorstellen. Ich werde sehen, ob ich den Inhalt veröffentlichen kann der Verzeichnisse auch in die Frage. Vielen Dank.
Alecxe
1
Ich würde sie in mehrere Repos nach "Affinität" der Arbeit aufteilen, Skripte, die zusammen an App X arbeiten. Möglicherweise wird ein Skript für zwei Apps verwendet. Wenn sich jedoch die App ändert, muss das Skript die App handhaben, mit der es kommuniziert Es ist besser, zwei getrennte Versionen zu haben, also würde ATEOTD sie mit der Anwendung speichern, auf die sie sich beziehen, oder wenn sie mehrere Aufgaben in einem bestimmten Repository pro Aufgabe umfassen, sodass Sie immer eine Version haben, die den bereitgestellten Anwendungen entspricht, und Sie nicht Es muss nicht gleichzeitig ein nicht verwandtes Skript markiert werden.
Tensibai

Antworten:

3

Die aktuelle Organisation des von Ihnen beschriebenen Codes und der Konfiguration wird durch die beteiligten technischen Lösungen strukturiert. Dies ist ein schlechtes Design, das viel Aufwand bei unseren Wartungsaktivitäten und viele Fallen auf unserem Weg verursacht. Stattdessen sollte diese Organisation nach den von uns bereitgestellten Artefakten strukturiert sein .

Der Grund dafür ist, dass wir Artefakte ( z. B. ein Docker-Image oder ein Softwarepaket) als Objekte der folgenden Verben betrachten möchten :

  • bauen
  • Prüfung
  • bereitstellen

um einen minimalen Satz automatisierter Aufgaben zu berücksichtigen, die wir ausführen möchten. Wenn Sie etwas an der Implementierung des Testverbs ändern möchten, können Sie den Ordner, der diesem Artefakt entspricht, im entsprechenden Repository aufrufen und dann die Jenkins-spezifischen Automatisierungselemente ermitteln, die aktualisiert werden müssen. Wenn die Automatisierungsrezepte nach technischen Lösungen strukturiert sind, müssen wir aus heiterem Himmel herausfinden, dass Jenkins an den Testverfahren beteiligt ist, und dort die artefaktbezogenen Automatisierungselemente finden. In komplexen Situationen macht die Organisation um technische Lösungen Aktualisierungen sehr schwierig, da wir a priori alle technischen Lösungen kennen müssen, die an einem Service beteiligt sind, um sie entsprechend zu aktualisieren.

Beispielsweise kann ein Repository, das den Code für eine Website und einen Mikrodienst "a" enthält, die folgenden Unterverzeichnisse für Vorgänge enthalten:

./ops/website
./ops/micro-service-a

die jeweils drei Skripte genannt build, testund deploy. Nachdem die Organisation der Automatisierungselemente irgendwie geklärt wurde, wenden wir uns der Konfiguration zu.

Die Hauptbedingungen und -anforderungen für die Konfigurationsorganisation werden durch das deployVerb festgelegt, wenn es auf ein serviceähnliches Artefakt angewendet wird. Das deployVerb sollte folgende Parameter haben:

  • die Version des zu implementierenden Artefakts,
  • das Bereitstellungsziel des Artefakts, das die konkrete Umgebung beschreibt, in der das bereitgestellte Artefakt ausgeführt wird ( z. B. ein Cluster und Endpunkte, mit denen es kommunizieren soll)
  • die Anmeldeinformationen, mit denen eine Verbindung zu anderen Endpunkten ( z. B. Datenbanken) hergestellt werden soll
  • die Laufzeitkonfiguration von (wie lange Cache-Einträge leben sollen, etc.)

Aus betrieblicher Sicht entspricht diese Aufschlüsselung der Parametrisierung den natürlichen Freiheitsgraden des Bereitstellungsproblems - abgesehen von den Anmeldeinformationen, die mit der Laufzeitkonfiguration gebündelt werden könnten. Es ist jedoch besser, sie zu trennen, um eine unachtsame Verbreitung zu vermeiden.

Michael Le Barbier Grünewald
quelle
5

Ich kann auf Docker antworten. Eine der besten Methoden zur Verwendung von Docker besteht darin, die Docker-Datei und die Compose-Dateien im selben Repository des Projekts zu belassen. Überall dort, wo Sie das Projekt klonen, können Sie das Docker-Image erstellen Behalten Sie beispielsweise mehrere Versionen von Docker Compose-Dateien (Prod, Staging, Dev) bei, damit Sie das Image erstellen und den Container mit einer bestimmten Option für jede Umgebung ausführen können. Beispielsweise können Sie für einen Dev-Computer ein bestimmtes Netzwerk verwenden und mehr Abhängigkeitscontainer oder was auch immer ausführen.

Wissam Roujoulah
quelle
4

Der Code jedes Tools geht in ein eigenes Repo. für zB

  1. Jenkins Groovy Vorlage in ein Jenkins Repo
  2. Ansible YAML-Playbooks in einem eigenen Repo (mit den Rollen, Aufgaben, Inventar-Unterverzeichnissen
  3. Cloudformation / Terrform-Vorlagen in einem eigenen Repo
  4. Docker-Dateien in eigenen 5 .. Und so weiter

Dies würde Ihnen helfen, die Prozess-Orchestrierung besser zu skalieren und verschiedene Zweige für jede Umgebung zu verwalten

Dies würde Ihnen eine detailliertere Kontrolle geben und Ihren gesamten Versionsaufwand auf die Versionskontrollsysteme verlagern. Erstellen Sie außerdem separate Zweige für jede Umgebung und kennzeichnen Sie den Code für jede Produktionsversion (wie bei der Anwendungscodebasis). Denken Sie an Infra und verarbeiten Sie in Bezug auf Code. (Jede Änderung des Prozesses muss kodifiziert und an QA, SIT, UAT und dann an PROD gesendet werden.) Ähnlich wie bei der Anwendung.

Zum Beispiel kann V2.1 von Ansible in der Produktion (Hauptzweig) ausgeführt werden, während V2.0 von Docker-Containern in Prod (Hauptzweig) ausgeführt wird.

Bewahren Sie Ihre DB-Skripte / Bash-Skripte auf ähnliche Weise in ihren eigenen Repositorys auf. Möglicherweise können Sie eine Healthcheck-Datei (JSON / YAML) konfigurieren, um die Versionen aller Tools / Teile in jeder bereitgestellten URL für Nachverfolgungs- und Automatisierungszwecke anzuzeigen. (Damit Ihre Webhooks die URL lesen und Bereitstellungen automatisieren)

Ameen Ibrahim Raffic - "AIR"
quelle
2
Die Gefahr dieses Ansatzes besteht darin, dass v2.1 in qa und nicht validiert ist und Sie die Produktion dringend patchen müssen. Sie können v2.0 nicht ändern. Wenn Sie eine v2.2 für diesen Patch erstellen, besteht ein hohes Risiko, dass dies der Fall ist verloren oder überschrieben, wenn v2.1 in Produktion geht, multiplizieren Sie mit der Menge an separatem Code in einem Repo und Sie haben bald einen Albtraum von Backports (es funktioniert, aber ich musste diesen Haftungsausschluss hinzufügen :))
Tensibai
3
Die Verwendung von Zweigen zum Verfolgen von umgebungs- / bereitstellungsspezifischen Informationen scheint mir ein Ameisenmuster zu sein: Wenn wir 20 Umgebungen haben, bedeutet dies, dass wir 20 Zweige synchron halten müssen… eine wahrscheinliche Quelle für Fehler und Verwirrung. Können Sie erklären, warum Sie keine Konfigurationsdateien verwenden, um umgebungs- / implementierungsspezifische Informationen zu erfassen, und wie Ihr Workflow mit diesen Zweigen arbeitet? Dies sind keine trivialen Probleme!
Michael Le Barbier Grünewald
3

Die Unterscheidung zwischen Ops, Dev und DevOps fördert die Isolation und erzwingt die Einstellung "Über die Mauer werfen". Um die Zusammenarbeit zwischen den Teams zu verbessern, sollte alles in ein Repository gestellt werden, das zum Erstellen und Bereitstellen des Projekts erforderlich ist.

Trotzdem die Antwort auf die Frage:

Wie strukturiere ich DevOps-bezogenen Code und Konfigurationen in einem Code-Repository?

Wenn config zum Ausführen des Projekts erforderlich ist, sollte es im selben Verzeichnis abgelegt werden.

030
quelle