
Mein Name ist Dmitrij Sugrobov, ich bin Entwickler bei âLeroy Merlinâ. In diesem Artikel erlĂ€utere ich, warum Helm nötig ist, wie er die Arbeit mit Kubernetes erleichtert, was sich in der dritten Version geĂ€ndert hat und wie man mit seiner Hilfe Anwendungen im Produktionsumfeld ohne Ausfallzeit aktualisieren kann.
Dies ist eine Zusammenfassung basierend auf einem Vortrag auf einer Konferenz by â wenn Sie nicht lesen möchten, schauen Sie sich das Video an.

Warum wir Kubernetes in der Produktion verwenden
âLeroy Merlinâ ist ein fĂŒhrendes Unternehmen im DIY-Einzelhandel in Russland und Europa. In unserer Firma gibt es mehr als einhundert Entwickler, 33.000 interne Mitarbeiter und eine riesige Anzahl von Menschen, die unsere BaumĂ€rkte und unsere Website besuchen. Um alle glĂŒcklich zu machen, haben wir uns entschieden, uns an gĂ€ngige Standards der Branche zu halten. Wir entwickeln neue Anwendungen unter Verwendung einer Microservices-Architektur; zur Isolierung von Umgebungen und fĂŒr die korrekte Bereitstellung nutzen wir Container; und fĂŒr die Orchestrierung verwenden wir Kubernetes. Die Kosten fĂŒr den Einsatz von Orchestratoren sinken rasant: Die Anzahl der Ingenieure, die mit der Technologie vertraut sind, steigt, und es entstehen Anbieter, die Kubernetes als Service anbieten.
Alles, was Kubernetes tut, kann natĂŒrlich auch auf andere Weise erledigt werden, zum Beispiel indem man mit Skripten einen Jenkins und docker-compose aufsetzt. Aber warum das Leben komplizierter machen, wenn es eine fertige und zuverlĂ€ssige Lösung gibt? Daher haben wir uns fĂŒr Kubernetes entschieden und nutzen es nun seit einem Jahr in der Produktion. Momentan betreiben wir vierundzwanzig Kubernetes-Cluster, der Ă€lteste hat ĂŒber ein Jahr auf dem Buckel und umfasst etwa zweihundert Pods.
Das Fluch der vielen YAML-Dateien in Kubernetes
Um einen Mikroservice in Kubernetes zu starten, erstellen wir mindestens fĂŒnf YAML-Dateien: fĂŒr Deployment, Service, Ingress, ConfigMap, Secrets â und senden diese in den Cluster. FĂŒr die nĂ€chste Anwendung wiederholen wir diesen YAML-Satz, und mit der dritten â nochmals einen und so weiter. Multiplizieren wir die Anzahl der Dokumente mit der Anzahl der Umgebungen, haben wir bereits Hunderte von Dateien, ganz zu schweigen von dynamischen Umgebungen.

Adam Reese, Hauptverantwortlicher fĂŒr Helm, hat den Begriff ââ, der so aussieht:
- Copy YAML â YAML-Datei kopieren.
- Paste YAML â einfĂŒgen.
- Fix Indents â EinrĂŒckungen reparieren.
- Repeat â erneut wiederholen.
Das ist ein funktionierender Ansatz, aber man muss die YAML-Dateien oft mehrfach kopieren. Um diesen Zyklus zu Àndern, wurde Helm entwickelt.
Was ist Helm?
ZunĂ€chst einmal ist Helm â von KISS ist in Shell geschrieben und umfasst etwa 500 Zeilen Code. Alle Pakete werden aus Quelltexten erstellt. Die AbhĂ€ngigkeiten werden berĂŒcksichtigt und zusĂ€tzliche Patches können angewendet werden., der bei der Suche und Installation der benötigten Programme hilft. Um zum Beispiel MongoDB zu installieren, muss man nicht auf die offizielle Website gehen und die BinĂ€rdateien herunterladen, es genĂŒgt, den Befehl auszufĂŒhren. helm install stable/mongodb.
Zweitens ist Helm â ein Template-Manager, der hilft, Dateien zu parametrisieren. ZurĂŒck zu den YAML-Dateien in Kubernetes. Es ist einfacher, dieselbe YAML-Datei zu schreiben und einige Platzhalter hinzuzufĂŒgen, die Helm mit Werten ausfĂŒllt. Anstatt einer groĂen Anzahl von YAML-Dateien gibt es also eine Sammlung von Templates, in die zur passenden Zeit die benötigten Werte eingesetzt werden.
Drittens ist Helm â der Meister des Deployments. Damit können Anwendungen installiert, zurĂŒckgerollt und aktualisiert werden. Lass uns anschauen, wie das gemacht wird.

