Am 1. November 2017 wurde ich Leiter des Entwicklungsteams in der Timeweb-Softwareentwicklungsabteilung. Und am 12. November 2018 fragte der Abteilungsleiter, wann der Artikel für Habrahabr fertig sein würde, weil die Marketingabteilung fragte, die Freiwilligen beendet waren und der Inhaltsplan etwas anderes erforderte.
Daher möchte ich einen Rückblick darauf geben, wie sich die Entwicklungs-, Test- und Lieferprozesse unserer Produkte im vergangenen Jahr verändert haben. Über ältere Prozesse und Tools, Docker, Gitlab und wie wir uns entwickeln.
Timeweb Hoster existiert seit 2006. Während dieser ganzen Zeit investiert das Unternehmen viel Mühe, um den Kunden einen einzigartigen und bequemen Service zu bieten, der es von den Mitbewerbern unterscheidet. Timeweb verfügt über eigene mobile Anwendungen, eine webbasierte E-Mail-Schnittstelle, Kontrollfelder für virtuelles Hosting, VDS, ein Partnerprogramm, Support-Tools und vieles mehr.
In unserem Gitlab befinden sich ungefähr 250 Projekte: Client-Anwendungen, interne Tools, Bibliotheken und Konfigurations-Repositorys. Dutzende von ihnen werden aktiv entwickelt und unterstützt: Sie verpflichten sich während der Arbeitswoche, testen, sammeln und geben sie frei.
Zusätzlich zu der großen Menge an Legacy-Code bringt dies eine angemessene Anzahl geerbter Prozesse und zugehöriger Tools mit sich. Wie jedes Vermächtnis müssen sie auch gewartet, optimiert, überarbeitet und manchmal ersetzt werden.
Von all dieser Fülle von Projekten sind Control Panels dem Hosting von Kunden am nächsten. Und genau im Projekt „Control Panel“ führen wir am häufigsten verschiedene Infrastrukturverbesserungen durch und unternehmen große Anstrengungen, um die vernetzte Infrastruktur in Form zu halten. Weitergabe der gesammelten Erfahrungen und bevorzugten Praktiken an andere Produkte und deren Teams.
Über verschiedene Änderungen an Werkzeugen und Prozessen im letzten Jahr werde ich berichten.
Vagrant → Docker-Compose
Das Problem
Am ersten Arbeitstag habe ich versucht, die Bedienfelder vor Ort anzuheben. Zu diesem Zeitpunkt befanden sich fünf Webanwendungen in einem Repository:
- PU Virtual Hosting 3.0,
- PU VDS 2.0,
- PU-Webmaster,
- PERSONAL (Werkzeughalter),
- Richtlinien (Demo standardisierter Front-End-Komponenten).
Zum Ausführen lokal verwendeter Vagrant. Vagrant startete ansible. Zum Starten und Konfigurieren wurde die Hilfe von Kollegen und etwa ein Tag sauberer Zeit benötigt. Ich musste eine spezielle Version von Virtual Box installieren (es gab Probleme mit der aktuellen stabilen Version). Die Arbeit über die Konsole in der virtuellen Maschine war sehr nervig: Triviale Befehle wie die Installation von npm / composer wurden erheblich verlangsamt.
Die Leistung der Anwendungen selbst in der virtuellen Maschine war angesichts des verwendeten Technologie-Stacks und der Leistung der Maschine bei weitem nicht möglich. Ganz zu schweigen davon, dass eine virtuelle Maschine eine virtuelle Maschine ist und per Definition einen erheblichen Teil der Ressourcen Ihres PCs beansprucht.
Lösung
Die lokale Entwicklungsumgebung wurde neu geschrieben, um in Docker-Containern ausgeführt zu werden. Die auf Docker basierende Containerisierung ist die häufigste Lösung zum Isolieren der Anwendungsumgebung in allen Phasen ihres Lebenszyklus. Daher gibt es keine speziellen Alternativen.
Schlussfolgerungen
Von den Profis:
- Lokal reagiert die Anwendung schneller, Container benötigen weniger als VMs.
- Das Starten einer neuen Instanz dauert, wie die Praxis gezeigt hat, nur wenige Minuten und erfordert nur Docker (-compose), der nicht niedriger als bestimmte Versionen ist. Führen Sie nach dem Klonen einfach Folgendes aus:
make install-dev make run-dev
Es gab einige Kompromisse:
- Ich musste Shell-Bindungen für Docker-Befehle (Composer, npm usw.) schreiben. Sie sind wie docker-compose.yml im Vergleich zu Vagrant nicht vollständig plattformübergreifend. Das Starten unter Mac erfordert beispielsweise zusätzliche Anstrengungen, und unter Windows ist es wahrscheinlich einfacher, eine Distribution mit Docker in der virtuellen Linux-Maschine auszuführen. Dies ist jedoch ein akzeptabler Kompromiss Das Team verwendet nur Debian-basierte Distributionen. Dies ist eine akzeptable Einschränkung für die kommerzielle Entwicklung.
- Zur Unterstützung virtueller Hosts
wird lokal ein Container gestartet, der auf
github.com/jwilder/nginx-proxy basiert . Nicht dass es sich um eine Krücke handelt, sondern um zusätzliche Software, an die man sich manchmal erinnern muss, obwohl sie keine Probleme verursacht.
Ja, jeder im Team musste zumindest ein wenig erkennen, was Docker ist. Dank der erwähnten Shell-Skripte und Makefile führen Entwickler 95% ihrer Aufgaben aus, ohne an Container zu denken, sondern in einer garantiert identischen Umgebung.
newcp-dev → cp-steht
Diese seltsamen Ausdrücke sind die Namen von Maschinen mit Prüfständen für neue und alte Bedienfelder.
Das Problem
Ansible Rezepte wurden ausschließlich in Vagrant verwendet, sodass der Hauptvorteil nicht erreicht wurde: Die Versionen der Pakete im Produkt und auf den Ständen unterschieden sich von denen, an denen die Entwickler arbeiteten.
Die Nichtübereinstimmung der Versionen der Server-Softwarepakete auf dem alten Stand mit dem, was die Entwickler hatten, führte zu Problemen. Die Synchronisierung wurde durch die Tatsache erschwert, dass Systemadministratoren ein anderes Konfigurationsverwaltungssystem verwenden und es nicht möglich ist, es in das Entwickler-Repository zu integrieren.
Lösung
Nach der Containerisierung war es nicht schwierig, die Docker-Compose-Konfiguration für die Verwendung auf Prüfständen zu erweitern. Es wurde eine neue Maschine erstellt, um Stände auf DOCKER_HOST bereitzustellen.
Schlussfolgerungen
Entwickler sind jetzt zuversichtlich, dass lokale Umgebungen und Testumgebungen relevant sind.
TeamCity → gitlab-ci
Die Probleme
Die Projektkonfiguration in TeamCity ist ein mühsamer und undankbarer Prozess. Die CI-Konfiguration wurde getrennt vom Code in XML gespeichert, für die keine normale Versionierung gilt, sowie eine Übersicht über die Änderungen. Wir hatten auch Probleme mit der Stabilität des Erstellungsprozesses auf TeamCity-Agenten.
Lösung
Da gitlab bereits als Repository für Repositorys verwendet wurde, war die Verwendung des CI nicht nur logisch, sondern auch einfach und angenehm. Jetzt befindet sich die gesamte CI / CD-Konfiguration direkt im Repository.
Ergebnis
Im Laufe des Jahres sind fast alle von TeamCity zusammengestellten Projekte sicher nach gitlab-ci umgezogen. Wir hatten die Möglichkeit, schnell eine Vielzahl von Funktionen zur Automatisierung von CI / CD-Prozessen zu implementieren.
Screenshots von Pipelines sind am offensichtlichsten:
Abb. 1. Feature-Branch: Alle verfügbaren automatischen Prüfungen und Tests sind enthalten. Wenn Sie fertig sind, wird ein Kommentar mit einem Link zur Pipeline an die Redmine-Aufgabe gesendet. Manuelle Aufgaben zum Zusammenbau und Starten eines Standes mit diesem Zweig.
Abb. 2. Geplante Erstellung mit Code Freeze entwickeln (Checkout: rc): Entwicklung nach Zeitplan mit Code Freeze. Die Montage der Bilder für die Stände der einzelnen Bedienfelder erfolgt parallel.
Abb. 3. Tag-Pipeline: Freigabe eines der Bedienfelder. Manuelle Aufgabe zur Rollback-Freigabe.Darüber hinaus gibt es ab gitlab-ci eine Statusänderung und die Ernennung einer Person in redmine in den Phasen In Bearbeitung → Überprüfung → Qualitätssicherung, Benachrichtigung in Slack über Freigaben und Aktualisierungen, Staging und Rollbacks.
Dies ist praktisch, aber wir haben einen methodischen Punkt nicht berücksichtigt. Nachdem eine solche Automatisierung in einem Projekt implementiert wurde, gewöhnen sich die Leute schnell daran. Und wenn Sie zu einem anderen Projekt wechseln, bei dem dies noch nicht vorhanden ist oder der Prozess anders ist, können Sie vergessen, die Aufgabe in redmine zu verschieben und neu zuzuweisen, oder einen Kommentar mit einem Link zu Merge Request hinterlassen (was auch gitlab-ci tut), wodurch der Betrachter gezwungen wird, nach dem gewünschten zu suchen MR selbst. Gleichzeitig möchten Sie die .gitlab-ci.yml-Teile und den zugehörigen Shell-Code zwischen den Projekten einfach nicht kopieren, da Sie das Kopieren und Einfügen unterstützen müssen.
Fazit: Automatisierung ist gut, aber wenn sie auf der Ebene aller Teams und Projekte gleich ist - noch besser. Ich wäre der angesehenen Öffentlichkeit für Ideen dankbar, wie die Wiederverwendung einer solchen Konfiguration schön organisiert werden kann.
Pipeline-Dauer: 80 min → 8 min
Allmählich nahm unser CI unanständig viel Zeit in Anspruch. Die Tester litten stark darunter: Jeder Fix im Master musste eine Stunde auf eine Veröffentlichung warten. Es sah so aus:
Abb. 4.Pipeline 80 lvl min Dauer.Ich musste mich mehrere Tage lang mit der Analyse langsamer Orte befassen und nach Möglichkeiten suchen, um zu beschleunigen und gleichzeitig die Funktionalität aufrechtzuerhalten.
Die längsten Stellen im Prozess waren die Installation von npm-Paketen. Ohne Probleme ersetzten sie es durch Garn und sparten an mehreren Stellen bis zu 7 Minuten.
Sie lehnten automatische Staging-Updates ab und bevorzugten die manuelle Kontrolle des Status dieses Standes.
Wir haben auch mehrere Läufer hinzugefügt und die Zusammenstellung von Anwendungsbildern und alle Überprüfungen in parallele Aufgaben unterteilt. Nach diesen Optimierungen begann die Pipeline der Hauptniederlassung mit der Aktualisierung aller Stände in den meisten Fällen 7-8 Minuten zu dauern.
Capistrano → Bereitsteller
Für den Einsatz in der Produktion und auf dem Qa-Stand wurde Capistrano verwendet (und wird zum Zeitpunkt des Schreibens weiterhin verwendet). Das Hauptszenario für dieses Tool ist: Klonen des Repositorys auf den Zielserver und Ausführen aller dortigen Aufgaben.
Zuvor wurde die Bereitstellung von einem QS-Techniker mit den erforderlichen SSH-Schlüsseln von Vagrant ausgelöst. Dann, als Vagrant aufgab, zog Capistrano in einen separaten Container. Jetzt erfolgt die Bereitstellung aus dem Container mit Capistrano mit Gitlab-Läufern, die mit speziellen Tags gekennzeichnet sind und über die erforderlichen Schlüssel verfügen, automatisch, wenn die erforderlichen Tags angezeigt werden.
Das Problem hierbei ist, dass der gesamte Erstellungsprozess:
a) verbraucht erheblich die Ressourcen des Kampfservers (insbesondere Knoten / Schluck),
b) Es gibt keine Möglichkeit, Composer- und Npm-Versionen auf dem neuesten Stand zu halten. Knoten usw.
Es ist logischer, auf einem Build-Server aufzubauen (in unserem Fall Gitlab-Runner) und fertige Artefakte auf den Zielserver hochzuladen. Dadurch wird der Battle Server vor Assembly-Dienstprogrammen und ausländischer Verantwortung geschützt.
Jetzt betrachten wir Deployer als Ersatz für Capistrano (da wir keine Rubisten haben und auch nicht den Wunsch haben, mit DSL zu arbeiten) und planen, die Baugruppe auf die Gitlab-Seite zu übertragen. In einigen unkritischen Projekten haben wir es bereits versucht und sind bisher zufrieden: Es sieht einfacher aus, wir haben keine Einschränkungen festgestellt.
Gitflow: RC-Zweige → Tags
Die Entwicklung erfolgt in wöchentlichen Zyklen. Innerhalb von fünf Tagen wird eine neue Version entwickelt: Die Entwicklung akzeptiert die Verbesserungen und Korrekturen, die für die Veröffentlichung nächste Woche geplant sind. Am Freitagabend wird der Code automatisch eingefroren. Am Montag beginnt der Test der neuen Version, es werden Verbesserungen vorgenommen und bis Mitte der Arbeitswoche erfolgt eine Veröffentlichung.
Zuvor haben wir Zweige mit Namen der Form rc18-47 verwendet, was bedeutet, dass der Release-Kandidat die 47. Woche des Jahres 2018 ist. Code Freeze sollte den RC-Zweig von der Entwicklung auschecken. Aber im Oktober dieses Jahres haben wir auf Tags umgestellt. Tags wurden vor, aber nach der Veröffentlichung und Fusion von rc mit master gesetzt. Jetzt führt das Erscheinungsbild des Tags zu einer automatischen Bereitstellung, und das Einfrieren ist eine Verschmelzung der Entwicklung zum Master.
Also haben wir zusätzliche Entitäten in Git und Variablen im Prozess entfernt.
Jetzt ziehen wir Projekte, die im Prozess zurückbleiben, auf einen ähnlichen Workflow.
Fazit
Die Automatisierung von Prozessen, deren Optimierung sowie Entwicklung ist eine ständige Angelegenheit: Solange sich das Produkt aktiv entwickelt und das Team arbeitet, gibt es entsprechende Aufgaben. Es erscheinen neue Ideen, wie Routinemaßnahmen beseitigt werden können: Funktionen sind in gitlab-ci implementiert.
Wenn Anwendungen wachsen, dauern CI-Prozesse unannehmbar lange - es ist Zeit, an ihrer Leistung zu arbeiten. Da Ansätze und Tools veraltet sind, müssen Sie sich Zeit nehmen, um sie umzugestalten, zu überprüfen und zu aktualisieren.
