Problem
Bei großen und technisch komplexen Projekten, an denen in der Regel viele verteilte Teams gleichzeitig arbeiten, gibt es ein bekanntes Problem bei der Entwicklung versionierter Software, das verschiedene Unternehmen unterschiedlich lösen.
Derzeit liefern einige unserer Kunden und Partner die neuesten Versionen (CI / CD) manuell an die Produktion, indem sie die neuesten / aktuellen Versionen ihrer Software installieren, nachdem sie diese zuvor mit dem Rest der Umgebung getestet haben. Zum Beispiel durch Bereitstellung von Builds von iOS-, Android- usw. Anwendungen, wenn es sich um Client-Software handelt, oder durch Aktualisieren von Docker-Images in einer Docker-Umgebung, wenn es sich um Backend handelt. Bei großen und wichtigen Projekten, bei denen die Entscheidung, jedes Mal eine neue Version in Production zu veröffentlichen, vom Projektmanager getroffen wird, ist eine solche Entscheidung gerechtfertigt und nicht zu kostspielig, insbesondere wenn Releases nicht häufig veröffentlicht werden. In der Testentwicklungsumgebung (Dev / Stage-Umgebung) führt die Verwendung von „manuellen“ Tools jedoch zu einer Komplexität des Projekts, einer möglichen Unterbrechung der Impressionen für den Kunden usw. Dies kann viele Gründe haben, darunter Inkonsistenzen in den Versionen verschiedener Container in Middleware-Software oder das Fehlen eines detaillierten Versionsverlaufs.
Wir mussten dies persönlich sicherstellen und hatten große Schwierigkeiten bei einem großen Projekt, bei dem täglich 6-8 neue Softwareversionen im Backend und 2-3 Softwareversionen im Frontend im CI-System veröffentlicht wurden, bei denen Testingenieure die Last und nicht objektiv bewältigen konnten Es gab einen ständigen Mangel an Verständnis dafür, welche Version der Software im Frontend / Backend im Moment als stabil angesehen wurde.
Unsere Erfahrung
Unser Unternehmen verwendet bei seiner Arbeit verschiedene CI / CD-Systeme, deren Auswahl häufig von den Anforderungen des Kunden abhängt. Beispielsweise stoßen unsere Spezialisten häufig auf CI / CD-Systeme wie Jenkins, TeamCity, Travis CI, Circle CI, Gitlab CI und Atlassian Bamboo, bei denen wir manchmal ausschließlich an der Infrastruktur des Kunden arbeiten. Dementsprechend liegt bei diesem Ansatz das Problem bei der Lösung der Versionierung vollständig beim Kunden.
Wenn wir Lösungen für Kunden entwickeln und die Möglichkeit haben, dies in unserer eigenen Infrastruktur zu tun, verwenden wir TFS Version 2018 als Grundlage für das Continuous Integration / Continuous Delivery-System. Dies ermöglicht es uns, die Hauptaufgabe zu lösen, einen vollständigen Softwareentwicklungszyklus zu erstellen, nämlich:
- Aufstellung der Aufgaben (Probleme, Fehler, Aufgaben) basierend auf dem im aktuellen Projekt verwendeten Ansatz zur Softwareentwicklung;
- Speicherung des Projektquellcodes;
- Bereitstellung der Infrastruktur von Build-Agents für Assemblys für verschiedene Betriebssysteme (Windows, Linux, MacOS);
- Zusammenstellen von Projekten im "manuellen" Modus und CI;
- Bereitstellung von Projekten im "manuellen" Modus und auf CD;
- Projekte testen;
- Bildung von Daten über die Zeit, die Mitarbeiter für das Projekt aufgewendet haben, und eine Reihe zusätzlicher Funktionen, die wir mithilfe von TFS-Erweiterungen unseres eigenen Designs und durch Hinzufügen von Statiken zu WIT implementiert haben (in dieser Form ersetzte TFS unser Unternehmen Redmine und vereinfachte die Erfassung von Statistiken, Berichten usw. im Rahmen von Projekten )
In diesem Fall wäre es logisch, TFS die Lösung für das Versionsproblem zuzuweisen und die TFS-Funktionalität für unsere Aufgaben und die Wünsche des Kunden zu finalisieren. Infolgedessen wurde die Aufgabe, ein Versionsverwaltungssystem für Microservice-Architekturprojekte zu erstellen, durch TFS-Tools gelöst, indem verschiedene Build-Skripte angepasst und Test- / Release-Umgebungen organisiert wurden.
Die Lösung: Verwenden von TFS und Tools von Drittanbietern
Daher benötigen wir ein Versionierungssystem für Microservice-Architekturprojekte, um Testumgebungen und Releases zu organisieren.
Als erste Daten haben wir:
- Orchestrierung - Wir verwenden Docker-Schwarm hauptsächlich, um die Verwendung anderer Tools von Drittanbietern zu reduzieren. Gleichzeitig gibt es Konverter zum Konvertieren von Konfigurationen - zum Beispiel das Dienstprogramm Kompose , mit dem Sie bei Bedarf Kubernetes verwenden können.
- Build Agents - VM basierend auf Linux-Servern.
- Quell-Repository - TFS-basiertes Git.
- Bildspeicherung - Docker-Registrierung auf VM.
Auf die Frage nach dem Namen der Builds
- Es ist logisch, vorhandene Namensstandards zu verwenden, z. B. die Semantic Versioning Specification .
- Wir folgen diesem Namen, wenn wir den Erstellungsprozess der Release-Version manuell starten, da Sie sonst nicht automatisch den richtigen Namen erhalten können (es sei denn, Sie geben ihn manuell in den Code ein, was wiederum wenig mit der CI-Ideologie zu tun hat).
- Im CI-Modus zum "Debuggen" von Softwareversionen verwenden wir die folgenden Namen für verschiedene Projekte:
- Integrierte TFS-Erweiterungen
- Nummerierung basierend auf dem aktuellen Datum und der Build-Nummer an diesem Tag;
- Die Nummer des Commits, mit dem der Build gestartet wurde.
Eine bestimmte Lösung kann beispielsweise anhand eines Beispiels des in Javascript erstellten
Calculator- Dienstes und mehrerer öffentlich verfügbarer Projekte angezeigt werden.
Entscheidungsalgorithmus
1. Erstellen Sie in TFS2018 ein Projekt namens SibEDGE Semver und importieren Sie das Repository in das lokale Repository
Abbildung 1 - SibEDGE Semver-Projekt im Repository bei TFS 20182. Erstellen Sie eine Dockerfile-Datei mit der Beschreibung der Assembly node.js für unsere Anforderungen (
Link ).
FROM node:7 WORKDIR /usr/src/app COPY package.json app.js LICENSE /usr/src/app/ COPY lib /usr/src/app/lib/ LABEL license MIT COPY tests tests ENV NODE_ENV dev RUN npm config set strict-ssl false RUN npm update && \ npm install -g mocha CMD ["mocha", "tests/test.js", "--reporter", "spec"]
Skript 1 - Docker-Datei zum Erstellen eines Builds
3. Erstellen Sie auf dem Prüfstand (mit installiertem Docker), auf dem wir unsere Umgebung bereitstellen möchten, einen Schwarmcluster. In unserem Fall besteht es aus einem Server.
$ docker swarm init
4. Erstellen Sie eine yml-Datei mit einer Beschreibung der Microservices für unsere Bedürfnisse (
Link ).
Beachten Sie, dass
vm-docker-registry.development.com:5000
das interne Repository für dieses Projekt ist, das wir im Voraus vorbereitet haben. Damit der Teststand dieses Repository verwenden kann, muss ein SSL-Zertifikat auf dem Stand im Ordner /etc/docker/certs.d/ <Repository-Name> /ca.crt registriert werden
version: '3.6' services: #--- # Portainer for manage Docker #--- portainer: image: portainer/portainer:1.15.3 command: --templates http://templates/templates.json -d /data -H unix:///var/run/docker.sock networks: - semver-network ports: - 9000:9000 volumes: - /var/run/docker.sock:/var/run/docker.sock #--- #----Service Calculator Test# #--- semver-calc: image: vm-docker-registry.development.com:5000/calculator:latest networks: - semver-network #--- #----Pminder - Nginx# #--- nginx: image: nginx:1.9.6 depends_on: - mysql ports: - "8888:80" - "6443:443" networks: - semver-network # #----------------------------- # START NoSQL - Redis. #--- redis: image: redis:4.0 networks: - semver-network ports: - "8379:6379" # # END NoSQL - Redis. #--- #----Pminder - DB# #--- mysql: image: mysql:5.7 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: 'ODdsX0xcN5A9a6q' MYSQL_DATABASE: 'semver' MYSQL_USER: 'user' MYSQL_PASSWORD: 'uXcgTQS8XUm1RzR' networks: - semver-network #--- #----PhpMyAdmin # #--- phpmyadmin: image: phpmyadmin/phpmyadmin depends_on: - mysql environment: PMA_HOST: 'mysql' PMA_USER: 'user' PMA_PASSWORD: 'uXcgTQS8XUm1RzR' ports: - "8500:80" - "8600:9000" networks: - semver-network #--- networks: semver-network:
Skript 2 ist der Inhalt der Datei semver.yml, bei der es sich um die Docker-Compose-Projektdatei handelt.
5. Erstellen Sie eine Build-Beschreibung in TFS2018 (Build-Definition).
6. Die erste Aktion unseres Skripts besteht darin, das Docker-Container-Image zu erstellen:
Abbildung 2 - Erstellen eines Images für unseren Build in TFS 20187. Senden Sie das auf dem Buildcomputer erstellte Docker-Container-Image an das interne Repository für dieses Projekt:
Abbildung 3 - Speichern des Docker-Images für unsere Assembly im TFS 2018-Repository8. Ändern Sie für die gesamte Umgebung auf dem Prüfstand in der Microservices-Beschreibungsdatei den Bildnamen in einen neuen:
Abbildung 4 - Ersetzen des Image-Namens im Build-Skript für unser Build in TFS 20189. Kopieren Sie auf dem Prüfstand das erstellte Docker-Container-Image aus dem internen Repository und aktualisieren Sie den Dienst in Docker-Schwarm:
Abbildung 5 - Bereitstellen des Docker-Containers mit dem Build-Skript für unseren Build aus dem Image in TFS 2018Wenn wir das TFS-Repository verlassen, haben wir daher eine yml-Datei mit Release-Versionen von Docker-Images, die wiederum einen Release-Namen für das gesamte Projekt hat.
10. Wir gehen zum Prüfstand und überprüfen den Betrieb der Dienste und stellen sicher, dass der Rechnerdienst aktualisiert wurde und die neue Version der Baugruppe verwendet.
$ docker service ls
Abbildung 6 - Aktualisieren des Rechnerservices und Überprüfen der aktuellen Version auf unserem PrüfstandDaher haben wir in unserem Docker-Registrierungsbildspeicher eine Reihe von Bildern verschiedener Versionen von Mikrodiensten (in diesem speziellen Fall wird die Version von nur einem Mikrodienst geändert). Durch Starten eines separaten Bereitstellungsprozesses (über ein Skript, das die yml-Beschreibungsdatei ändert) können Sie jederzeit die zum Testen erforderliche Umgebung auf einem Prüfstand abrufen und diese Konfiguration an die QS-Abteilung übertragen. Nach dem Testen (Regression, Laden usw.) erhalten wir die Information, dass der Microservice einer bestimmten Version auf einem Prüfstand mit den Release-Versionen anderer Microservices dieser und jener Versionen stabil funktioniert, und die endgültige Entscheidung darüber, was aktualisiert werden kann oder nicht, ist bereits getroffen Release Stand auf die neue Version.
Zusammenfassung - was Sie am Ausgang bekommen haben
Dank der Implementierung der Versionierung in Projekten mit Microservice-Architektur wurde folgendes Ergebnis erzielt:
- Das Chaos in den Versionen hat abgenommen.
- Die Geschwindigkeit der Bereitstellung einer neuen Umgebung in Projekten hat zugenommen.
- Die Qualität der Baugruppen hat sich verbessert und die Fehlerquote hat abgenommen.
- erhöhte Transparenz der Entwicklung für Projektmanager und Kunden;
- Die Interaktion zwischen den Abteilungen hat sich verbessert.
- Es gibt neue Richtungen in der Arbeit von DevOps.
PS Vielen Dank an meine Kollegin Kirill B., die mir beim Schreiben dieses Artikels geholfen hat.