Wie man Helm zur Bereitstellung eigener Anwendungen nutzt
Wir installieren den Helm-Client auf dem Computer, indem wir der offiziellen Anleitung folgen. . AnschlieĂend erstellen wir eine Sammlung von YAML-Dateien. Anstatt spezifische Werte anzugeben, lassen wir Platzhalter, die Helm spĂ€ter mit Informationen fĂŒllen wird. Diese Sammlung von Dateien wird als Helm Chart bezeichnet. Es gibt drei Möglichkeiten, sie an den Helm-Konsolen-Client zu ĂŒbermitteln:
- ein Verzeichnis mit Templates angeben;
- in einer .tar-Archive packen und darauf verweisen;
- Legen Sie die Vorlage in ein entferntes Repository und fĂŒgen Sie den Link zum Repository im Helm-Client hinzu.
AuĂerdem wird eine Datei mit Werten benötigt â values.yaml. Die Daten daraus werden in die Vorlage eingesetzt. Lassen Sie uns auch diese erstellen.

In der zweiten Version von Helm gibt es eine zusĂ€tzliche Serveranwendung â Tiller. Diese lĂ€uft auĂerhalb von Kubernetes und wartet auf Anfragen vom Helm-Client, um beim Aufruf die erforderlichen Werte in die Vorlage einzusetzen und an Kubernetes zu senden.

Helm 3 ist einfacher strukturiert: Anstatt die Vorlagen auf dem Server zu verarbeiten, wird die gesamte Information jetzt direkt auf der Seite des Helm-Clients verarbeitet und direkt an die Kubernetes-API gesendet. Diese Vereinfachung erhöht die Sicherheit des Clusters und erleichtert den Rollout-Prozess.
So funktioniert das alles
Wir starten den Befehl helm install. Wir geben den Namen der Anwendungsbereitstellung an und den Pfad zur values.yaml. Am Ende geben wir das Repository an, das das Chart enthĂ€lt, sowie den Namen des Charts. In diesem Beispiel sind das âlmruâ und âbestchartâ.
helm install --name bestapp --values values.yaml lmru/bestchart
Die AusfĂŒhrung des Befehls ist nur einmal möglich; bei einer erneuten AusfĂŒhrung muss install verwendet werden. upgradeUm es einfacher zu machen, kann der Befehl upgrade mit dem zusĂ€tzlichen SchlĂŒssel --install. Bei der ersten AusfĂŒhrung sendet Helm den Befehl zur Installation des Releases und wird es fortan aktualisieren.
helm upgrade --install bestapp --values values.yaml lmru/bestchart
Herausforderungen beim Deployen neuer Versionen von Anwendungen mit Helm
An dieser Stelle des ErzĂ€hlens spiele ich mit dem Publikum in âWer wird MillionĂ€r?â und wir klĂ€ren, wie wir Helm dazu bringen, die Version der Anwendung zu aktualisieren. .
Als ich die Funktionsweise von Helm studierte, war ich ĂŒber das seltsame Verhalten erstaunt, als ich versuchte, die Versionen laufender Anwendungen zu aktualisieren. Ich hatte den Anwendungscode aktualisiert, ein neues Image im Docker-Registry hochgeladen, den Befehl zum Deployen gesendet â und es passierte nichts. Nachfolgend einige weniger erfolgreiche Methoden zur Aktualisierung von Anwendungen. Wenn man jede von ihnen genauer betrachtet, versteht man die inneren Funktionsweisen des Tools und die GrĂŒnde fĂŒr dieses nicht offensichtliche Verhalten.
Methode 1. Keine Informationen seit dem letzten Start Àndern
Wie es heiĂt Helm: 'Kubernetes-Charts können groĂ und komplex sein, deshalb bemĂŒht sich Helm darum, nichts unnötig zu Ă€ndern.' Daher, wenn man die neueste Version des Anwendung-Images im Docker-Registry aktualisiert und den Befehl ausfĂŒhrt helm upgrade, dann passiert nichts. Helm wird denken, dass sich nichts geĂ€ndert hat, und es ist nicht notwendig, Kubernetes den Befehl zur Aktualisierung der Anwendung zu senden.
Der Tag latest wird hier und in der Folge nur als Beispiel angezeigt. Wenn dieser Tag angegeben ist, wird Kubernetes jedes Mal das Image aus dem Docker-Registry herunterladen, unabhĂ€ngig von der imagePullPolicy. Die Verwendung von latest in der Produktion ist unerwĂŒnscht und kann Nebenwirkungen verursachen.
Methode 2. LABEL im Image aktualisieren
Wie im selben , "Helm wird die Anwendung nur aktualisieren, wenn sie sich seit dem letzten Release geĂ€ndert hat." Eine logische Option dafĂŒr wĂ€re es, das LABEL im Docker-Image zu aktualisieren. Allerdings sieht Helm nicht in die Anwendungs-Images und hat keine Kenntnis ĂŒber Ănderungen daran. Daher wird Helm bei der Aktualisierung der Labels im Image nichts davon erfahren, und der Befehl zur Aktualisierung der Anwendung wird nicht an Kubernetes gesendet.
Methode 3. Den SchlĂŒssel --force

