In Tscheljabinsk finden die Treffen der Sysadminka-Systemadministratoren statt, und zuletzt habe ich einen Bericht über unsere Lösung für funktionierende Anwendungen auf 1C-Bitrix in Kubernetes erstellt.
Bitrix, Kubernetes, Ceph - eine tolle Mischung?
Ich werde Ihnen sagen, wie wir aus all dem eine funktionierende Lösung zusammenstellen.
Lass uns gehen!

Mitap fand am 18. April in Tscheljabinsk statt. Sie können über unsere Mitaps im Timepad lesen und auf YouTube ansehen.
Wenn Sie mit einem Bericht oder als Zuhörer zu uns kommen möchten - an Wellcome, schreiben Sie an vadim.isakanov@gmail.com und an Telegram t.me/vadimisakanov.
Mein Bericht

Folien
Bitrix in Kubernetes Southbridge 1.0-Lösung
Ich werde über unsere Lösung im Format "für Dummies in Kubernetes" sprechen, wie es auf dem Treffen getan wurde. Aber ich nehme an, dass Ihnen die Wörter Bitrix, Docker, Kubernetes, Ceph zumindest auf der Ebene von Wikipedia-Artikeln bekannt sind.
Was haben Sie über Bitrix in Kubernetes?
Überall im Internet gibt es nur sehr wenige Informationen über den Betrieb von Anwendungen unter Bitrix in Kubernetes.
Ich habe nur solche Materialien gefunden:
Bericht von Alexander Serbul, 1C-Bitrix und Anton Tuzlukov von Qsoft:
Ich empfehle es anzuhören.
Entwicklung einer eigenen Lösung vom Anwender serkyron auf Habré .
Ich habe auch eine solche Lösung gefunden .
III ... eigentlich.
Ich warne Sie, wir haben die Qualität der Lösungen nicht über die obigen Links überprüft :-)
Übrigens, als ich unsere Lösung vorbereitete, habe ich mit Alexander Serbul gesprochen, dann war sein Bericht noch nicht, also gibt es auf meinen Folien den Punkt „Bitrix verwendet keine Kubernetes“.
Es gibt jedoch bereits viele vorgefertigte Docker-Images, die Bitrix in Docker verwenden kann: https://hub.docker.com/search?q=bitrix&type=image
Reicht dies aus, um eine vollständige Bitrix-Lösung in Kubernetes zu erstellen?
Nein. Es gibt eine große Anzahl von Problemen, die angegangen werden müssen.
Was sind die Probleme mit Bitrix in Kubernetes?
Erstens - Dockerhub-fertige Bilder sind nicht für Kubernetes geeignet
Wenn wir eine Microservice-Architektur erstellen möchten (und in Kubernetes normalerweise), muss die Anwendung in Kubernetes in Container unterteilt werden und sicherstellen, dass jeder Container eine kleine Funktion ausführt (und dies gut macht). Warum nur einer? Kurz gesagt - je einfacher, desto zuverlässiger.
Wenn es authentischer ist, schauen Sie sich diesen Artikel und das Video an: https://habr.com/en/company/southbridge/blog/426637/
Docker-Bilder in Dockerhub basieren hauptsächlich auf dem Prinzip "All in One", daher mussten wir immer noch unser eigenes Fahrrad bauen und sogar Bilder von Grund auf neu erstellen.
Zweitens: Der Site-Code wird im Admin-Bereich bearbeitet
Wir haben einen neuen Abschnitt auf der Site erstellt - der Code wurde aktualisiert (ein Verzeichnis mit dem Namen des neuen Abschnitts wurde hinzugefügt).
Die Komponenteneigenschaften im Admin-Bereich wurden geändert. Der Code wurde geändert.
Kubernetes "standardmäßig" weiß nicht, wie man damit arbeitet, Container müssen zustandslos sein.
Grund: Jeder Container (Sub) im Cluster verarbeitet nur einen Teil des Datenverkehrs. Wenn Sie den Code nur in einem Container (unten) ändern, ist der Code in verschiedenen Pods unterschiedlich, die Site funktioniert anders, verschiedene Versionen der Site werden verschiedenen Benutzern angezeigt. So kannst du nicht leben.
Drittens müssen Sie das Problem der Bereitstellung lösen
Wenn wir einen Monolithen und einen „klassischen“ Server haben, ist alles sehr einfach: Wir stellen eine neue Codebasis bereit, migrieren die Datenbank und schalten den Datenverkehr auf die neue Version des Codes um. Das Umschalten erfolgt sofort.
Wenn wir eine Website in Kubernetes haben, wird sie in Microservices zersägt, es gibt viele Container mit Code. Sie müssen Container mit der neuen Version des Codes sammeln, sie anstelle der alten ausrollen, die Datenbankmigration korrekt ausführen und dies im Idealfall unsichtbar für Besucher tun. Glücklicherweise hilft uns Kubernetes dabei und unterstützt eine ganze Cloud mit verschiedenen Arten der Bereitstellung.
Viertens - Sie müssen das Problem der statischen Speicherung lösen
Wenn Ihre Site „nur“ 10 Gigabyte wiegt und Sie sie vollständig in Containern bereitstellen, erhalten Sie Container mit einem Gewicht von 10 Gigabyte, die für immer bereitgestellt werden.
Sie müssen die „schwersten“ Teile der Baustelle außerhalb von Containern lagern, und es stellt sich die Frage, wie Sie es richtig machen können
Was ist nicht in unserer Entscheidung
Der gesamte Bitrix-Code für Mikrofunktionen / Microservices wird nicht abgeschnitten (so dass die Registrierung separat ist, das Modul des Online-Shops separat ist usw.). Wir speichern die gesamte Codebasis in jedem Container als Ganzes.
Wir speichern die Basis auch nicht in Kubernetes (ich habe dennoch Lösungen mit der Basis in Kubernetes für Entwicklerumgebungen implementiert, aber nicht für die Produktion).
Site-Administratoren werden weiterhin feststellen, dass die Site in Kubernetes funktioniert. Die Funktion "Systemprüfung" funktioniert nicht ordnungsgemäß. Um den Site-Code im Admin-Bereich zu bearbeiten, müssen Sie zuerst auf die Schaltfläche "Ich möchte den Code bearbeiten" klicken.
Wir haben uns für die Probleme entschieden, wir haben uns für die Notwendigkeit entschieden, Microservice zu implementieren. Das Ziel ist klar: ein funktionierendes System für die Arbeit an Bitrix-Anwendungen in Kubernetes zu erhalten, wobei sowohl die Bitrix-Funktionen als auch die Vorteile von Kubernetes erhalten bleiben. Wir beginnen mit der Implementierung.
Architektur
Viele "funktionierende" Herde mit einem Webserver (Arbeiter).
Eine unter mit Kronen (unbedingt nur eine).
Ein Upgrade zum Bearbeiten des Site-Codes über das Admin-Panel (nur eines ist ebenfalls erforderlich).

