Patche mich, wenn du kannst: wie wir die Produktion debuggen. Teil 1

UPD: Der zweite Teil des Artikels ist fertig .

Hallo Habr! Ich heiße Alexander Izmailov. Bei Badoo leite ich ein Team von Release-Ingenieuren. Ich weiß, dass Sie in vielen Unternehmen Codeänderungen an eine speziell geschulte Person senden können, die sie sich ansieht und dort hinzufügt, wo sie sollten (zum Beispiel passiert genau dies mit Git-Code). Und ich möchte darüber sprechen, wie wir diesen Prozess mit uns automatisiert haben.

Meine Geschichte wird aus zwei Teilen bestehen. In diesem Teil werde ich darüber sprechen, was wir mit dem neuen System erreichen wollten, wie es in seiner ersten Version aussah und warum wir es am Ende wiederholen mussten. Im zweiten Teil werden wir über den Prozess der Neugestaltung des Systems und über die unerwarteten Boni sprechen, die es uns gebracht hat.


Bild: Quelle

Es war einmal in unserem Unternehmen, dass jeder seine Änderungen direkt an der Hauptniederlassung vornehmen und sie mit eigenen Händen auslegen konnte. Zu diesem Zweck haben wir ein spezielles MSCP-Dienstprogramm geschrieben, das sehr primitiv funktioniert: Es hat die Änderungen von einem Computer auf einen anderen kopiert und die erforderlichen Rechte festgelegt.

Im Laufe der Zeit wuchs das Unternehmen - und wir mussten über die Automatisierung von Prozessen nachdenken, einschließlich des Prozesses, kleine Änderungen vorzunehmen. So kamen wir auf die Idee, ein Patch-System zu erstellen. Zunächst wollten wir, dass jeder Entwickler seine Änderungen an Git senden und auf Servern auslegen kann. Unsererseits forderten wir, dass ein anderer Entwickler die Änderungen überprüft und sie mit der Aufgabe unseres Bug-Tracking-Systems verknüpft (wir verwenden Jira).

Patch Collector 6000
Ich muss sagen, dass diese Anforderungen nicht alle Entwickler angesprochen haben. Es schien uns, dass es keine Sache ist, ein paar Minuten für die Erstellung einer Aufgabe aufzuwenden, aber für uns würde dies eine bewusstere Verwendung des Systems bedeuten. Aber die Entwickler begannen sich zu widersetzen und argumentierten, dass das Auslegen der Änderungen um ein Vielfaches weniger Zeit in Anspruch nimmt als das Erstellen eines neuen Tickets. Infolgedessen haben wir immer noch "universelle" Aufgaben, an die Hunderte von Patches angehängt sind.

Darüber hinaus wurde das System mit dem Ziel konzipiert, dringende Probleme zu beheben, und es kann schwierig sein, um drei Uhr morgens einen Prüfer für einen Patch zu finden.

Was brauchen wir


Ja, nur ein Licht im Fenster ... Unser Problem könnte bedingt in zwei Teile unterteilt werden: Wir brauchten eine Möglichkeit, Änderungen am Repository zu akzeptieren und diese Änderungen zu planen.

Wir haben die erste Frage schnell genug entschieden: Wir haben ein Formular erstellt, an das wir unsere Änderungen anhängen und die Details (Prüfer und Aufgabe) angeben müssen.


Auf der zweiten Seite können Sie die Änderungen sehen, ablehnen oder akzeptieren.



Nach der Bestätigung fielen die Änderungen in den Master.

Zweite Frage: Wie können diese Änderungen schnell an Server übermittelt werden? Heutzutage verwenden viele die kontinuierliche Integration, und es könnte die Arbeit gut machen, wenn unsere „ehrlichen“ Builds und Layouts nicht so viel Zeit in Anspruch nehmen würden.

Faire Versammlung


Unsere Montage war schon immer ziemlich kompliziert. Das allgemeine Prinzip war folgendes: In einem separaten Verzeichnis haben wir die Dateien so angeordnet, wie sie sich auf den Zielservern befinden würden. Dann haben wir diesen Status in einem Snapshot (Snapshot des Dateisystems) gespeichert und angelegt.

Wir haben den PHP-Code in das Verzeichnis gestellt, das wir unverändert aus dem Repository entnommen haben, und die generierten Dateien (z. B. Vorlagen und Übersetzungen) hinzugefügt. Wir haben die Statik separat angelegt. Dies ist ein ziemlich komplizierter Prozess, und Sie können ihm einen ganzen Artikel widmen. Als Ergebnis hatten wir eine Versionsübersicht, um Dateilinks für Benutzer zu generieren, die zusammen mit dem Hauptcode abgereist sind.

Als nächstes musste der Status des Verzeichnisses irgendwo gespeichert werden. Zu diesem Zweck haben wir ein Blockgerät verwendet , das wir als Schleife bezeichnet haben. Das gesamte Verzeichnis wurde auf ein leeres Gerät kopiert, das dann archiviert und an separate „Hauptserver“ geliefert wurde. Von diesen Servern haben wir im Verlauf des Layouts Archive genommen. Jedes Archiv hatte eine Größe von 200 MB, und beim Auspacken wogen die Loops 1 GB. Wir haben ungefähr fünf Minuten gebraucht, um ohne statische Aufladung zu bauen.

