
Mein Name ist Dmitrij Sugrobov, ich bin Entwickler bei âLeroy Merlinâ. In diesem Artikel werde ich erlĂ€utern, warum Helm notwendig ist, wie es die Arbeit mit Kubernetes vereinfacht, was sich in der dritten Version geĂ€ndert hat und wie man damit Anwendungen in der Produktion ohne Ausfallzeiten aktualisieren kann.
Dies ist eine Zusammenfassung basierend auf einem Vortrag auf der Konferenz indem â Wenn Sie nicht lesen möchten, schauen Sie sich das Video an.

Warum wir Kubernetes in der Produktion verwenden
âLeroy Merlinâ ist fĂŒhrend im DIY-Einzelhandel in Russland und Europa. In unserem Unternehmen sind ĂŒber einhundert Entwickler tĂ€tig, 33.000 interne Mitarbeiter und eine riesige Anzahl von Menschen, die unsere BaumĂ€rkte und unsere Website besuchen. Um sie alle glĂŒcklich zu machen, haben wir beschlossen, uns an standardisierte AnsĂ€tze in der Branche zu halten. Neue Anwendungen entwickeln wir unter Verwendung einer Mikroservices-Architektur; zur Isolierung von Umgebungen und zur korrekten Bereitstellung verwenden wir Container; und zur Orchestrierung setzen wir Kubernetes ein. Die Kosten fĂŒr die Nutzung von Orchestratoren sinken schnell: Die Anzahl der Ingenieure, die mit der Technologie vertraut sind, wĂ€chst auf dem Markt, und es kommen Anbieter hinzu, die Kubernetes als Service anbieten.
Alles, was Kubernetes tut, kann selbstverstĂ€ndlich auch auf andere Weise erreicht werden, zum Beispiel indem man ein Skript fĂŒr Jenkins und docker-compose verwendet, aber warum das Leben komplizierter machen, wenn es eine fertige und zuverlĂ€ssige Lösung gibt? Deshalb sind wir zu Kubernetes gekommen und verwenden es seit einem Jahr in der Produktion. Aktuell haben wir vierundzwanzig Kubernetes-Cluster, der Ă€lteste davon ist ĂŒber ein Jahr alt und enthĂ€lt etwa zweihundert Pods.
Der Fluch einer Vielzahl von 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 sie an den Cluster. FĂŒr die nĂ€chste Anwendung schreiben wir dasselbe Paket von YAMLs, fĂŒr die dritte noch eins und so weiter. Wenn wir die Anzahl der Dokumente mit der Anzahl der Umgebungen multiplizieren, kommen wir bereits auf Hunderte von Dateien, und das ohne die dynamischen Umgebungen zu berĂŒcksichtigen.

Adam Reese, Hauptverantwortlicher fĂŒr Helm, fĂŒhrte den Begriff ââ ein, der so aussieht:
- Copy YAML â YAML-Datei kopieren.
- Paste YAML â sie einfĂŒgen.
- Fix Indents â EinrĂŒckungen korrigieren.
- Repeat â wiederholen.
Diese Methode ist zwar praktikabel, erfordert jedoch viele KopiervorgÀnge mit YAML-Dateien. Um diesen Zyklus zu Àndern, wurde Helm erfunden.
Was ist Helm
Erstens, Helm â Paketmanager, der hilft, die benötigten Programme zu finden und zu installieren. 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, Helm â Template-Engine, hilft, Dateien zu parametrisieren. Kommen wir zur Situation mit YAML-Dateien in Kubernetes zurĂŒck. Es ist einfacher, die gleiche YAML-Datei zu schreiben, einige Platzhalter hinzuzufĂŒgen, die Helm mit Werten fĂŒllt. Das heiĂt, anstelle eines groĂen Satzes von YAML-Dateien gibt es eine Sammlung von Vorlagen, in die die benötigten Werte zu gegebener Zeit eingesetzt werden.
Drittens, Helm â Master fĂŒr die Bereitstellung. Mit ihm kann man Anwendungen installieren, zurĂŒcksetzen und aktualisieren. Lassen Sie uns anschauen, wie das funktioniert.

