
Allen gute WĂŒnsche!Â
Ich bin Nikita, Teamleiter des Ingenieurteams bei Cian. Eine meiner Aufgaben im Unternehmen besteht darin, die Anzahl der infrastrukturellen VorfÀlle in der Produktion auf null zu reduzieren.
Das Thema, das ich gleich behandeln werde, hat uns viel Schmerz bereitet. Ziel dieses Artikels ist es, anderen zu helfen, unsere Fehler zu vermeiden oder deren Auswirkungen zumindest zu minimieren.Â
PrÀambel
Vor langer Zeit, als Cian aus Monolithen bestand und es noch keine Anzeichen von Mikrodiensten gab, haben wir die VerfĂŒgbarkeit der Ressource durch die ĂberprĂŒfung von 3â5 Seiten gemessen.Â
Wenn sie antworten â alles in Ordnung, wenn sie ĂŒber lĂ€ngere Zeit nicht antworten â Alarm. Wie lange sie nicht funktionieren mĂŒssen, damit das als Vorfall gilt, wurde in Besprechungen entschieden. Das Ingenieurteam war stets an der Untersuchung von VorfĂ€llen beteiligt. Wenn die Untersuchung abgeschlossen war, wurde ein Post-Mortem verfasst â ein Bericht in Form von: was passiert ist, wie lange es gedauert hat, was im Moment unternommen wurde und was wir in Zukunft tun werden.Â
Die Hauptseiten der Website oder wie wir erkennen, dass wir den Tiefpunkt erreicht haben
Â
Um die FehlerprioritĂ€t besser zu verstehen, haben wir die kritischsten Seiten fĂŒr die GeschĂ€ftsablĂ€ufe der Website hervorgehoben. Anhand dieser Seiten zĂ€hlen wir die Anzahl der erfolgreichen und nicht erfolgreichen Anfragen sowie ZeitĂŒberschreitungen. So messen wir die VerfĂŒgbarkeit.Â
Angenommen, wir haben einige extrem wichtige Bereiche der Website identifiziert, die fĂŒr den Hauptservice - die Suche und Veröffentlichung von Anzeigen - verantwortlich sind. Wenn die Anzahl der fehlerhaften Anfragen 1 % ĂŒbersteigt, handelt es sich um einen kritischen Vorfall. Ăbersteigt der Fehlerprozentsatz wĂ€hrend der Hauptsendezeit von 0,1 % in einem Zeitraum von 15 Minuten, wird auch dies als kritischer Vorfall betrachtet. Diese Kriterien decken den GroĂteil der VorfĂ€lle ab, wĂ€hrend andere auĂerhalb dieses Artikels liegen.

