CICD: Nahtlose Bereitstellung auf verteilten Clustersystemen ohne Ausfallzeiten

Published on October 09, 2018

CICD: Nahtlose Bereitstellung auf verteilten Clustersystemen ohne Ausfallzeiten

    Ich veröffentliche den zweiten Bericht von unserem ersten Treffen im September. Das letzte Mal konnten Sie lesen (und sehen), wie Sie mit Consul Stateful Services von Ivan Bubnov von BIT.GAMES skalieren konnten, und heute werden wir über CICD sprechen. Genauer gesagt, unser Systemadministrator Egor Panov, der für die Verfügbarkeit von Infrastruktur und Diensten in Pixonic verantwortlich ist, wird darüber berichten. Unter den Cut-Transcript-Performances.



    Zunächst ist die Spielebranche riskanter - man weiß nie, was genau im Herzen des Spielers versinkt. Und deshalb schaffen wir viele Prototypen. Natürlich fertigen wir Prototypen am Knie von Stöcken, Streichern und anderen improvisierten Materialien.

    Es scheint, dass es mit einem solchen Ansatz unmöglich ist, irgendetwas später zu unterstützen. Aber auch in dieser Phase halten wir. Halte dich an drei Säulen fest:

    1. exzellente Expertentester;
    2. Interaktion mit ihnen;
    3. die Zeit, die wir zum Testen ausgeben.

    Wenn wir also unsere Prozesse nicht aufbauen, beispielsweise Deployment oder CI (Continuous Integration), werden wir früher oder später zu dem Schluss kommen, dass die Testzeit immer länger wird. Und wir werden entweder langsam alles tun und den Markt verlieren oder einfach bei jeder Verzögerung explodieren.

    Der CICD-Prozess ist jedoch nicht so einfach zu erstellen. Einige werden sagen, na ja, ich werde Jenkins installieren, ich werde schnell etwas aufrufen, also habe ich eine fertige CICD. Nein, es ist nicht nur ein Werkzeug, es ist auch eine Praxis. Beginnen wir in der richtigen Reihenfolge.


    Die erste In vielen Artikeln heißt es, dass alles in einem Repository aufbewahrt werden muss: der Code, die Tests, das Aufwärmen und sogar das Datenbankschema und die IDE-Einstellungen, die allen gemeinsam sind. Wir sind unseren Weg gegangen.

    Wir haben verschiedene Repositorys identifiziert: Bereitstellen in einem Repository, Testen in einem anderen. Das geht schneller. Vielleicht passen Sie nicht, aber für uns ist es viel bequemer. Da es in diesem Absatz einen wichtigen Punkt gibt, müssen Sie einen einfachen und transparenten für alle gitflow erstellen. Natürlich können Sie es irgendwo herunterladen, aber in jedem Fall müssen Sie es anpassen, verbessern. Für uns zum Beispiel lebt die Wärme von einem eigenen Githflo, das eher GitHub-Flow ähnelt, und die serverseitige Entwicklung lebt von einem eigenen Githflo.

    Der nächste Punkt. Sie müssen einen vollautomatischen Build konfigurieren. Es ist klar, dass der Entwickler in der ersten Phase das Projekt selbst zusammenstellt und es dann mit Hilfe von SCP persönlich nutzt, es selbst startet und an wen er es braucht sendet. Diese Option hielt nicht lange an, ein Bash-Skript erschien. Nun, da sich die Entwicklungsumgebung ständig ändert, ist ein dedizierter Build-Server erschienen. Er lebte sehr lange. Während dieser Zeit konnten wir die Anzahl der Server auf 500 erhöhen, die Serverkonfiguration auf Puppet konfigurieren, Legacy auf Puppet speichern, Puppet ablehnen, zu Ansible wechseln, und dieser Build-Server lebte weiter.

    Wir beschlossen, nach zwei Anrufen alles zu ändern, der dritte wartete nicht. Die Geschichte ist klar: Der Buildserver ist eine einzige Fehlerquelle, und natürlich fiel das Rechenzentrum, als wir etwas reparieren mussten, vollständig mit unserem Buildserver zusammen. Und der zweite Aufruf: Wir mussten die Java-Version aktualisieren - wir haben sie auf dem Buildserver aktualisiert, auf die Bühne gebracht, alles war cool, alles war großartig und genau dort war ein kleiner Bugfix erforderlich, um auf dem Produkt zu laufen. Natürlich haben wir vergessen, zurück zu rollen und alles ist einfach auseinandergefallen.

    Danach haben wir alles so umgeschrieben, dass der gesamte Build auf absolut jedem TeamCity-Agenten ausgeführt werden kann, und haben es auf Ansible umgeschrieben. Wenn Sie also auf Ansible konfigurieren, sollten Sie dasselbe Tool für die Bereitstellung verwenden.

    Die folgende Regel: Je öfter Sie sich verpflichten, desto besser. Und warum? Weil es ein viertes gibt: Jedes Commit wird ausgeführt. Und in der Tat sogar mehr als jedes Commit. Ich habe bereits gesagt, dass wir TeamCity haben und es Ihnen ermöglicht, ein Commit von Ihrer bevorzugten IDE aus zu starten (Sie können sich vorstellen, was ich meine). Eigentlich schnelles Feedback, alles ist super.

    Ein defekter Build wird sofort repariert. Sobald Sie die automatische Bereitstellung eingerichtet haben, müssen Sie die automatische Benachrichtigung in Slack einrichten. Wir alle wissen genau, dass ein Entwickler weiß, wie sein Code funktioniert, nur in dem Moment, in dem er ihn schreibt. Deshalb: eine Person hat es herausgefunden - hat es sofort behoben.

    Wir testen an der Umgebung, indem wir das Produkt wiederholen. Alles ist einfach, wir haben uns für Ansible und AWX entschieden. Jemand könnte fragen, was ist mit Docker, Kubernetes, OpenShift, wo all die Probleme von Anfang an gelöst wurden? Ich habe vergessen zu sagen, wir haben sowohl Linux- als auch Windows-Komponenten. Und zum Beispiel den Photon-Server, den wir unter Windows erst kürzlich mehr oder weniger normal in einen 10-GB-Docker-Container packen konnten. Dementsprechend haben wir eine Anwendung unter Windows, die in einem Container schlecht verpackt ist. Es gibt eine Anwendung unter Linux (in Java), die sich perfekt packen lässt, dies ist jedoch nicht erforderlich. Sie funktioniert überall dort, wo Sie sie ausführen. Das ist Java.

    Dann wählten wir zwischen Ansible und Chef. Beide funktionieren gut mit Windows, aber Ansible war für uns viel einfacher. Als wir AWX installiert haben - im Allgemeinen ist alles Feuer geworden. In AWX gibt es Geheimnisse, es gibt Grafiken, Geschichte. Man kann jemandem zeigen, der von all dem weit entfernt ist, er wird sofort alles sehen und alles wird klar.

    Und Sie müssen den Build immer schnell halten. Ich weiß nicht warum, aber immer, wenn Sie ein neues Projekt starten, werden Sie den Build-Server und die Agenten vergessen und einen Computer auswählen, der neben Ihnen lag - dies ist unser Build-Server. Es ist unerwünscht, diesen Fehler zu wiederholen, da alles, worüber ich spreche (schnelles Feedback, Vorteile) - alles wird nicht mehr so ​​relevant sein, wenn der Build auf Ihrem eigenen Laptop viel schneller als auf einer Build-Server-Farm ausgeführt wird.


    7 Punkte - und wir haben bereits eine Art CI-Prozess erstellt. Großartig Das folgende Diagramm ist nicht sichtbar, aber an der Seite befindet sich ein Graylog. Wer unsere Artikel über Habré liest, hat bereits gesehen, wie wir Graylog ausgewählt und installiert haben . In jedem Fall hilft es, otdebazhit, wenn noch ein Problem aufgetreten ist.


    Hier auf dieser Basis ist es bereits möglich, zum Deployment zu gelangen.


    Aber ich habe bereits im zweiten Absatz über den Einsatz gesprochen, daher werde ich nicht weiter darauf eingehen. Ich sage eines: Wenn Sie Ansible verwenden, müssen Sie diese Seriennummer auf der Folie hinzufügen. Mehr als einmal ist es passiert, dass Sie etwas gestartet haben, und dann haben Sie es verstanden, aber ich habe es nicht gestartet, oder nicht am richtigen Ort oder am falschen Ort, und dann sehen Sie, dass es nur ein Server ist. Und wir können leicht einen Server verlieren und Sie laden ihn einfach neu, niemand bemerkt.

    Außerdem haben sie ein Repository mit Artefakten auf Nexus installiert - es ist ein einziger Einstiegspunkt für absolut jeden, nicht nur für CI.


    Und es hilft uns, die Wiederholbarkeit sicherzustellen. Da Nexus als Proxy-Dienst in verschiedenen Regionen eingesetzt werden kann, beschleunigen sie die Bereitstellung, die Installation von RPM-Paketen und Docker-Images.

    Bei der Verlegung eines neuen Projekts ist es ratsam, Komponenten auszuwählen, die für die Automatisierung leicht zugänglich sind. Mit dem Photon-Server sind wir beispielsweise gescheitert. In jedem Fall war es die beste Lösung für andere Parameter. Aber Cassandra zum Beispiel ist sehr bequem aktualisiert und automatisiert.


    Hier ist ein Beispiel eines unserer Projekte. Der Client kommt zum APP-Server, wo er ein Profil in der Cassandra-Datenbank hat, und geht dann zum Master-Server, der ihm mit Hilfe von Matchmaking einen Spieleserver mit etwas Platz gibt. Alle anderen Dienste werden in Form von "application - DB" ausgeführt und auf die gleiche Weise aktualisiert.

    Der zweite Punkt: Sie müssen eine einfache, lose gekoppelte Architektur für die Bereitstellung bereitstellen. Es ist uns gelungen.


    Siehe, aktualisiere zum Beispiel den App-Server. Wir haben dedizierte Discovery-Services, die den Balancer neu konfigurieren. Wir gehen einfach zum App-Server, löschen ihn, er gerät aus dem Gleichgewicht, wir aktualisieren ihn und das wars. Und so mit jedem einzeln.

    Master-Server werden fast identisch aktualisiert. Der Client pingt jeden Masterserver in der Region an und wechselt zu demjenigen, auf dem Ping besser ist. Wenn wir also den Master-Server aktualisieren, wird das Spiel möglicherweise etwas langsamer, dies ist jedoch einfach und problemlos möglich.

    Spieleserver werden etwas anders aktualisiert, da es noch ein Spiel gibt. Wir gehen zum Matchmaking, bitten ihn, einen bestimmten Server aus dem Gleichgewicht zu bringen, wir gelangen zum Spieleserver, warten, bis die Spiele genau Null werden, und aktualisieren. Dann kehren wir zum Balancieren zurück.


    Der entscheidende Punkt hierbei sind die Endpunkte, über die jede Komponente verfügt und mit denen die Kommunikation einfach und unkompliziert ist. Wenn Sie ein Beispiel benötigen, ist das Elasticsearch-Cluster. Mit normalen http-Anfragen in JSON können Sie problemlos damit kommunizieren. Und er gibt sofort in der gleichen JSON alle Arten von verschiedenen Metriken und allgemeinen Informationen über den Cluster aus: grün, gelb, rot.

    Nachdem wir diese 12 Schritte ausgeführt hatten, erhöhten wir die Anzahl der Umgebungen, begannen, mehr zu testen, setzten uns schneller ein und die Leute erhielten schnelles Feedback.


    Was sehr wichtig ist, wir haben die Einfachheit und Geschwindigkeit der Experimente. Und das ist sehr wichtig, denn wenn es viele Experimente gibt, können wir leicht die fehlerhaften Ideen aussortieren und bei den richtigen anhalten. Und das nicht aufgrund subjektiver Einschätzungen, sondern aufgrund objektiver Indikatoren.

    Tatsächlich sehe ich nicht einmal zu, wann wir dort eine Bereitstellung haben, wenn eine Veröffentlichung stattfindet. Es gibt kein Gefühl von "Oh, loslassen!", Alles hat sich angesammelt und Gänsehaut. Jetzt ist es so eine Routineoperation, ich sehe gelegentlich etwas in der Chatika, dass etwas kaputt geht, na ja, okay. Das ist echt cool. Ihr Sysadmin wird vor Freude brüllen, wenn Sie das tun.

    Aber die Welt steht nicht still, er springt manchmal. Wir haben etwas zu verbessern. Zum Beispiel möchten Build-Protokolle auch in Graylog geworfen werden. Dies erfordert eine weitere Verfeinerung der Protokollierung, sodass es keine separate Story gibt, sondern eindeutig: So verlief der Build, wie wurde er getestet, wie wurde er bereitgestellt, und so verhält er sich auf dem Produkt. Und kontinuierliche Überwachung - damit ist die Geschichte komplizierter.


    Wir verwenden Zabbix und er ist für solche Ansätze überhaupt nicht bereit. Bald wird die 4. Version veröffentlicht, wir werden herausfinden, was da ist und wenn alles schlecht ist, werden wir eine andere Lösung finden. Wie wir das schaffen, werde ich Ihnen beim nächsten Mal mitteilen.

    Fragen aus dem Publikum


    Und was passiert, wenn Sie in der Produktion Abfälle einsammeln? Sie haben beispielsweise nicht die Leistung berechnet und bei der Integration ist alles in Ordnung. In der Produktion werden Sie jedoch feststellen, dass die Server allmählich ausfallen. Wie rollst du zurück? Gibt es eine Art "Rette mich" -Button?

    Wir haben versucht, den Rücktransport zu automatisieren. Sie können dann in den Berichten nachlesen, wie es cool funktioniert, wie wunderbar das alles ist. Aber zuerst entwerfen wir es so, dass die Versionen abwärtskompatibel sind und testen es. Und als wir dieses vollautomatische Ding machten, das etwas dort prüfte und zurückrollte und dann damit zu leben begann, stellten wir fest, dass wir viel mehr in es investieren, als wenn wir nur die alten Versionen mit dem gleichen Pedal nehmen .

    In Bezug auf das automatische Update von Deploy: Warum nehmen Sie Änderungen am aktuellen Server vor und fügen keinen neuen hinzu und fügen ihn einfach der Zielgruppe oder dem Balancer hinzu?

    Also schneller.

    Wenn Sie beispielsweise die Java-Version aktualisieren müssen, ändern Sie den Status von Amazon, aktualisieren die Java-Version oder etwas anderes. Wie können Sie in diesem Fall ein Rollback durchführen? Nehmen Sie Änderungen am Produktionsserver vor?

    Ja, jede Komponente funktioniert einwandfrei mit der neuen und der alten Version. Ja, möglicherweise müssen Sie den Server perezalit.

    Es gibt Zustandsänderungen, wenn große Probleme möglich sind ...

    Dann explodieren wir.

    Mir kommt es nur so vor, als würde ich einen neuen Server hinzufügen und ihn einfach auf dem Balancer in der Zielgruppe platzieren - eine kleine Aufgabe und eine ziemlich gute Übung.

    Wir werden auf Hardware gehostet, nicht in den Clouds. Wir fügen einen Server hinzu - es ist möglich, aber etwas länger als nur ein Klick in die Cloud. Deshalb nehmen wir unseren aktuellen Server (wir haben keine solche Last, damit wir einige der Maschinen nicht rausholen können) - wir geben einige der Maschinen aus, aktualisieren sie, senden Verkaufsdaten dorthin, sehen, wie es funktioniert, wenn alles in Ordnung ist, dann gehen wir weiter andere Autos.

    Sie sagen, wenn jeder Commit läuft und alles schlecht ist, regelt der Entwickler sofort alles. Wie verstehst du, dass alles schlecht ist? Welche Prozeduren werden mit einem Commit durchgeführt?

    Natürlich ist das erste Mal eine Art manuelles Testen, das Feedback ist langsam. Später, von einigen Autotests auf Appium, wird all dies abgedeckt, es funktioniert und gibt eine Art Feedback darüber, ob Tests gefallen sind oder nicht.

    Dh Zuerst rollt jedes Commit aus und die Tester schauen es sich an.

    Nun, nicht jeder ist eine Praxis. Wir haben ein Training dieser 12 Punkte absolviert - beschleunigt. Tatsächlich ist es eine lange und harte Arbeit, vielleicht ein Jahr lang. Aber im Idealfall kommst du dazu und alles funktioniert. Ja, wir brauchen eine Art Autotest, zumindest einen minimalen Satz, damit alles funktioniert.

    Und die Frage ist kleiner: Es gibt einen App-Server auf dem Bild und so weiter. Was interessiert mich dort? Sie sagten, dass Sie den Docker nicht haben. Was ist ein Server? Naked Java oder was?

    Irgendwo ist Photon unter Windows (Spieleserver), der App-Server ist eine Java-Anwendung auf Tomkat.

    Dh irgendein virtualok, irgendwelche container, irgendwas?

    Java ist ein Container.

    Und Ansiblom all diese Rolle?

    Ja Dh Ab einem bestimmten Punkt haben wir einfach nicht in Orchestrierung investiert. Warum? Wenn in jedem Fall das Windows separat auf die gleiche Weise verwaltet werden muss und hier alles mit einem Tool abgedeckt ist.

    Und eine Datenbank als? Abhängigkeit von Komponente oder Service?

    Im Dienst selbst gibt es ein Schema, das sicher ist, wenn es angezeigt wird und so gestaltet werden muss, dass nichts gelöscht wird, sondern nur etwas hinzugefügt wird und es abwärtskompatibel ist.

    Haben Sie auch eine Eisenbasis oder eine Basis irgendwo in einer Wolke bei Amazon?

    Die größte Base ist Eisen, aber es gibt noch andere. Es gibt kleine, RDS - das ist nicht Eisen, virtuell. Diese kleinen Dienste, die ich gezeigt habe: Chatrooms, Ligen, Kommunikation mit Facebook, Clans, einige davon - RDS.

    Masterserver - wie ist das?

    Dies ist im Wesentlichen derselbe Spieleserver, nur mit dem Vorzeichen eines Masters und es ist ein Balancer. Dh Der Client pingt alle Master an, dann erhält er denjenigen, an den der Ping kleiner ist, und der Master-Server sammelt bereits mithilfe von Matchmaking die Räume auf den Game-Servern und sendet den Spieler.

    Ich verstehe richtig, dass Sie die Migration schreiben (wenn Features angezeigt werden), um die Daten für jedes Rollout zu aktualisieren. Sie sagten, Sie nehmen alte Artefakte und füllen sie auf - und was passiert mit diesen Daten? Schreiben Sie eine Migration, um die Datenbank zurückzusetzen?

    Dies ist ein sehr seltener Rollback-Vorgang. Ja, Sie schreiben Migrationshandles und was zu tun ist.

    Wie werden Serverupdates mit Clientupdates synchronisiert? Dh Sie müssen eine neue Version des Spiels veröffentlichen - aktualisieren Sie zuerst alle Server, dann werden die Clients aktualisiert? Unterstützt der Server sowohl die alte als auch die neue Version?

    Ja, wir entwickeln Feature-Toggle und Feature-Dimming. Dh Dies ist ein spezieller Griff, mit dem Sie einige Funktionen später aktivieren können. Sie können in aller Ruhe ein Upgrade durchführen, um sicherzustellen, dass alles für Sie funktioniert. Diese Funktion ist jedoch nicht enthalten. Und wenn Sie bereits einen Client aufgelöst haben, können Sie mit Fidhidimming 10% optimieren und sicherstellen, dass alles in Ordnung und dann in vollem Umfang funktioniert.

    Sie sagen, dass Sie Teile des Projekts separat in verschiedenen Repositorys speichern, d. H. Haben Sie einen Prozess zu entwickeln? Wenn Sie das Projekt selbst ändern, sollten Ihre Tests fallen, da Sie das Projekt geändert haben. Daher müssen die separat liegenden Tests so schnell wie möglich behoben werden.

    Ich erzählte Ihnen von der "engen Interaktion der Wale mit den Testern". Dieses Schema mit verschiedenen Repositorys funktioniert nur dann sehr gut, wenn eine sehr enge Kommunikation besteht. Das ist für uns kein Problem, jeder kommuniziert leicht miteinander, es gibt gute Kommunikation.

    Dh Verfügt Ihr Team über ein Test-Repository, das von Testern unterstützt wird? Und Autotests liegen separat?

    Ja Sie haben eine Funktion erstellt, und Sie können aus dem Repository der Tester die erforderlichen automatischen Tests eingeben, aber nicht alles andere überprüfen.

    Bei diesem Ansatz, bei dem alles schnell läuft, können Sie es sich leisten, bei jedem Commit sofort zum Produkt zu gehen. Halten Sie sich an solche Taktiken oder stellen Sie einige Veröffentlichungen zusammen? Dh Gibt es einmal pro Woche, nicht freitags, nicht am Wochenende, irgendwelche Release-Taktiken, die Sie haben, oder ist das Feature fertig, können Sie es veröffentlichen? Denn wenn Sie ein kleines Release kleinerer Funktionen erstellen, ist die Wahrscheinlichkeit geringer, dass alles kaputt geht, und wenn etwas kaputt geht, wissen Sie es mit Sicherheit.

    Client-Benutzer alle fünf Minuten zu zwingen oder täglich eine neue Version herunterzuladen, ist keine Eisidee. In jedem Fall sind Sie an den Kunden gebunden. Es ist großartig, wenn Sie ein Webprojekt haben, in dem Sie jeden Tag ein Update durchführen können und nichts zu tun haben. Beim Kunden ist die Geschichte komplizierter, wir haben eine Art Release-Taktik und folgen ihr.

    Sie erzählten von der Automatisierung des Rollouts auf Einkaufsservern, und (wie ich es verstehe) gibt es auch eine Automatisierung des Rollouts für einen Test - und was ist mit Entwicklungsumgebungen? Gibt es eine Automatisierung, die von Entwicklern bereitgestellt wird?

    Fast dasselbe. Das einzige ist, dass es sich nicht mehr um Eisenserver handelt, sondern um virtuelle Maschinen, aber das Wesentliche ist ungefähr dasselbe. Gleichzeitig haben wir auf dem gleichen Ansible (wir haben Ovirt) die Erstellung dieser virtuellen Maschine und das Rändeln darauf geschrieben.

    Haben Sie die ganze Geschichte zusammen mit den Ansible-Verkaufs- und Testkonfigurationen in einem Projekt gespeichert oder lebt und entwickelt sie separat?

    Wir können sagen, dass dies separate Projekte sind. Dev (wir nennen es devbox) ist eine Geschichte, in der sich alles in einer Packung befindet, und auf dem Produkt steht eine verteilte Geschichte.

    Weitere Berichte von Pixonic DevGAMM Talks