Die Einführung einer neuen Projektversion in die Produktion erfordert eine sorgfältige Balance zwischen der Geschwindigkeit des Deployments und der Zuverlässigkeit der Lösung. Bei Slack wird Wert auf schnelle Iterationen, kurze Feedbackzyklen und eine zügige Reaktion auf Benutzeranfragen gelegt. Darüber hinaus stehen Hunderten von Programmierern zur Verfügung, die nach maximaler Produktivität streben.
Die Autoren des Materials, dessen Übersetzung wir heute veröffentlichen, betonen, dass ein Unternehmen, das solche Werte verfolgt und gleichzeitig wächst, ständig sein Deployment-System verbessern sollte. Es ist wichtig, in die Transparenz und Zuverlässigkeit der Arbeitsprozesse zu investieren, damit diese den Anforderungen des Projekts gerecht werden. Hier wird über die Arbeitsprozesse gesprochen, die in Slack entstanden sind, sowie über einige Lösungen, die das Unternehmen zur aktuellen Deployment-Systematik geführt haben.
Wie die Deployment-Prozesse heute funktionieren
Jede PR (Pull Request) in Slack muss unbedingt einer Code-Überprüfung unterzogen werden und alle Tests erfolgreich bestehen. Erst nachdem diese Bedingungen erfüllt sind, kann der Entwickler seinen Code mit dem Master-Branch des Projekts zusammenführen. Die Bereitstellung des Codes erfolgt jedoch nur während der Arbeitszeiten in Nordamerikanischer Zeitzone. Dadurch sind wir dank unserer Mitarbeiter vor Ort vollständig bereit, unerwartete Probleme zu lösen.
Jeden Tag führen wir etwa 12 geplante Bereitstellungen durch. Während jeder Bereitstellung ist der für die Bereitstellung verantwortliche Entwickler für die Einführung des neuen Builds in die Produktion zuständig. Dies ist ein mehrstufiger Prozess, der eine reibungslose Einführung des Builds in den Live-Betrieb gewährleistet. Mit diesem Ansatz können wir Fehler erkennen, bevor sie alle unsere Nutzer beeinträchtigen. Sollte es zu vielen Fehlern kommen, kann die Bereitstellung des Builds zurückgesetzt werden. Wird hingegen ein spezifisches Problem nach der Veröffentlichung entdeckt, lässt sich dafür leicht ein Hotfix ausbringen.