Die besten VorfÀlle bei Cian
Wir haben also eindeutig gelernt, dass ein Vorfall aufgetreten ist.Â
Jetzt ist jeder Vorfall detailliert beschrieben und in einem Jira-Epic dokumentiert. Ăbrigens haben wir dafĂŒr ein separates Projekt gegrĂŒndet, das wir FAIL genannt haben â dort können nur Epics erstellt werden.Â
Wenn man alle FehlschlĂ€ge der letzten Jahre zusammenfasst, sind die hĂ€ufigsten:Â
- VorfÀlle im Zusammenhang mit mssql;
- VorfÀlle, die durch externe Faktoren verursacht wurden;
- Fehler des Administrators.
Lassen Sie uns genauer auf die Fehler von Administratoren eingehen, sowie auf einige andere interessante Fehltritte.
Platz fĂŒnf â âOrdnung im DNS schaffenâ
Es war ein trĂŒber Dienstag. Wir beschlossen, Ordnung in unser DNS-Cluster zu bringen.Â
Wir wollten die internen DNS-Server von BIND auf PowerDNS umstellen und dafĂŒr vollkommen separate Server einrichten, auf denen nichts auĂer DNS lĂ€uft.Â
Wir haben in jeder Location unserer Rechenzentren einen DNS-Server platziert, und es kam der Moment, die Zonen von BIND auf PowerDNS zu migrieren und die Infrastruktur auf die neuen Server umzuschalten.Â
Mitten im Umzug blieb von all den ServerServern, die in den lokalen Caches der BIND-Server angegeben waren, nur einer ĂŒbrig, der im Rechenzentrum in St. Petersburg war. Dieses Rechenzentrum wurde ursprĂŒnglich als nicht kritisch fĂŒr uns deklariert, wurde aber plötzlich zum Single Point of Failure.
Gerade in dieser Phase des Umzugs fiel die Verbindung zwischen Moskau und St. Petersburg aus. Wir hatten faktisch fĂŒnf Minuten lang keinen DNS und kamen erst wieder online, als der Hoster die Probleme behoben wurden.Â
Fazit:
FrĂŒher haben wir externe Faktoren bei der Vorbereitung auf Arbeiten vernachlĂ€ssigt, aber jetzt gehören sie ebenfalls zu den Aspekten, auf die wir uns vorbereiten. Wir streben nun an, dass alle Komponenten nach dem n-2 Prinzip reserviert sind, und wĂ€hrend der Arbeiten können wir dieses Niveau auf n-1 absenken.
- Beim Erstellen des Aktionsplans sollten Sie Punkte markieren, an denen der Service ausfallen kann, und ein Szenario durchdenken, bei dem alles "schlimmer als gedacht" lÀuft, um vorbereitet zu sein.
- Verteilen Sie die internen DNS-Server auf verschiedene geografische Standorte/Rechenzentren/Racks/Switches/EingÀnge.
- Auf jedem Server installieren Sie einen lokalen caching DNS-Server, der Anfragen an die Haupt-DNS-Server weiterleitet und im Falle seiner Nichterreichbarkeit aus dem Cache antwortet.Â
Platz vier â âOrdnung in Nginx schaffenâ
Eines Tages beschloss unser Team, dass es âdas reichtâ, und der Prozess zur Umstrukturierung der nginx-Konfigurationen begann. Das Hauptziel war es, die Konfigurationen in eine intuitive Struktur zu bringen. FrĂŒher war alles âhistorisch bedingtâ und machte wenig Sinn. Jetzt haben wir jeden server_name in eine gleichnamige Datei ausgelagert und alle Konfigurationen in verschiedene Ordner verteilt. Ăbrigens enthĂ€lt die Konfiguration 253.949 Zeilen oder 7.836.520 Zeichen und belegt fast 7 Megabyte. Die oberste Ebene der Struktur:Â
Nginx-Struktur
âââ access
â Â âââ allow.list
...
â Â âââ whitelist.conf
âââ geobase
â Â âââ exclude.conf
...
â Â âââ geo_ip_to_region_id.conf
âââ geodb
â Â âââ GeoIP.dat
â Â âââ GeoIP2-Country.mmdb
â Â âââ GeoLiteCity.dat
âââ inc
â Â âââ error.inc
...
â Â âââ proxy.inc
âââ lists.d
â Â âââ bot.conf
...
â Â âââ dynamic
â Â âââ geo.conf
âââ lua
â Â âââ cookie.lua
â Â âââ log
â Â â Â âââ log.lua
â Â âââ logics
â Â â Â âââ include.lua
â Â â Â âââ ...
â Â â Â âââ utils.lua
â Â âââ prom
â Â Â Â âââ stats.lua
â Â Â Â âââ stats_prometheus.lua
âââ map.d
â Â âââ access.conf
â Â âââ ..Â
â Â âââ zones.conf
âââ nginx.conf
âââ robots.txt
âââ server.d
â Â âââ cian.ru
â Â â Â âââ cian.ru.conf
â Â â Â âââ ...
â Â â Â âââ my.cian.ru.conf
âââ service.d
â Â âââ ...
â Â âââ status.conf
âââ upstream.d
    âââ cian-mcs.conf
    âââ ...
    âââ wafserver.confEs ist deutlich besser geworden, allerdings hatten beim Umbenennen und der Verteilung der Konfigurationen einige von ihnen die falsche Erweiterung und wurden nicht in die Direktive include *.conf aufgenommen. Infolgedessen waren einige Hosts nicht erreichbar und gaben einen 301-Redirect zur Hauptseite zurĂŒck. Da der Antwortcode nicht 5xx/4xx war, fiel dies nicht sofort auf, sondern erst am Morgen. Daraufhin begannen wir mit dem Schreiben von Tests zur ĂberprĂŒfung der Infrastrukturkomponenten.
Fazit:Â
- Strukturieren Sie Ihre Konfigurationen (nicht nur nginx) sorgfĂ€ltig und planen Sie die Struktur bereits in der frĂŒhen Projektphase. So machen Sie es Ihrem Team verstĂ€ndlicher, was wiederum die Time-to-Market verkĂŒrzt.
- FĂŒr einige Infrastrukturkomponenten schreiben Sie Tests. Zum Beispiel: ĂberprĂŒfen Sie, ob alle wichtigen server_name den richtigen Status zurĂŒckgeben und die Antwort richtig ist. Es genĂŒgt, ein paar Skripte zur VerfĂŒgung zu haben, die die grundlegenden Funktionen der Komponente ĂŒberprĂŒfen, damit Sie nicht um 3 Uhr nachts in Panik geraten mĂŒssen, was Sie noch ĂŒberprĂŒfen mĂŒssen.Â
Der dritte Platz - "Plötzlich war der Speicher in Cassandra voll"
Die Daten wuchsen stetig, und alles war gut, bis die Reparaturen groĂer Keyspaces im Cassandra-Cluster fehlschlugen, weil die Kompaktierung nicht durchgefĂŒhrt werden konnte.Â
An einem nebligen Tag verwandelte sich der Cluster fast in einen KĂŒrbis, und zwar:
- es waren noch etwa 20% des Gesamtspeichers im Cluster verfĂŒgbar;
- Es ist nicht möglich, Nodes hinzuzufĂŒgen, da der Cleanup nach der HinzufĂŒgung eines Nodes aufgrund von Speichermangel auf den Partitionen nicht erfolgt;
- Die Leistung sinkt allmĂ€hlich, da die Kompaktierung nicht funktioniert;Â
- der Cluster arbeitet im Notfallmodus.