So verwenden Sie Helm fĂŒr die Bereitstellung eigener Anwendungen
Wir installieren den Helm-Client auf dem Computer, indem wir der offiziellen . Dann erstellen wir eine Sammlung von YAML-Dateien. Anstatt konkrete Werte anzugeben, lassen wir Platzhalter, die spĂ€ter von Helm mit Informationen gefĂŒllt werden. Diese Sammlung von Dateien nennt man Helm Chart. Man kann sie auf drei Arten an den Konsolen-Client von Helm senden:
- einen Ordner mit Vorlagen angeben;
- in ein .tar-Archiv packen und darauf verweisen;
- die Vorlage in ein entferntes Repository legen und einen Link zum Repository im Helm-Client hinzufĂŒgen.
AuĂerdem wird eine Datei mit Werten benötigt â values.yaml. Die Daten daraus werden im Template eingesetzt. Lassen Sie uns auch diese erstellen.

In der zweiten Version von Helm gibt es eine zusĂ€tzliche Serveranwendung â Tiller. Sie hĂ€ngt auĂerhalb von Kubernetes und wartet auf Anfragen vom Helm-Client, und bei einem Aufruf setzt sie die benötigten Werte in das Template ein und sendet es an Kubernetes.

Helm 3 ist einfacher aufgebaut: Anstatt die Templates auf dem Server zu verarbeiten, wird die Information jetzt vollstÀndig auf der Seite des Helm-Clients verarbeitet und direkt an die Kubernetes API gesendet. Diese Vereinfachung erhöht die Sicherheit des Clusters und erleichtert das Rollout.
Wie das alles funktioniert
Wir fĂŒhren den Befehl aus helm install. Wir geben den Namen der Anwendungs-Release an, geben den Pfad zu values.yaml an. Am Ende geben wir das Repository an, in dem das Chart liegt, und den Namen des Charts. Im 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 Wiederholung wird stattdessen install sollte benutzt werden upgrade. Zur Vereinfachung kann man anstelle von zwei Befehlen den Befehl upgrade mit dem zusĂ€tzlichen SchlĂŒssel --install. Bei der ersten AusfĂŒhrung wird Helm den Befehl zum Installieren des Releases senden und wird ihn in der Folge aktualisieren.
helm upgrade --install bestapp --values values.yaml lmru/bestchart
Fallstricke beim Deployen neuer Versionen der Anwendung mit Helm
An dieser Stelle der ErzÀhlung spiele ich mit dem Saal in 'Wer wird MillionÀr?', und wir klÀren, wie man Helm dazu bringt, die Version der Anwendung zu aktualisieren. .
Als ich die Funktionsweise von Helm studierte, war ich ĂŒber das merkwĂŒrdige Verhalten ĂŒberrascht, das auftrat, wenn ich versuchte, die Versionen von laufenden Anwendungen zu aktualisieren. Den Anwendungscode aktualisiert, ein neues Bild im Docker-Registry hochgeladen, den Befehl zum Deployen geschickt â und es passierte nichts. Unten sind einige nicht ganz erfolgreiche Methoden zum Aktualisieren von Anwendungen. Wenn man jede davon nĂ€her betrachtet, beginnt man, das innere Funktionieren des Werkzeugs und die GrĂŒnde fĂŒr solch unerwartetes Verhalten zu verstehen.
Methode 1. Keine Informationen seit dem letzten Start Àndern
Wie es heiĂt Helm, 'Kubernetes-Charts können groĂ und komplex sein, daher versucht Helm, nicht unnötig einzugreifen'. Daher wird beim Aktualisieren der neuesten Version des Anwendungsbildes im Docker-Registry und ausfĂŒhren des Befehls helm upgrade, nichts passieren. Helm wird denken, dass sich nichts geĂ€ndert hat, und es ist nicht nötig, Kubernetes den Befehl zur Aktualisierung der Anwendung zu senden.
Hier und weiter wird das Tag 'latest' nur als Beispiel gezeigt. Beim Angabe dieses Tags wird Kubernetes das Bild jedes Mal aus dem Docker-Registry herunterladen, unabhĂ€ngig von der Einstellung 'imagePullPolicy'. Die Verwendung von 'latest' in der Produktion ist unerwĂŒnscht und kann Nebenwirkungen haben.
Methode 2. LABEL im Image aktualisieren
Wie im gleichen , 'Helm wird die Anwendung nur aktualisieren, wenn sie sich seit dem letzten Release geĂ€ndert hat'. Eine logische Option dafĂŒr wĂ€re die Aktualisierung des LABELs im Docker-Image selbst. Allerdings sieht Helm nicht in die Anwendungsbilder hinein und hat keine Ahnung von irgendwelchen Ănderungen darin. Dementsprechend, wenn LABELs im Bild aktualisiert werden, wird Helm nichts davon erfahren, und der Befehl zur Aktualisierung der Anwendung in Kubernetes wird nicht gesendet.
Methode 3. Den SchlĂŒssel verwenden --force