Die Schnittstelle des Checkpoint-Systems, die in Slack zur Bereitstellung von Projekten verwendet wird
Der Prozess der Bereitstellung eines neuen Releases in der Produktion kann als bestehend aus vier Schritten dargestellt werden.
▍1. Erstellung eines Release-Branches
Jedes Release beginnt mit einem neuen Release-Branch zu einem bestimmten Zeitpunkt in unserer Git-Historie. Dies ermöglicht es, dem Release Tags zuzuweisen und schafft einen Bereich, in den schnelle Korrekturen für Fehler eingefügt werden können, die während der Vorbereitung des Releases für die Produktion entdeckt wurden.
▍2. Bereitstellung in der Zwischenumgebung
Der nächste Schritt besteht darin, das Build auf den Staging-Servern bereitzustellen und einen automatischen Test auf die allgemeine Funktionsfähigkeit des Projekts (Smoke-Test) durchzuführen. Die Zwischenumgebung ist eine Produktionsumgebung, in die kein externer Traffic eindringt. In dieser Umgebung führen wir zusätzliche manuelle Tests durch. Dies gibt uns zusätzliche Sicherheit, dass das angepasste Projekt korrekt funktioniert. Automatisierte Tests allein reichen nicht aus, um ein solches Vertrauen zu gewinnen.
▍3. Bereitstellung in Dogfood- und Canary-Umgebungen
Die Bereitstellung in der Produktion beginnt mit der dogfood-Umgebung, die aus einer Reihe von Hosts besteht, die unsere internen Arbeitsbereiche in Slack unterstützen. Da wir starke Slack-Nutzer sind, hat dieser Ansatz geholfen, viele Fehler in den frühen Phasen der Bereitstellung zu erkennen. Sobald wir unsergestellt haben, dass die grundlegenden Funktionalitäten des Systems nicht beeinträchtigt sind, erfolgt die Bereitstellung des Builds in der Canary-Umgebung. Diese besteht aus Systemen, die etwa 2% des Produktionsverkehrs erhalten.
▍4. Schrittweise Einführung in der Produktion
Wenn die Überwachungskennzahlen der neuen Version stabil sind und wir nach der Bereitstellung des Projekts in der Canary-Umgebung keine Beschwerden erhalten haben, setzen wir die schrittweise Umstellung der Produktionsserver auf die neue Version fort. Der Bereitstellungsprozess ist in die folgenden Phasen unterteilt: 10%, 25%, 50%, 75% und 100%. So können wir den Produktionsverkehr schrittweise auf die neue Version des Systems übertragen. Dies gibt uns Zeit, die Situation zu beobachten, falls Anomalien auftreten.
▍Was tun, wenn während der Bereitstellung etwas schiefgeht?
Änderungen im Code sind immer mit Risiken verbunden. Doch wir meistern dies dank unserer gut geschulten Deployment-Leiter, die den Prozess der Bereitstellung neuer Releases in die Produktion leiten, die Überwachungskennzahlen im Blick behalten und die Arbeit der Entwickler koordinieren, die den Code erstellen.
Falls etwas tatsächlich schiefgeht, versuchen wir, das Problem so früh wie möglich zu erkennen. Wir analysieren das Problem, identifizieren den PR, der die Fehler verursacht, setzen ihn zurück, untersuchen ihn gründlich und erstellen ein neues Build. Manchmal bleibt das Problem jedoch bis zur Produktion unentdeckt. In einem solchen Fall ist es am wichtigsten, den Dienst wiederherzustellen. Daher setzen wir, bevor wir mit der Problemuntersuchung beginnen, sofort zur letzten funktionierenden Version zurück.
Die Grundbausteine des Deployment-Systems
Betrachten wir die Technologien, die unserer Projektbereitstellung zugrunde liegen.
▍Schnelle Deployments
Der oben beschriebene Arbeitsprozess mag im Rückblick als vollkommen offensichtlich erscheinen. Aber unser Deployment-System hat sich nicht von Anfang an so entwickelt.
Als das Unternehmen noch viel kleiner war, konnte unsere gesamte Anwendung auf 10 Amazon EC2-Instanzen laufen. Die Bereitstellung eines Projekts in einer solchen Situation bedeutete, rsync für eine schnelle Synchronisation aller Server zu verwenden. Früher trennte nur ein Schritt den neuen Code von der Produktion, der durch eine Zwischenumgebung dargestellt wurde. Builds wurden in dieser Umgebung erstellt und getestet, bevor sie direkt in die Produktion gingen. Es war sehr einfach, sich in einem solchen System zurechtzufinden, da es jedem Programmierer zu jedem Zeitpunkt ermöglichte, seinen geschriebenen Code bereitzustellen.
Doch mit wachsenden Kundenzahlen stieg auch der Umfang der Infrastruktur, die für den Betrieb des Projekts erforderlich war. Bald, angesichts des ständigen Systemwachstums, konnte unser Bereitstellungsmodell, das auf dem Senden neuen Codes an die Server basierte, nicht mehr seinen Zweck erfüllen. Jedes Hinzufügen eines neuen Servers bedeutete eine Erhöhung der Zeit, die für die Bereitstellung benötigt wurde. Selbst Strategien, die auf der parallelen Anwendung von rsync basierten, haben gewisse Einschränkungen.
Schließlich haben wir das Problem gelöst, indem wir auf ein vollständig paralleles Bereitstellungssystem umgestiegen sind, das anders strukturiert ist als das alte System. Statt den Code über ein Synchronisationsskript auf Server zu senden, laden nun die Server selbstständig die neue Version herunter, nachdem sie durch das Monitoring der Änderung des Consul-Schlüssels darüber informiert wurden. Die Server laden den Code parallel herunter. Dies ermöglichte es uns, eine hohe Bereitstellungsgeschwindigkeit auch in Zeiten des ständigen Systemwachstums aufrechtzuerhalten.