Ausgang â wir haben 5 weitere Nodes ohne Bereinigung hinzugefĂŒgt, anschlieĂend begannen wir, systematisch Nodes aus dem Cluster zu entfernen und wieder als leere Nodes einzufĂŒhren, auf denen kein Platz mehr war. Die dafĂŒr benötigte Zeit war erheblich höher, als wir uns gewĂŒnscht hĂ€tten. Es bestand das Risiko einer teilweisen oder vollstĂ€ndigen UnzugĂ€nglichkeit des Clusters.Â
Fazit:
- Auf allen Cassandra-Servern sollte nicht mehr als 60 % des Speicherplatzes in jedem Abschnitt belegt sein.Â
- Sie sollten nicht mehr als zu 50 % ausgelastet sein, was die CPU betrifft.
- Man sollte das Capacity Planning nicht vernachlĂ€ssigen und dieses fĂŒr jede Komponente, basierend auf ihren spezifischen Anforderungen, grĂŒndlich durchdenken.
- Je mehr Nodes im Cluster enthalten sind, desto besser. Server, die nur einen geringen Datensatz enthalten, lassen sich schneller neu starten, und ein solcher Cluster ist leichter wiederherzustellen.Â
Der zweite Punkt â «Daten aus dem Consul Key-Value-Speicher sind verschwunden»
FĂŒr die Service-Discovery verwenden wir, wie viele andere, Consul. Allerdings nutzen wir es auch fĂŒr die Blue-Green-Bereitstellung unseres Monolithen. Dort wird die Information ĂŒber aktive und inaktive Upstreams gespeichert, die wĂ€hrend des Deployments wechseln. Zu diesem Zweck wurde ein Deployment-Service entwickelt, der mit KV interagiert. Irgendwann gingen die Daten aus dem KV verloren. Wir haben sie aus dem GedĂ€chtnis wiederhergestellt, jedoch mit einigen Fehlern. Infolgedessen wurde die Last auf die Upstreams ungleichmĂ€Ăig verteilt, und wir erhielten viele 502-Fehler aufgrund von CPU-Ăberlastung der Backends. Letztendlich sind wir von Consul KV auf Postgres umgestiegen, von wo aus es nicht so einfach ist, sie zu entfernen. Â
Fazit:
- Dienste ohne jegliche Autorisierung sollten keine kritischen Daten fĂŒr den Betrieb der Website enthalten. Wenn Sie beispielsweise keine Autorisierung in ES haben, wĂ€re es besser, den Zugriff auf Netzwerkebene ĂŒberall dort zu sperren, wo er nicht benötigt wird, nur notwendige Zugriffe zuzulassen und auĂerdem action.destructive_requires_name: true zu setzen.
- Testen Sie den Backup- und Wiederherstellungsmechanismus im Voraus. Erstellen Sie beispielsweise im Voraus ein Skript (zum Beispiel in Python), das sowohl Backups erstellen als auch wiederherstellen kann.
Der erste Platz geht an 'Captain Offensichtlichkeit'.Â
Wir haben zu einem bestimmten Zeitpunkt eine ungleichmĂ€Ăige Lastverteilung auf die Upstreams von Nginx festgestellt, wenn im Backend mehr als 10 Server aktiv waren. Da das Round-Robin-Verfahren die Anfragen nacheinander an die Upstreams weiterleitete und jeder Nginx-Reload von vorne begann, erhielten die ersten Upstreams immer mehr Anfragen als die anderen. Infolgedessen arbeiteten sie langsamer und die gesamte Website litt darunter. Dies wurde mit steigendem Traffic immer deutlicher. Ein einfaches Update von Nginx auf random brachte nichts â wir mussten eine Menge Lua-Code ĂŒberarbeiten, der bei Version 1.15 nicht funktionierte (zu diesem Zeitpunkt). Also haben wir unsere Nginx-Version 1.14.2 gepatcht und die UnterstĂŒtzung fĂŒr random integriert. Damit war das Problem gelöst. Dieser Bug gewinnt den Preis fĂŒr âCaptain Offensichtlichâ.
Fazit:
Es war sehr faszinierend und interessant, diesen Bug zu untersuchen).Â
- Richten Sie das Monitoring so ein, dass es Ihnen hilft, solche Fluktuationen schnell zu erkennen. Zum Beispiel kann man ELK nutzen, um die RPS (Requests per Second) fĂŒr jedes Backend jedes Upstreams zu ĂŒberwachen und die Antwortzeiten aus der Perspektive von Nginx zu verfolgen. In diesem Fall hat uns das geholfen, das Problem zu identifizieren.Â
Die Mehrheit der Fehler lĂ€sst sich durch einen sorgfĂ€ltigeren Ansatz vermeiden, wenn man bei der Arbeit aufmerksam bleibt. Man sollte immer an das Murphy-Gesetz denken: Alles, was schiefgehen kann, wird schiefgehen, und Komponenten sollten entsprechend gestaltet werden.Â
Quelle: habr.com