Lass uns die HandbĂŒcher zu Rate ziehen und nach dem nötigen SchlĂŒssel suchen. Der SchlĂŒssel, der am meisten Sinn macht, ist die SchlĂŒsseloption. --force. Trotz des sprechenden Namens weicht das Verhalten von den Erwartungen ab. Statt ein erzwungenes Update der Anwendung durchzufĂŒhren, ist der eigentliche Zweck die Wiederherstellung einer im Status FAILED befindlichen Version. Wenn dieser SchlĂŒssel nicht verwendet wird, mĂŒssen die Befehle nacheinander ausgefĂŒhrt werden. helm delete && helm install --replace. Stattdessen wird vorgeschlagen, den SchlĂŒssel --force, der die abwechselnde AusfĂŒhrung dieser Befehle automatisiert, zu verwenden. Weitere Informationen finden Sie in diesem . Um Helm dennoch dazu zu bringen, die Version der Anwendung zu aktualisieren, ist leider dieser SchlĂŒssel nicht geeignet.
Methode 4. Labels direkt in Kubernetes Àndern

Das direkte Update des Labels im Cluster mit dem Befehl kubectl edit ist keine gute Idee. Diese Aktion fĂŒhrt zu Inkonsistenzen zwischen der laufenden Anwendung und dem, was ursprĂŒnglich zur Bereitstellung gesendet wurde. Das Verhalten von Helm bei der Bereitstellung weicht in diesem Fall von seiner Version ab: Helm 2 wird nichts tun, wĂ€hrend Helm 3 die neue Version der Anwendung bereitstellt. Um die GrĂŒnde zu verstehen, ist es notwendig zu wissen, wie Helm funktioniert.
Wie Helm funktioniert
Um festzustellen, ob sich die Anwendung seit dem letzten Release geĂ€ndert hat, kann Helm auf Folgendes zurĂŒckgreifen:
- die laufende Anwendung in Kubernetes;
- neue values.yaml und aktuelles Chart;
- interne Informationen von Helm ĂŒber Releases.
FĂŒr die Neugierigen: Wo speichert Helm die internen Informationen ĂŒber Releases?Durch den Befehl helm history, erhalten wir alle Informationen ĂŒber die Versionen, die mit Helm installiert wurden.

Es gibt auch detaillierte Informationen zu den gesendeten Vorlagen 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), in einer ConfigMap, die mit dem Label âOWNER=TILLERâ gekennzeichnet ist:

Mit dem Erscheinen der dritten Version von Helm wurden die Informationen in Secrets verschoben, und zwar in denselben Namespace, in dem die Anwendung lĂ€uft. Dadurch wurde es möglich, mehrere Anwendungen in verschiedenen Namespaces mit demselben Release-Namen gleichzeitig auszufĂŒhren. In der zweiten Version war dies ein groĂes Problem, da Namespaces isoliert sind, aber sich gegenseitig beeinflussen können.

Die zweite Version von Helm verwendet bei der ĂberprĂŒfung, ob ein Update erforderlich ist, nur zwei Informationsquellen: das, was ihr jetzt bereitgestellt wurde, und die internen Informationen ĂŒber die Releases, die in der ConfigMap gespeichert sind.

Der dritte Helm verwendet die Strategie des Three-Way-Merge: ZusĂ€tzlich zu den vorhandenen Informationen berĂŒcksichtigt er auch die Anwendung, die gerade in Kubernetes lĂ€uft.