Wir lösen Probleme:
- Wo können Sitzungen gespeichert werden?
- Wo soll der Cache gespeichert werden?
- Wo kann man Statik speichern und nicht Gigabyte Statik in einen Haufen Container legen?
- Wie funktioniert die Datenbank?
Docker-Bild
Wir beginnen mit der Erstellung eines Docker-Images.
Die ideale Option ist, dass wir ein universelles Image haben. Auf dieser Basis erhalten wir sowohl Worker-Pods als auch Pods mit Klammern und Upgrade-Pods.
Wir haben genau so ein Bild gemacht .
Es enthält nginx, apache / php-fpm (kann während der Montage ausgewählt werden), msmtp zum Senden von E-Mails und cron.
Beim Zusammenstellen des Images wird die vollständige Codebasis der Site in das Verzeichnis / app kopiert (mit Ausnahme der Teile, die wir in einem separaten gemeinsam genutzten Speicher ablegen).
Microservice, Dienstleistungen
Arbeiterherde:
- Container mit nginx + apache / php-fpm + msmtp container
- msmtp hat in einem separaten Microservice nicht funktioniert. Bitrix beginnt erneut zu senden, dass keine E-Mails direkt gesendet werden können
- Jeder Container verfügt über eine vollständige Codebasis.
- Verbot der Codeänderung in Containern.
cron unter:
- Behälter mit Apache, PHP, Cron
- komplette Codebasis enthalten
- Verbot der Codeänderung in Containern
Upgrade unter:
- Container mit nginx + apache / php-fpm + msmtp container
- Es gibt kein Verbot, Code in Containern zu ändern
Sitzungsspeicher
Bitrix Cache-Speicher
Wichtiger: Wir speichern Passwörter für die Verbindung zu allem, von der Datenbank bis zum Mailing, in Kubernetes-Geheimnissen. Wir erhalten einen Bonus. Passwörter sind nur für diejenigen sichtbar, denen wir Zugriff auf Geheimnisse gewähren, und nicht für alle, die Zugriff auf die Codebasis des Projekts haben.
Statische Speicherung
Sie können alles verwenden: ceph, nfs (aber nfs werden für die Produktion nicht empfohlen), Netzwerkspeicher von "Cloud" -Anbietern usw.
Der Speicher muss in Containern mit dem Verzeichnis / upload / der Site und anderen statischen Verzeichnissen verbunden werden.
Datenbank
Der Einfachheit halber empfehlen wir, die Basis außerhalb von Kubernetes zu verschieben. Die Basis in Kubernetes ist eine separate komplexe Aufgabe, die die Schaltung erheblich komplizierter macht.
Sitzungsspeicher
Wir verwenden memcached :)
Es macht einen guten Job beim Speichern von Sitzungen, Clustern und wird nativ als session.save_path in PHP unterstützt. Ein solches System wurde in der klassischen monolithischen Architektur viele Male ausgearbeitet, als wir Cluster mit einer großen Anzahl von Webservern erstellten. Für den Einsatz verwenden wir Helm.
$ helm install stable/memcached --name session
php.ini - hier in den Bildeinstellungen sind Sitzungen zum Speichern in Memcached festgelegt
Wir haben Umgebungsvariablen verwendet, um Hostdaten mit zwischengespeicherten https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/ zu übertragen .
Auf diese Weise können Sie denselben Code in den Umgebungen dev, stage, test, prod verwenden (die darin gespeicherten Hostnamen sind unterschiedlich, daher müssen wir für jede Umgebung einen eindeutigen Hostnamen für Sitzungen übertragen).
Bitrix Cache-Speicher
Wir brauchen einen ausfallsicheren Speicher, in den alle Herde schreiben und aus dem wir lesen können.
Wir verwenden auch memcached.
Diese Lösung wird von Bitrix selbst empfohlen.
$ helm install stable/memcached --name cache
bitrix / .settings_extra.php - hier in Bitrix wird festgelegt, wo der Cache gespeichert wird
Wir verwenden auch Umgebungsvariablen.
Krontaski
In Kubernetes gibt es verschiedene Ansätze für Crontabs.
- separater Einsatz mit Herd
- Cronjob zum Ausführen von Crontask (wenn es sich um eine Web-App handelt - mit wget https: // $ host $ cronjobname oder kubectl exec in einem der Worker-Herde usw.)
- usw.
Sie können über das Richtigste streiten, aber in diesem Fall haben wir die Option "Separate Bereitstellung mit Pods für Crontask" gewählt.
Wie es geht:
- Fügen Sie Kronen über ConfigMap oder über config / addcron hinzu
- Führen Sie in einem Fall einen Container aus, der mit dem Worker-Sub identisch ist, und ermöglichen Sie die Ausführung von Kronenaufgaben darin
- Es wird dieselbe Codebasis verwendet, dank der Vereinheitlichung ist die Montage des Containers einfach
Was nützen wir:
- Wir arbeiten mit Crontaski in einer Umgebung, die mit der Entwicklungsumgebung (Docker) identisch ist.
- Krontaski muss für Kubernetes nicht „umgeschrieben“ werden, sie arbeiten in derselben Form und in derselben Codebasis wie zuvor
- Kronenmitglieder können alle Teammitglieder mit Festschreibungsrechten zur Produktionsabteilung hinzufügen und nicht nur Administratoren
Southbridge K8SDeploy-Modul und Bearbeiten von Code über das Admin-Panel
Wir sprachen über ein Upgrade unter?
Und wie lenkt man den Verkehr dorthin?
Hurra, wir haben ein Modul dafür in PHP geschrieben :) Dies ist ein kleines klassisches Modul für Bitrix. Es ist noch nicht öffentlich verfügbar, aber wir planen, es zu öffnen.
Das Modul wird als reguläres Modul in Bitrix installiert:

Und es sieht so aus:

Sie können ein Cookie setzen, das den Site-Administrator identifiziert und es Kubernetes ermöglicht, Datenverkehr zum Upgrade unter zu senden.
Wenn die Änderungen abgeschlossen sind, müssen Sie git push drücken. Die Codeänderungen werden an git gesendet. Anschließend sammelt das System das Image mit der neuen Version des Codes und „rollt“ es über den Cluster, wobei die alten Pods ersetzt werden.
Ja, es ist ein bisschen wie eine Krücke, aber gleichzeitig behalten wir die Microservice-Architektur bei und nehmen den Bitrix-Benutzern nicht die bevorzugte Gelegenheit, den Code im Admin-Bereich zu korrigieren. Am Ende ist dies eine Option, mit der Sie das Problem der Codebearbeitung auf andere Weise lösen können.
Helmkarte
Zum Erstellen von Anwendungen in Kubernetes verwenden wir normalerweise den Helm-Paketmanager.
Für unsere Bitrix-Lösung bei Kubernetes hat Sergey Bondarev, unser leitender Systemadministrator, ein spezielles Helm-Diagramm erstellt.
Es baut Worker-, Ugrade- und Cron-Herde auf, konfiguriert Eingriffe, Dienste und überträgt Variablen von Kubernetes-Geheimnissen auf Herde.
Wir speichern den Code in Gitlab und führen auch die Helm-Assembly von Gitlab aus.
Kurz gesagt, es sieht so aus
$ helm upgrade --install project .helm --set image=registrygitlab.local/k8s/bitrix -f .helm/values.yaml --wait --timeout 300 --debug --tiller-namespace=production
Mit Helm können Sie auch einen „nahtlosen“ Rollback durchführen, wenn während der Bereitstellung ein Fehler aufgetreten ist. Es ist schön, wenn Sie nicht in Panik sind: "Korrigieren Sie den Code für FTP, weil das Produkt gefallen ist", und Kubernetes tut dies automatisch, ohne Ausfallzeiten.
Bereitstellen
Ja, wir sind Fans von Gitlab & Gitlab CI, benutze es :)
Beim Festschreiben von Gitlab im Projekt-Repository startet Gitlab eine Pipeline, die die neue Version der Umgebung bereitstellt.
Stufen:
- erstellen (neues Docker-Image erstellen)
- Test (Test)
- aufräumen (Testumgebung entfernen)
- push (an die Docker-Registrierung senden)
- bereitstellen (wir stellen die Anwendung in Kubernetes über Helm bereit).

Hurra, wir sind bereit, es vorzustellen!
Nun, oder stellen Sie gegebenenfalls Fragen.
Also, was haben wir getan?
Aus technischer Sicht:
- dockerisierte Bitrix;
- Bitrix in Behälter „schneiden“, von denen jeder ein Minimum an Funktionen erfüllt;
- zustandslosen Zustand der Container erreicht;
- löste das Problem mit der Aktualisierung von Bitrix in Kubernetes;
- Alle Bitrix-Funktionen funktionierten weiterhin (fast alle).
- funktionierte Bereitstellung in Kubernetes und Rollback zwischen Versionen.
Aus geschäftlicher Sicht:
- Fehlertoleranz;
- Kubernetes-Tools (einfache Integration in Gitlab CI, nahtlose Bereitstellung usw.);
- Passwörter in Geheimnissen (nur für diejenigen sichtbar, denen direkt Zugriff auf Passwörter gewährt wird);
- Es ist praktisch, zusätzliche Umgebungen (für Entwicklung, Tests usw.) in einer einzigen Infrastruktur zu erstellen.