Schauen wir in die HandbĂŒcher und suchen nach dem passenden SchlĂŒssel. Am sinnvollsten scheint der SchlĂŒssel --force. Trotz des vielsagenden Namens verhĂ€lt sich das Ganze anders als erwartet. Anstelle eines erzwungenen Anwendungsupdates ist es tatsĂ€chlich dafĂŒr gedacht, eine fehlgeschlagene Veröffentlichung wiederherzustellen. Wenn dieser SchlĂŒssel nicht verwendet wird, mĂŒssen die Kommandos nacheinander ausgefĂŒhrt werden. helm delete && helm install --replace. Stattdessen wird empfohlen, den SchlĂŒssel --force, der das sequentielle AusfĂŒhren dieser Kommandos automatisiert, zu verwenden. Weitere Informationen finden Sie in diesem . Um Helm tatsĂ€chlich zu sagen, dass die Version der Anwendung aktualisiert werden soll, geeignet sich dieser SchlĂŒssel leider nicht.
Methode 4. Labels direkt in Kubernetes Àndern.

Die Aktualisierung von Labels direkt im Cluster mit dem Befehl kubectl edit ist eine schlechte Idee. Diese Aktion fĂŒhrt zu Inkonsistenzen zwischen der laufenden Anwendung und dem, was ursprĂŒnglich deployt wurde. Das Verhalten von Helm beim Deployment ist in diesem Fall anders als in der vorherigen Version: Helm 2 wird nichts tun, wĂ€hrend Helm 3 eine neue Version der Anwendung deployt. Um den Grund zu verstehen, muss man wissen, wie Helm funktioniert.
Wie Helm funktioniert
Um festzustellen, ob sich die Anwendung seit der letzten Veröffentlichung geÀndert hat, kann Helm Folgendes verwenden:
- laufenden Anwendung in Kubernetes;
- neuen values.yaml und dem aktuellen Chart;
- internen Helm-Informationen zu den Releases.
FĂŒr die Neugierigen: Wo speichert Helm die internen Informationen zu den Releases?FĂŒhren Sie den Befehl aus helm history, um alle Informationen zu den Versionen, die mit Helm installiert wurden, zu erhalten.

Es gibt auch detaillierte Informationen zu den ĂŒbermittelten Templates und Werten. Wir können sie anfordern:

In der zweiten Version von Helm befinden sich diese Informationen im selben Namespace, in dem Tiller lĂ€uft (standardmĂ€Ăig kube-system), im ConfigMap, das mit dem Tag âOWNER=TILLERâ versehen ist:

Mit dem Erscheinen der dritten Helm-Version sind die Informationen in Secrets umgezogen, und zwar in denselben Namespace, in dem die Anwendung lĂ€uft. Dadurch wurde es möglich, mehrere Anwendungen gleichzeitig in verschiedenen Namespaces mit demselben Release-Namen zu starten. In der zweiten Version war dies ein groĂes Kopfzerbrechen, da Namespaces isoliert sind, aber dennoch Einfluss aufeinander nehmen können.

Die zweite Helm-Version, wenn sie versucht zu verstehen, ob ein Update erforderlich ist, verwendet nur zwei Informationsquellen: das, was ihr gerade bereitgestellt wurde, und die internen Informationen zu den Releases, die im ConfigMap liegen.

Die dritte Version von Helm verwendet eine Strategie des Three-Way-Merge: ZusĂ€tzlich zu den vorhandenen Informationen wird auch die Anwendung berĂŒcksichtigt, die aktuell in Kubernetes lĂ€uft.