Faires Layout


Zuerst mussten wir das Archiv an die Zielserver liefern. Wir haben Tausende von ihnen, daher war die Lieferfrage für uns immer ein großes Problem: Wir haben mehrere Plattformen (Rechenzentren) und auf den „dicksten“ tausend Servern einen Code. Bei dem Versuch, eine bessere Leistung (minimale Zeit und Ressourcen) zu erzielen, haben wir verschiedene Methoden ausprobiert: von einem einfachen SCP bis zu Torrents. Am Ende haben wir uns für UFTP entschieden. Die Methode war schnell (bei gutem Wetter - eine Minute), aber leider nicht problemlos. In regelmäßigen Abständen brach etwas zusammen und wir mussten zu den Admins und Networkern laufen.

Nachdem sich das Archiv (irgendwie) auf den Servern befunden hat, muss es entpackt werden, was ebenfalls nicht kostenlos ist. Dieses Verfahren scheint besonders teuer zu sein, wenn Sie sich daran erinnern, dass es tausende Male ausgeführt wird, wenn auch parallel auf verschiedenen Maschinen.

Keine Montage


Das ehrliche Posten von Änderungen nahm also viel Zeit in Anspruch, und die Liefergeschwindigkeit war für das Patch-System sehr wichtig, da davon ausgegangen wurde, dass sie verwendet werden würden, wenn etwas nicht mehr funktioniert. Daher kehrten wir zu der Idee zurück, MSCP zu verwenden: schnell und einfach zu implementieren. Nachdem die Änderungen im Assistenten angezeigt wurden, konnten die geänderten Dateien auf einer separaten Seite nacheinander zerlegt werden.



Es lebt


Das System funktioniert. Trotz einiger Unzufriedenheit mit den kleinen Dingen konnten die Entwickler ihre Arbeit erledigen, und dafür brauchten sie keinen Zugriff auf den Master oder auf die Server.

Aber natürlich hatten wir bei dieser Layoutmethode Probleme. Einige waren vorhersehbar, andere haben wir sogar irgendwie entschieden. Die meisten davon betrafen die parallele Bearbeitung von Dateien.

Ein Patch für mehrere Dateien


Ein Beispiel für ein vorhersehbares Problem. Neue Dateien wurden der Reihe nach angelegt. Was tun, wenn Sie mehrere Dateien ändern müssen und die Änderungen damit zusammenhängen? Zum Beispiel möchte ich eine neue Methode in eine Datei einfügen und sie sofort in anderen verwenden. Solange es keinen Loopback mit Methoden gibt (siehe gegenseitige Rekursion ), reicht es aus, sich die richtige Reihenfolge des Dateilayouts zu merken.

Ehrliche Entscheidung
Um das Problem zu lösen, mussten wir mehrere Dateien atomar ersetzen. Bei einer einzelnen Datei ist die Lösung bekannt: Sie müssen die Dateioperation umbenennen. Angenommen, wir haben eine Datei F und müssen deren Inhalt ersetzen. Erstellen Sie dazu eine TMP-Datei, schreiben Sie die erforderlichen Informationen hinein und benennen Sie TMP F um.

Lassen Sie uns die Aufgabe komplizieren. Angenommen, wir haben ein Verzeichnis D und müssen dessen Inhalt ersetzen. Der Umbenennungsvorgang hilft uns nicht, da er ein nicht leeres Verzeichnis nicht ersetzen kann. Es gibt jedoch eine Problemumgehung: Sie können das D-Verzeichnis vorab durch einen sogenannten symbolischen Link (Symlink) ersetzen. Dann liegt der Inhalt selbst an einer anderen Stelle, beispielsweise im Verzeichnis D_1, und D ist eine Verknüpfung zu D_1. In dem Moment, in dem ein Austausch erforderlich ist, wird der neue Inhalt in das Verzeichnis D_2 geschrieben, zu dem ein neuer TMP-Link erstellt wird. Jetzt funktioniert das Umbenennen von TMP D, da dieser Vorgang auf Links angewendet werden kann.

Diese Lösung sieht angemessen aus: Sie können das gesamte Verzeichnis mit dem Code ändern, alte Dateien kopieren und neue darüber schreiben. Das Problem ist, dass das Kopieren des gesamten Codes lang und teuer ist. Sie können nur das Unterverzeichnis ersetzen, in dem sich die Dateien geändert haben, aber dann müssen alle Unterverzeichnisse mit dem Code Links sein, da wir das gefüllte Verzeichnis während des Layoutprozesses nicht durch irgendetwas ersetzen können. Diese Lösung sieht nicht nur sehr kompliziert aus - Sie müssen auch einige Einschränkungen hinzufügen, damit die beiden Prozesse nicht gleichzeitig dasselbe Verzeichnis oder Verzeichnis und seine Unterverzeichnisse ändern können.