Aus diesem Grund wird die alte Version von Helm nichts tun, da sie die Informationen der Anwendung im Cluster nicht berĂŒcksichtigt, wĂ€hrend Helm 3 Ănderungen erhĂ€lt und die neue Anwendung fĂŒr das Deployment sendet.
Methode 5. Verwenden Sie den SchlĂŒssel ârecreate-pods
Mit dem SchlĂŒssel --recreate-pods kann das erreicht werden, was ursprĂŒnglich mit dem SchlĂŒssel geplant war. --forceDie Container werden neu gestartet und, gemÀà der Policy imagePullPolicy: Always fĂŒr das Tag latest (darĂŒber in der FuĂnote oben), wird Kubernetes die neue Version des Images herunterladen und starten. Das geschieht nicht auf die beste Art: Ohne BerĂŒcksichtigung des StrategyType des Deployments schaltet es abrupt alle alten Instanzen der Anwendung ab und beginnt, neue zu starten. WĂ€hrend des Neustarts wird das System nicht funktionieren, und die Benutzer werden darunter leiden.
Auch im Kubernetes selbst gab es dieses Problem lange Zeit. Und nach 4 Jahren seit der Entdeckung , wurde das Problem behoben, und seit Version 1.15 von Kubernetes gibt es die Möglichkeit, diese Pods rolling-restart.
Helm schaltet einfach alle Anwendungen aus und startet daneben neue Container. Das sollte in der Produktion nicht gemacht werden, um einen Stillstand der Anwendung zu vermeiden. Das ist nur fĂŒr Entwicklungszwecke notwendig und kann nur in Stage-Umgebungen durchgefĂŒhrt werden.
Wie aktualisiere ich die Version der Anwendung mit Helm?
Wir werden die Werte Ă€ndern, die an Helm gesendet werden. In der Regel sind dies die Werte, die anstelle des Tags des Images eingesetzt werden. Im Fall von latest, das hĂ€ufig fĂŒr nicht produktive Umgebungen verwendet wird, ist die zu Ă€ndernde Information die Annotation, die fĂŒr Kubernetes nutzlos ist, aber fĂŒr Helm ein Signal zum Aktualisieren der Anwendung darstellt. Möglichkeiten zur AusfĂŒllung des Wertes der Annotation:
- ZufĂ€lliger Wert mithilfe der Standardfunktion â
{{ randAlphaNum 6 }}.
Es gibt einen Schönheitsfehler: Nach jedem Deployment mit einem Chart, der solch eine Variable enthĂ€lt, wird der Wert der Annotation einzigartig sein, und Helm wird annehmen, dass es Ănderungen gibt. Das bedeutet, wir werden die Anwendung immer neu starten, auch wenn wir ihre Version nicht geĂ€ndert haben. Das ist nicht kritisch, da es keine StillstĂ€nde geben wird, aber dennoch unangenehm. - Aktuelles Datum und Uhrzeit â
{{ .Release.Date }}.
Die Variante Ă€hnelt dem zufĂ€lligen Wert mit einer stĂ€ndig einzigartigen Variablen. - Eine bessere Methode ist die Verwendung von PrĂŒfziffern. Das ist der SHA des Images oder der SHA des letzten Commits in Git â
{{ .Values.sha }}.
Diese mĂŒssen berechnet und an den Helm-Client auf der aufrufenden Seite gesendet werden, zum Beispiel in Jenkins. Wenn sich die Anwendung Ă€ndert, Ă€ndert sich auch die PrĂŒfziffer. Folglich wird Helm die Anwendung nur dann aktualisieren, wenn es nötig ist.
Fassen wir unsere Versuche zusammen
- Helm nimmt Ănderungen auf die am wenigsten invasive Weise vor, daher fĂŒhrt jede Ănderung auf der Ebene des Anwendungsimages im Docker Registry nicht zu einem Update: Nach AusfĂŒhrung des Befehls passiert nichts.
- SchlĂŒssel
--forcewird zur Wiederherstellung problematischer Releases verwendet und steht nicht im Zusammenhang mit einem erzwungenen Update. - SchlĂŒssel
--recreate-podserzwingt die Aktualisierung von Anwendungen, tut dies jedoch auf eine gewaltsame Weise: Es schaltet abrupt alle Container aus. Davon leiden die Benutzer, im produktiven Betrieb sollte man das nicht tun. - Direkt Ănderungen am Kubernetes-Cluster mit dem Befehl
kubectl editsind nicht erforderlich: Wir wĂŒrden die Konsistenz verletzen, und das Verhalten wĂ€re von der Helm-Version abhĂ€ngig. - Mit der neuen Version von Helm sind viele Nuancen hinzugekommen. Die Issues im Helm-Repository sind in verstĂ€ndlicher Sprache beschrieben und helfen, die Details zu verstehen.
- Durch das HinzufĂŒgen einer verĂ€nderbaren Annotation zum Chart wird es flexibler. Dadurch kann die Anwendung richtig ausgerollt werden, ohne Ausfallzeiten.
Ein Gedanke, der in allen Lebensbereichen funktioniert: Lesen Sie die Anleitung vor der Anwendung und nicht danach. Nur mit vollstĂ€ndigen Informationen lassen sich zuverlĂ€ssige Systeme aufbauen und die Benutzer glĂŒcklich machen.
Weitere Links zum Thema:
Dieser Bericht wurde erstmals auf von Mail.ru Cloud Solutions. Sehen Sie weitere VortrĂ€ge und abonnieren Sie die AnkĂŒndigungen von Veranstaltungen auf Telegram .
Quelle: habr.com
