Hinweis.: Anfang August gab Red Hat öffentlich bekannt, dass die Probleme mit der Verfügbarkeit, die in den vergangenen Monaten bei den Nutzern ihres Dienstes aufgetreten waren, behoben wurden. (dahinter steht ein Container-Image-Registry, das zusammen mit dem Kauf von CoreOS in den Besitz des Unternehmens überging). Unabhängig von Ihrem Interesse an diesem Dienst ist der Weg, den die SRE-Ingenieure des Unternehmens bei der Diagnose und Behebung der Ursachen für die Ausfälle gegangen sind, lehrreich.

Am 19. Mai, früh am Morgen (nach Summer Eastern Daylight Time, EDT), fiel der Dienst quay.io aus. Der Ausfall betraf sowohl die Nutzer von quay.io als auch Open-Source-Projekte, die quay.io als Plattform zum Bauen und Verbreiten von Software nutzten. Red Hat schätzt das Vertrauen beider Gruppen.
Das SRE-Team von Ingenieuren setzte sich sofort an die Arbeit und bemühte sich, den Dienst Quay so schnell wie möglich zu stabilisieren. Während sie jedoch daran arbeiteten, hatten die Kunden die Möglichkeit verloren, neue Images zu pushen, und konnten nur sporadisch vorhandene Images pullen. Aus unbekannten Gründen wurde die Datenbank von quay.io nach der Skalierung des Dienstes auf volle Kapazität blockiert.
«Was hat sich geändert?» ist die erste Frage, die in solchen Fällen gestellt wird. Wir haben festgestellt, dass der OpenShift Dedicated-Cluster, auf dem quay.io läuft, kurz vor dem Problem mit dem Update auf Version 4.3.19 begonnen hat. Da quay.io auf Red Hat OpenShift Dedicated (OSD) basiert, waren regelmäßige Updates eine alltägliche Operation und führten nie zu Problemen. Zudem haben wir in den letzten sechs Monaten mehrfach die Quay-Cluster aktualisiert, ohne dass es zu Serviceunterbrechungen kam.
Während wir versuchten, den Dienst wiederherzustellen, begannen andere Ingenieure mit der Vorbereitung eines neuen OSD-Clusters mit einer vorherigen Softwareversion, um bei Bedarf alles darauf zu deployen.
Ursachenanalyse
Das Hauptsymptom des Ausfalls war eine Flut von Zehntausenden von Verbindungen zur Datenbank, wodurch die MySQL-Instanz faktisch nicht mehr funktionsfähig war. Dies machte es schwierig, das Problem zu diagnostizieren. Wir haben eine Obergrenze für die maximale Anzahl von Verbindungen von Clients festgelegt, um dem SRE-Team zu helfen, das Problem einzuschätzen. Es wurde kein ungewöhnlicher Datenbankverkehr festgestellt: Tatsächlich waren die meisten Anfragen Leseanfragen, während nur wenige Schreibanfragen waren.
Wir haben auch versucht, ein Muster im Datenbankverkehr zu identifizieren, das diese Überlastung verursachen könnte. Allerdings ließ sich in den Logs kein Muster finden. In Erwartung der Fertigstellung des neuen Clusters mit OSD 4.3.18 setzten wir unsere Versuche fort, die Pods von quay.io zu starten. Jedes Mal, wenn das Cluster auf volle Kapazität ging, kam die Datenbank zum Stillstand. Das bedeutete, dass wir die RDS-Instanz neu starten mussten, zusätzlich zu allen Pods von quay.io.
Bis zum Abend hatten wir den Dienst im Nur-Lese-Modus stabilisiert und die meisten nicht wesentlichen Funktionen (zum Beispiel die Müllsammlung im Namensraum) deaktiviert, um die Last auf der Datenbank zu senken. Die Ausfälle hörten auf, aber die Ursache wurde nicht gefunden. Das neue OSD-Cluster war einsatzbereit, und wir haben den Dienst umgezogen, den Datenverkehr angeschlossen und die Überwachung fortgesetzt.
Quay.io funktionierte stabil auf dem neuen OSD-Cluster, also kehrten wir zu den Datenbanklogs zurück, konnten jedoch keine Korrelation entdecken, die die Blockierungen erklären würde. Die Ingenieure von OpenShift arbeiteten eng mit uns zusammen, um herauszufinden, ob Änderungen in Red Hat OpenShift 4.3.19 Probleme mit Quay verursachen könnten. Allerdings wurde nichts entdeckt, und es war nicht möglich, das Problem unter Laborbedingungen zu reproduzieren..
Zweiter Ausfall
Am 28. Mai, kurz vor Mittag EDT, fiel quay.io erneut mit demselben Symptom aus: die Datenbankfunktion wurde blockiert. Wiederum setzten wir alle Kräfte ein, um zu ermitteln, woran es lag. Zunächst musste der Dienst wiederhergestellt werden. Allerdings führten in diesem Fall ein Neustart von RDS und das Hochfahren der Pods von quay.io zu nichts: eine weitere Flut von Verbindungen überwältigte die Datenbank. Aber warum?
Quay ist in Python geschrieben, und jeder Pod arbeitet als ein einzelner monolithischer Container. In der Ausführungsumgebung des Containers werden gleichzeitig viele parallele Aufgaben ausgeführt. Wir verwenden die Bibliothek gevent eine gunicorn zur Verarbeitung von Webanfragen. Wenn eine Anfrage an Quay eingeht (über unsere eigene API oder die API von Docker), wird ihr ein gevent-Worker zugewiesen. Normalerweise sollte dieser Worker mit der Datenbank kommunizieren. Nach dem ersten Ausfall stellten wir fest, dass die gevent-Worker sich mit der Datenbank unter Verwendung der Standardkonfigurationen verbindet.
Angesichts der erheblichen Anzahl an Quay-Pods und Tausenden eingehender Anfragen pro Sekunde hätte eine hohe Anzahl von Datenbankverbindungen theoretisch die MySQL-Instanz überlasten können. Dank des Monitorings war bekannt, dass Quay im Durchschnitt 5.000 Anfragen pro Sekunde verarbeitet. Etwa so hoch war auch die Anzahl der Datenbankverbindungen. 5.000 Verbindungen lagen gut innerhalb der Kapazitäten unserer RDS-Instanz (was man von zig Tausenden nicht sagen kann). Aus irgendeinem Grund gab es unerwartete Spitzen bei der Anzahl der Verbindungen., jedoch beobachteten wir keine Korrelation mit den eingehenden Anfragen.
Diesmal haben wir uns entschieden, die Quelle des Problems zu finden und zu beheben, anstatt uns mit einem Neustart zufriedenzugeben. Im Quay-Code wurden Änderungen vorgenommen, um die Anzahl der Datenbankverbindungen für jeden Worker zu begrenzen. gevent. Diese Zahl wurde zu einem Parameter in der Konfiguration: Es ist nun möglich, ihn „on-the-fly“ zu ändern, ohne ein neues Container-Image zu erstellen. Um herauszufinden, wie viele Verbindungen tatsächlich verarbeitet werden können, wurden mehrere Tests in einer Staging-Umgebung durchgeführt, bei denen verschiedene Werte gesetzt wurden, um zu sehen, wie sich dies auf die Lasttestszenarien auswirken würde. Am Ende stellte sich heraus, dass Quay anfängt, 502-Fehler auszugeben, wenn die Anzahl der Verbindungen 10.000 überschreitet.
Wir haben diese neue Version sofort in der Produktion ausgerollt und begannen, die Verbindungsstatistiken zur Datenbank zu überwachen. Früher wurde die Datenbank nach ungefähr 20 Minuten blockiert. Nach 30 problemlosen Minuten hatten wir Hoffnung, und nach einer Stunde — Zuversicht. Wir haben den Schreibverkehr auf der Website wiederhergestellt und mit der Postmortem-Analyse begonnen.
Nachdem wir das Problem umgangen haben, haben wir seine wahren Ursachen nicht herausgefunden.Es wurde bestätigt, dass es nicht mit Änderungen in OpenShift 4.3.19 zusammenhing, da dasselbe auch bei Version 4.3.18 auftrat, die zuvor ohne Probleme mit Quay funktionierte.
Im Cluster verbarg sich offenbar noch etwas anderes.
Eine detaillierte Untersuchung
Quay.io hat sechs Jahre lang die Standardkonfiguration für die Verbindung zur Datenbank ohne irgendwelche Probleme genutzt. Was hat sich geändert? Es ist offensichtlich, dass der Traffic auf quay.io während dieser ganzen Zeit stetig gewachsen ist. In unserem Fall sah es so aus, als ob ein gewisser Grenzwert erreicht wurde, der einen Anstieg der Verbindungen ausgelöst hat. Wir haben weiterhin die Datenbankprotokolle nach dem zweiten Ausfall untersucht, konnten jedoch keine Muster oder offensichtlichen Zusammenhänge feststellen.
In der Zwischenzeit arbeitete das SRE-Team an Verbesserungen im Bereich der Sichtbarkeit von Anfragen bei Quay sowie der allgemeinen Gesundheit des Dienstes. Es wurden neue Metriken und Dashboards bereitgestellt, die zeigen, welche Teile von Quay bei den Kunden am meisten nachgefragt werden.
Quay.io funktionierte bis zum 9. Juni normal. Am Morgen (nach EDT) wurden wir erneut Zeugen eines erheblichen Anstiegs der Verbindungen zur Datenbank. Dieses Mal gab es keinen Ausfall., da die neue Einstellung ihre Anzahl einschränkte und eine Überschreitung der MySQL-Bandbreite verhinderte. Nach etwa einer halben Stunde berichteten viele Benutzer von langsamen Ladezeiten auf quay.io. Wir sammelten schnell alle verfügbaren Daten, indem wir die neu hinzugefügten Überwachungswerkzeuge verwendeten. Plötzlich trat ein Muster auf.
Kurz vor dem Anstieg der Verbindungsanzahl gab es eine Fülle von Anfragen an die App Registry API.. Die App Registry ist eine weniger bekannte Funktion von quay.io. Sie ermöglicht das Speichern von Elementen wie Helm-Charts und Containern mit umfangreichen Metadaten. Die meisten Benutzer von quay.io nutzen diese Funktion nicht, jedoch wird sie aktiv von Red Hat OpenShift verwendet. OperatorHub im Rahmen von OpenShift speichert alle Operatoren in der App Registry. Diese Operatoren bilden die Grundlage für das Ökosystem der Arbeitslasten von OpenShift und das Betriebskonzept (im Rahmen der „Second-Day“-Operationen), das sich an Partner orientiert.
Jeder OpenShift 4-Cluster verwendet Operatoren aus dem integrierten OperatorHub, um einen Katalog von verfügbaren Operatoren zur Installation zu veröffentlichen und Updates für bereits installierte Operatoren bereitzustellen. Mit der zunehmenden Beliebtheit von OpenShift 4 ist auch die Anzahl der darauf basierenden Cluster weltweit gestiegen. Jeder dieser Cluster lädt Inhalte von Operatoren herunter, um den integrierten OperatorHub zu starten, wobei die App-Registry innerhalb von quay.io als Backend dient. Auf der Suche nach der Ursache des Problems haben wir übersehen, dass mit dem allmählichen Anstieg der Beliebtheit von OpenShift auch die Belastung einer der selten genutzten Funktionen von quay.io zugenommen hat..
Wir haben eine Analyse des Traffics der App-Registry-Anfragen durchgeführt und einen Blick in den Code des Registrys geworfen. Sofort traten Mängel zutage, die dazu führten, dass die Datenbankanfragen suboptimal formuliert wurden. Bei geringer Last verursachten sie keine Probleme, jedoch wurden sie bei zunehmender Belastung zu einem Problem. Die App-Registry wies zwei problematische Endpunkte auf, die schlecht auf erhöhten Last reagierten: der erste lieferte eine Liste aller Pakete im Repository, der zweite gab alle Blobs für ein Paket zurück.
Beseitigung der Ursachen
In der gesamten nächsten Woche haben wir an der Optimierung des App Registrys und seiner Umgebung gearbeitet. Dabei wurden offensichtlich ineffiziente SQL-Abfragen überarbeitet, unnötige Kommandoaussprüche beseitigt, die bei jedem Abruf von Blobs ausgeführt wurden, und überall dort, wo es möglich war, Caching hinzugefügt. , Anschließend führten wir umfangreiche Leistungstests durch und verglichen die Geschwindigkeit des App Registrys vor und nach den Änderungen.
API-Anfragen, die zuvor bis zu einer halben Minute benötigten, werden jetzt in Millisekunden ausgeführt.In der nächsten Woche haben wir die Änderungen in der Produktion ausgerollt, und seitdem funktioniert quay.io stabil. Während dieser Zeit gab es mehrere plötzliche Verkehrsspitzen an der Endpoint des App Registrys, aber die vorgenommenen Verbesserungen haben Unterbrechungen in der Datenbankarbeit verhindert.
Was haben wir gelernt?
Es ist klar, dass jeder Dienst bestrebt ist, Ausfallzeiten zu vermeiden. In unserem Fall glauben wir, dass die jüngsten Ausfälle dazu beigetragen haben, quay.io zu verbessern. Wir haben einige wichtige Lektionen daraus gezogen, die wir gerne teilen möchten:
- Daten darüber, wer und wie Ihr Dienst genutzt wird, sind niemals überflüssig.. Da Quay "einfach funktionierte", hatten wir nie das Gefühl, Zeit mit der Optimierung des Verkehrs und der Lastensteuerung verbringen zu müssen. Dies führte zu einem falschen Gefühl der Sicherheit, dass der Service unbegrenzt skalierbar sei.
- Wenn der Service ausfällt, hat die Wiederherstellung der Funktionalität oberste Priorität.. Da Quay während des ersten Ausfalls weiterhin unter einer blockierten Datenbank litt, hatten unsere Standardverfahren nicht den gewünschten Effekt, und wir konnten den Service nicht wiederherstellen. Dies führte zu einer Situation, in der wir Zeit mit der Analyse und Datensammlung verbringen mussten, in der Hoffnung, die Ursache zu finden – anstatt unsere gesamte Energie auf die Wiederherstellung der Funktionalität zu richten.
- Bewerten Sie die Auswirkungen jeder Funktion des Services.. Kunden haben das App Registry selten genutzt, weshalb es für unser Team nicht prioritär war. Wenn bestimmte Funktionen eines Produkts kaum verwendet werden, tauchen deren Bugs selten auf und die Entwickler hören auf, den Code zu überwachen. Es ist leicht, in die Irre zu glauben, dass es so sein sollte – bis plötzlich diese Funktion im Mittelpunkt eines größeren Vorfalls steht.
Wie geht es weiter?
Die Arbeiten zur Gewährleistung der Service-Stabilität ruhen nie und wir verbessern ständig unsere Leistungen. Die Traffic-Mengen auf quay.io wachsen weiterhin und wir sind uns bewusst, dass wir alles tun müssen, um das Vertrauen der Kunden zu rechtfertigen. Daher arbeiten wir derzeit an folgenden Aufgaben:
- Bereitstellung von nur lesenden Datenbank-Repliken, um dem Service zu helfen, den entsprechenden Traffic im Falle von Problemen mit der Hauptinstanz RDS zu verarbeiten.
- Aktualisierung der RDS-Instanz. Die aktuelle Version stellt an sich kein Problem dar. Vielmehr möchten wir einfach einen falschen Hinweis beseitigen (dem wir während des Ausfalls gefolgt sind); das Halten der Software auf dem neuesten Stand wird einen weiteren Faktor für zukünftige Ausfälle beseitigen.
- Zusätzliches Caching im gesamten Cluster. Wir suchen weiterhin nach Bereichen, in denen Caching die Last auf die Datenbank reduzieren kann.
- Hinzufügen einer Webanwendungs-Firewall (WAF), um zu sehen, wer sich bei quay.io anmeldet und warum.
- Ab der nächsten Version werden die Red Hat OpenShift-Cluster auf Kataloge von Operatoren (Operator Catalogs) umsteigen und den App Registry zugunsten von Container-basierten Images, die auf quay.io verfügbar sind, aufgeben.
- Langfristig könnte die Unterstützung der Spezifikationen der Open Container Initiative (OCI) die App Registry ersetzen. Derzeit wird sie als native Funktion von Quay umgesetzt und wird den Nutzern zur Verfügung stehen, wenn die Spezifikation endgültig genehmigt ist.
All diese Maßnahmen sind Teil der anhaltenden Investitionen von Red Hat in quay.io, während wir uns von einem kleinen, 'startup-artigen' Team zu einer ausgereiften SRE-gemanagten Plattform entwickeln. Wir wissen, dass viele unserer Kunden auf quay.io für ihre täglichen Aufgaben angewiesen sind (einschließlich Red Hat!) und bemühen uns, so transparent wie möglich über kürzliche Ausfälle und unsere laufenden Bemühungen um Verbesserung zu sein.
P.S. vom Übersetzer
Lesen Sie auch in unserem Blog:
- «»;
- «»;
- «».
Quelle: habr.com