Infolgedessen konnten wir keine technische Lösung finden, aber wir haben herausgefunden, wie wir das Leben ein wenig vereinfachen können: Wir haben das Layout mehrerer Dateien mit einer Aktion in der Benutzeroberfläche erstellt. Der Entwickler hat das Layout der Dateien festgelegt und vom System bereitgestellt.

Mehrere Patches pro Datei


Es ist schwieriger, wenn es eine Datei gibt und es mehrere Entwickler gibt, die sie ändern möchten. Wir haben den ersten Patch angewendet, ihn aber nicht zerlegt. Zu diesem Zeitpunkt kommt der zweite Patch an und wird aufgefordert, ihn zu zerlegen. Was zu tun ist? Noch interessanter, wenn der zweite Patch angewendet wird und wir in diesem Moment gebeten werden, den ersten zu zerlegen.

Wahrscheinlich müssen wir klarstellen, dass wir immer nur die neueste Version des Assistenten bereitgestellt haben. Andernfalls können andere Probleme auftreten. Legen Sie beispielsweise die alte Version über die neue.

Wir haben keine wirklich gute Lösung für dieses Problem gefunden. Wir haben den Entwicklern den Unterschied zwischen dem, was sie angelegt haben, und dem, was sich zu einem bestimmten Zeitpunkt auf den Maschinen befindet, gezeigt, aber dies hat nicht immer funktioniert. Zum Beispiel könnte es viele Änderungen geben, und der Entwickler könnte es eilig haben oder einfach nur faul sein (alles kann passieren).

Viele Patches, und jeder ändert die gleichen Dateien


Dies ist die schlechteste Option, auf die Sie nicht einmal eingehen möchten. Wenn die Änderungen mehrerer Entwickler mehrere derselben Dateien betrafen, konnte unser Patch-System nicht besonders helfen - es blieb auf die Aufmerksamkeit der Entwickler und ihre Fähigkeit, miteinander zu kommunizieren, angewiesen. Theoretisch ist es jedoch durchaus möglich, "Fisch" zu erhalten, wenn in einer beliebigen Reihenfolge des Layouts irgendwann auf dem Server teilweise fehlerhafter Code vorhanden ist.


Bild: Quelle

Eisenprobleme


Ein weiteres Problem trat auf, als aus irgendeinem Grund einer der Server nicht mehr verfügbar war. Wir hatten einen Mechanismus zum Ausschließen solcher Server aus dem Layout, der recht gut funktionierte. Schwierigkeiten traten nach ihrer Rückkehr zum Dienst auf. Tatsache ist, dass die Versionen von Konfigurationen und Code auf funktionierenden Servern bei uns überprüft werden (es gibt eine ganze Überwachungsabteilung!) Und wir stellen sicher, dass alle Versionen auf dem neuesten Stand sind, wenn der Server wieder in Betrieb ist. Wir hatten jedoch keine Versionierung für Patches - wir haben nur neue Dateien in den aktuellen Code kopiert.

Wir haben keine genaue Methode zur Versionierung der zerlegten Patches gefunden, aber wir haben versucht, das Problem durch Problemumgehungen zu lösen. Beispiel: rsync von einem benachbarten Computer am Ende des Layoutprozesses. Aber irgendwie konnten wir es irgendwie nicht überprüfen.

Wir haben verschiedene Lösungen für dieses Problem durchgearbeitet, z. B. wollten wir Patches auch auf den "Hauptservern" anwenden (es ist wichtig zu bedenken, dass wir die gepackte Version bereitstellen, dh wir müssen den Patch anwenden und die Version zurückpacken), aber die Implementierung war ziemlich schwierig.

Ein Löffel Honig


Neben den Problemen gab es aber auch positive Aspekte.

Erstens haben die Entwickler schnell herausgefunden, dass Sie mithilfe des Patch-Systems nicht nur Probleme beheben, sondern manchmal auch neue Funktionen hochladen können, beispielsweise wenn Sie diese dringend benötigen. Wie in jedem Unternehmen haben wir höhere Gewalt. Wenn wir jedoch früher einen außergewöhnlichen Build erstellen mussten, von dem Tester und Release-Ingenieure abgelenkt waren, konnte der Entwickler jetzt einige Änderungen selbst zerlegen.

Zweitens wurde eine spezielle Person mit Rechten nicht mehr benötigt, um etwas zu reparieren. Jeder Entwickler selbst könnte seine Änderungen veröffentlichen. Dies ist jedoch noch nicht alles: Builds sind im Allgemeinen einfacher geworden. Jetzt wurden die Probleme in kritische und solche unterteilt, die mithilfe von Patches behoben werden können. Dies ermöglichte es, weniger häufig zurückzusetzen und schneller zu entscheiden, ob wir erfolgreich waren.

Einfach ausgedrückt, wir mochten das System und gewannen an Popularität. Wir haben weiter versucht, es zu verbessern, aber mit den beschriebenen Problemen mussten wir noch ein paar Jahre leben. Und wie wir sie entschieden haben, wie das System jetzt funktioniert und wie wir die Neujahrsfeiertage während des Aktualisierungsprozesses fast beendet haben, werde ich im zweiten Teil des Artikels erzählen.

Source: https://habr.com/ru/post/de413503/


All Articles