1. Produktionsserver überwachen den Consul-Schlüssel. 2. Der Schlüssel ändert sich, was den Servern signalisiert, dass sie mit dem Herunterladen des neuen Codes beginnen müssen. 3. Die Server laden die Tarball-Dateien mit dem Anwendungscode herunter.
▍Atomare Bereitstellungen
Eine weitere Lösung, die uns geholfen hat, zu einem mehrstufigen Bereitstellungssystem zu gelangen, war die atomare Bereitstellung.
Vor der Einführung atomarer Bereitstellungen konnte jede Bereitstellung eine Vielzahl von Fehlermeldungen verursachen. Der Grund dafür war, dass der Prozess des Kopierens neuer Dateien auf Produktionsserver nicht atomar war. Dies führte zu einer kurzen Zeitspanne, in der der Code, der neue Funktionen aufrief, zugänglich war, bevor die Funktionen selbst verfügbar waren. Wenn solcher Code ausgeführt wurde, kam es zu internen Fehlern. Dies äußerte sich in fehlgeschlagenen API-Anfragen und „kaputten“ Webseiten.
Das Team, das sich mit diesem Problem beschäftigte, löste es durch die Einführung des Konzepts von „heißen“ (hot) und „kalten“ (cold) Verzeichnissen. Der Code im „heißen“ Verzeichnis ist für die Verarbeitung des Produktionsverkehrs verantwortlich. In den „kalten“ Verzeichnissen wird der Code während des Systembetriebs lediglich für die Nutzung vorbereitet. Bei der Bereitstellung wird der neue Code in ein ungenutztes „kaltes“ Verzeichnis kopiert. Dann, wenn auf dem Server keine aktiven Prozesse mehr laufen, erfolgt ein sofortiger Verzeichniswechsel.

1. Entpacken des Anwendungscodes in ein 'kaltes' Verzeichnis. 2. Umschalten des Systems auf das 'kalte' Verzeichnis, das zu einem 'heißen' wird (atomare Operation)
Zusammenfassung: Verschiebung des Fokus auf Zuverlässigkeit
Im Jahr 2018 erreichte das Projekt ein solches Ausmaß, dass eine sehr schnelle Bereitstellung der Stabilität des Produkts schadete. Wir hatten ein äußerst fortschrittliches Bereitstellungssystem, in das wir viel Mühe und Zeit investiert hatten. Wir mussten nur die Prozesse der Bereitstellungsorganisation neu strukturieren und verbessern. Wir sind zu einem ausreichend großen Unternehmen geworden, dessen Entwicklungen weltweit für die Organisation einer unterbrechungsfreien Kommunikation und zur Lösung wichtiger Aufgaben verwendet wurden. Daher stand die Zuverlässigkeit im Mittelpunkt unserer Aufmerksamkeit.
Wir mussten den Prozess für die Bereitstellung neuer Slack-Versionen sicherer gestalten. Diese Notwendigkeit führte uns zur Verbesserung unseres Bereitstellungssystems. Wie bereits oben erwähnt, haben wir dieses verbesserte System diskutiert. Innerhalb des Systems setzen wir weiterhin auf Technologien für schnelle und atomare Bereitstellungen. Was sich verändert hat, ist, wie die Bereitstellung selbst erfolgt. Unser neues System ist darauf ausgelegt, die Bereitstellung neuer Codes schrittweise auf verschiedenen Ebenen und in unterschiedlichen Umgebungen durchzuführen. Jetzt verwenden wir fortschrittlichere Tools und Monitoring-Mittel als zuvor. Dies ermöglicht es uns, Fehler frühzeitig zu erkennen und zu beheben, bevor sie die Endnutzer erreichen.
Doch wir haben nicht vor, uns auf unseren Erfolgen auszuruhen. Wir verbessern dieses System ständig, indem wir fortschrittlichere Support-Tools und Automatisierungstechniken einsetzen.
Sehr geehrte Leser! Wie funktioniert der Prozess der Bereitstellung neuer Projekt-Versionen in Ihrem Arbeitsumfeld?
Quelle: habr.com