Aus diesem Grund wird die alte Version von Helm nichts unternehmen, da sie die Informationen ĂŒber die Anwendung im Cluster nicht berĂŒcksichtigt. Helm 3 hingegen wird die Ănderungen erfassen und die neue Anwendung bereitstellen.
Methode 5. Verwenden des SchlĂŒssels ârecreate-pods
Mit dem SchlĂŒssel --recreate-pods kann das erreicht werden, was ursprĂŒnglich mit dem SchlĂŒssel --forcegeplant war. Die Container werden neu gestartet und, gemÀà der Richtlinie imagePullPolicy: Always fĂŒr das Tag latest (siehe Anmerkung oben), wird Kubernetes die neue Version des Images herunterladen und starten. Dies geschieht jedoch nicht optimal: UnabhĂ€ngig vom StrategyType des Deployments werden abrupt alle alten Instanzen der Anwendung abgeschaltet und neue gestartet. WĂ€hrend des Neustarts wird das System nicht funktionieren, und die Benutzer werden betroffen sein.
Ein Ă€hnliches Problem bestand auch in Kubernetes ĂŒber einen lĂ€ngeren Zeitraum. Und nun, vier Jahre nach der Entdeckung , wurde das Problem behoben, und seit Version 1.15 von Kubernetes gibt es die Möglichkeit, Pods rolling-neu zu starten.
Helm schaltet einfach alle Anwendungen aus und startet daneben neue Container. Das sollte in der Produktion nicht gemacht werden, um keine Ausfallzeiten der Anwendung zu verursachen. Das ist nur fĂŒr Entwicklungszwecke notwendig und sollte ausschlieĂlich in Staging-Umgebungen durchgefĂŒhrt werden.
Wie aktualisiere ich die Version einer Anwendung mit Helm?
Wir werden die Werte Ă€ndern, die an Helm ĂŒbergeben werden. In der Regel sind das die Werte, die anstelle des Image-Tags eingesetzt werden. Bei 'latest', das hĂ€ufig in nicht-produktiven Umgebungen verwendet wird, ist die zu Ă€ndernde Information die Annotation, die fĂŒr Kubernetes selbst nutzlos ist, aber fĂŒr Helm als Signal zur Notwendigkeit der Aktualisierung der Anwendung dient. Optionen zur AusfĂŒllung des Wertes der Annotation:
- ZufĂ€lliger Wert mit der Standardfunktion â
{{ randAlphaNum 6 }}.
Es gibt einen Haken: Nach jedem Deployment mit einem Chart, das eine solche Variable enthĂ€lt, wird der Wert der Annotation einzigartig sein, und Helm wird annehmen, dass Ănderungen vorliegen. Das heiĂt, wir werden die Anwendung immer neu starten, auch wenn wir ihre Version nicht geĂ€ndert haben. Das ist nicht kritisch, da es keine Ausfallzeiten geben wird, aber dennoch unangenehm. - Aktuelles Datum und Uhrzeit â
{{ .Release.Date }}.
Die Option Ă€hnelt einem zufĂ€lligen Wert mit einer stĂ€ndig einzigartigen Variable. - Der richtigere Weg ist, PrĂŒfziffern. Dies ist der SHA des Images oder der SHA des letzten Commits im Git â
{{ .Values.sha }}.
Sie mĂŒssen berechnet und an den Helm-Client auf der aufrufenden Seite gesendet werden, beispielsweise in Jenkins. Wenn sich die Anwendung Ă€ndert, Ă€ndert sich auch die PrĂŒfziffer. Daher wird Helm die Anwendung nur dann aktualisieren, wenn es notwendig ist.
Fassen wir unsere Versuche zusammen.
- Helm fĂŒhrt Ănderungen auf die am wenigsten invasive Weise durch, weshalb jede Ănderung auf der Ebene des Anwendungs-Images im Docker-Registry nicht zu einem Update fĂŒhrt: Nach der AusfĂŒhrung des Befehls passiert nichts.
- Der SchlĂŒssel
--forcewird verwendet, um problematische Releases wiederherzustellen und steht nicht im Zusammenhang mit einem erzwungenen Update. - Der SchlĂŒssel
--recreate-podswird die Anwendungen gezwungen aktualisieren, aber auf vandalistische Weise: Alle Container werden abrupt abgeschaltet. Dies wird den Benutzern schaden; so sollte man das in der Produktion nicht machen. - Ănderungen direkt am Kubernetes-Cluster durchzufĂŒhren mit dem Befehl
kubectl editsollte man nicht: wir wĂŒrden die Konsistenz verletzen, und das Verhalten wĂŒrde je nach Helm-Version variieren. - Mit der neuen Version von Helm sind viele Nuancen aufgetreten. Die Probleme im Helm-Repository sind klar beschrieben und helfen, die Details zu verstehen.
- Das HinzufĂŒgen einer verĂ€nderbaren Annotation zum Chart macht es flexibler. Dadurch kann die Anwendung korrekt ausgerollt werden, ohne Ausfallzeiten.
Ein Gedanke, der in allen Lebensbereichen gilt: Lesen Sie die Anleitung vor der Anwendung, nicht danach. Nur mit vollstĂ€ndigen Informationen können zuverlĂ€ssige Systeme aufgebaut und die Nutzer glĂŒcklich gemacht werden.
Weitere Links zum Thema:
Dieser Vortrag wurde erstmals gehalten auf von Mail.ru Cloud Solutions. Sehen Sie sich an anderer VortrÀge an und abonnieren Sie die Veranstaltungshinweise auf Telegram. .
Quelle: habr.com
