
Jag heter Dmitrij Sugrobov, jag Àr utvecklare pÄ "Leroy Merlin". I artikeln kommer jag att berÀtta varför Helm behövs, hur det förenklar arbetet med Kubernetes, vad som har förÀndrats i den tredje versionen och hur man uppdaterar applikationer i produktion utan driftstopp.
Detta Ă€r en sammanfattning baserad pĂ„ en presentation pĂ„ konferensen by â om du inte vill lĂ€sa, titta pĂ„ videon.

Varför vi anvÀnder Kubernetes i produktion
"Leroy Merlin" Àr en ledare pÄ DIY-retailmarknaden i Ryssland och Europa. I vÄrt företag arbetar över hundra utvecklare, 33 000 interna anstÀllda och ett stort antal mÀnniskor besöker vÄra varuhus och webbplats. För att göra alla glada beslutade vi att följa standardmetoder inom branschen. Vi utvecklar nya applikationer med mikrotjÀnstarkitektur; för att isolera miljöer och sÀkerstÀlla korrekt leverans anvÀnder vi containrar; och för orkestrering anvÀnder vi Kubernetes. Kostnaden för att anvÀnda orkestratorer blir snabbt billigare: antalet ingenjörer som behÀrskar tekniken ökar pÄ marknaden och leverantörer erbjuder Kubernetes som en tjÀnst.
Allt som Kubernetes gör kan sjÀlvklart göras pÄ andra sÀtt, till exempel genom att kladda med skript i nÄgon Jenkins och docker-compose, men varför komplicera livet nÀr det finns en fÀrdig och pÄlitlig lösning? DÀrför har vi valt Kubernetes och har anvÀnt det i produktion i ett Är nu. Nu har vi tjugofyra Kubernetes-kluster, det Àldsta av dem Àr över ett Är gammalt och har cirka tvÄhundra pods.
Förbannelsen med ett stort antal YAML-filer i Kubernetes
För att starta en mikrotjĂ€nst i Kubernetes kommer vi att skapa minst fem YAML-filer: för Deployment, Service, Ingress, ConfigMap, Secrets â och skicka dem till klustret. För nĂ€sta applikation skriver vi samma uppsĂ€ttning YAML-filer, med den tredje â ytterligare en och sĂ„ vidare. Multiplicera antalet dokument med antalet miljöer, sĂ„ fĂ„r vi hundratals filer, och detta tar inte ens hĂ€nsyn till dynamiska miljöer.

Adam Reese, huvudansvarig för Helm, introducerade begreppet "" som ser ut sÄ hÀr:
- Kopiera YAML â kopiera YAML-filen.
- Klistra in YAML â klistra in den.
- Fixera indrag â fixa indragen.
- Upprepa â upprepa igen.
Detta alternativ fungerar, men man mÄste ofta kopiera YAML-filer flera gÄnger. För att förÀndra denna cykel uppfanns Helm.
Vad Àr Helm
Först och frĂ€mst Ă€r Helm â paketchef, som hjĂ€lper till att hitta och installera nödvĂ€ndiga program. För att installera till exempel MongoDB mĂ„ste man inte gĂ„ till den officiella webbplatsen och ladda ner binĂ€rfiler, det rĂ€cker att köra kommandot helm install stable/mongodb.
För det andra, Helm â en mallmotor, hjĂ€lper till att parametrera filer. LĂ„t oss Ă„tergĂ„ till situationen med YAML-filer i Kubernetes. Det Ă€r enklare att skriva samma YAML-fil, lĂ€gga till nĂ„gra platshĂ„llare, dĂ€r Helm sĂ€tter in vĂ€rden. Det betyder att istĂ€llet för en stor uppsĂ€ttning YAML-filer kommer det att finnas en uppsĂ€ttning mallar, dĂ€r de nödvĂ€ndiga vĂ€rdena kommer att sĂ€ttas in vid rĂ€tt tidpunkt.
För det tredje, Helm â mĂ€stare vid distribution. Med hjĂ€lp av det kan man installera, Ă„terstĂ€lla och uppdatera applikationer. LĂ„t oss gĂ„ igenom hur man gör detta.

Hur man anvÀnder Helm för att distribuera sina egna applikationer
Vi installerar Helm-klienten pÄ datorn, enligt den officiella . Sedan skapar vi en uppsÀttning YAML-filer. IstÀllet för att ange specifika vÀrden lÀmnar vi platshÄllare som Helm senare kommer att fylla med information. En uppsÀttning sÄdana filer kallas för en Helm-diagram. Den kan skickas till Helm-konsolklienten pÄ tre sÀtt:
- ange mappen med mallar;
- paketera den i en .tar-arkiv och ange den;
- placera mallen i ett fjÀrrrepo och lÀgga till en lÀnk till repositoriet i Helm-klienten.
Ăven en fil med vĂ€rden behövs â values.yaml. Data dĂ€rifrĂ„n kommer att sĂ€ttas in i mallen. LĂ„t oss skapa den ocksĂ„.

I den andra versionen av Helm finns det en tillĂ€ggstjĂ€nst â Tiller. Den finns utanför Kubernetes och vĂ€ntar pĂ„ förfrĂ„gningar frĂ„n Helm-klienten, och nĂ€r den anropas sĂ€tter den in nödvĂ€ndiga vĂ€rden i mallen och skickar dem till Kubernetes.

Helm 3 Àr enklare: istÀllet för att bearbeta mallarna pÄ servern, behandlas informationen nu helt och hÄllet pÄ sidan av Helm-klienten och skickas direkt till Kubernetes API. Denna förenkling förbÀttrar sÀkerheten för klustret och förenklar distributionsschemat.
Hur detta fungerar
Kör kommandot helm install. Ange namnet pÄ applikationens release, ge sökvÀgen till values.yaml. I slutet anger vi repo dÀr diagrammet ligger och namnet pÄ diagrammet. I exemplet Àr detta «lmru» och «bestchart» respektive.
helm install --name bestapp --values values.yaml lmru/bestchart
Utförandet av kommandot Àr möjligt endast en gÄng, vid upprepning av kommandot istÀllet för install mÄste du anvÀnda upgrade. För enkelhetens skull kan man istÀllet för tvÄ kommandon köra kommandot upgrade med en extra nyckel --install. Vid första körningen skickar Helm en kommando för att installera releasen, och kommer att uppdatera den i framtiden.
helm upgrade --install bestapp --values values.yaml lmru/bestchart
Fallgropar vid deployment av nya versioner av applikationen med Helm
Vid den hÀr punkt i berÀttelsen spelar jag med publiken i "Vem vill bli miljonÀr?", och vi tar reda pÄ hur man fÄr Helm att uppdatera applikationens version. .
NĂ€r jag studerade hur Helm fungerar, blev jag förvĂ„nad över det mĂ€rkliga beteendet vid försök att uppdatera versioner av körda applikationer. Applikationens kod uppdaterades, en ny bild laddades upp i Docker-registret, jag skickade ett kommando för deployment â och ingenting hĂ€nde. HĂ€r Ă€r nĂ„gra inte helt lyckade sĂ€tt att uppdatera applikationer. Genom att studera varje metod mer ingĂ„ende börjar man förstĂ„ verktygets inre funktion och orsakerna till detta inte sĂ„ uppenbara beteende.
Metod 1. Ăndra inte informationen sedan senaste körningen
Som det stÄr Helm, "Kubernetes charts kan vara stora och komplexa, sÄ Helm försöker helst att inte röra saker för mycket". DÀrför, om man uppdaterar latest-versionen av applikationens bild i Docker-registret och utför kommandot helm upgrade, sÄ kommer ingenting att hÀnda. Helm kommer att tro att ingenting har förÀndrats och behöver ingen kommando för att uppdatera applikationen i Kubernetes.
HÀr och framÄt visas taggen latest endast som ett exempel. Vid angivande av denna tagg kommer Kubernetes att ladda ner bilden frÄn Docker-registret varje gÄng, oavsett imagePullPolicy. AnvÀndning av latest i produktion Àr inte rekommenderat och ger biverkningar.
Metod 2. Uppdatera LABEL i bilden
Som det stÄr i samma , "Helm kommer att uppdatera applikationen endast om den har förÀndrats sedan senaste releasen". En logisk ÄtgÀrd för detta skulle vara att uppdatera LABEL-taggen i sjÀlva Docker-bilden. Men Helm kollar inte i applikationernas bilder och har ingen aning om nÄgra förÀndringar i dem. DÀrför, vid uppdatering av etiketter i bilden, fÄr Helm inte veta om dem och kommandot för att uppdatera applikationen i Kubernetes kommer inte att skickas.
Metod 3. AnvÀnd nyckeln --force

LÄt oss kolla manualerna och leta efter rÀtt nyckel. Den nyckel som passar bÀst i betydelse --force. Trots det talande namnet, skiljer sig beteendet frÄn förvÀntningarna. IstÀllet för att tvinga fram en uppdatering av appen, Àr dess verkliga syfte att ÄterstÀlla en release som Àr i status FAILED. Om denna flagga inte anvÀnds, mÄste kommandona utföras sekventiellt. helm delete && helm install --replace. IstÀllet föreslÄs det att anvÀnda flaggan --force, som automatiserar sekventiell körning av dessa kommandon. Mer information finns i denna . För att fÄ Helm att faktiskt uppdatera appversionen, kommer tyvÀrr denna flagga inte att fungera.
Metod 4. Ăndra labels direkt i Kubernetes.

Uppdatering av label direkt i klustret med kommandot kubectl edit. â Ă€r en dĂ„lig idĂ©. Denna Ă„tgĂ€rd kommer att leda till inkonsekvens i informationen mellan den körande appen och vad som ursprungligen skickades för distribution. Helm's beteende vid distribution i detta fall skiljer sig frĂ„n dess version: Helm 2 kommer inte att göra nĂ„got, medan Helm 3 kommer att distribuera en ny version av appen. För att förstĂ„ orsaken, behöver man förstĂ„ hur Helm fungerar.
Hur Helm fungerar.
För att avgöra om appen har Àndrats sedan den senaste releasen, kan Helm anvÀnda sig av:
- den körande appen i Kubernetes;
- en ny values.yaml och aktuell chart;
- intern information om releases frÄn Helm.
För de mest nyfikna: var lagrar Helm intern information om releases?Genom att köra kommandot helm history,fÄr vi all information om versioner installerade med hjÀlp av Helm.

Det finns ocksÄ detaljerad information om de skickade mallarna och vÀrdena. Vi kan begÀra det:

I den andra versionen av Helm ligger denna information i samma namespace dÀr Tiller kör, vilket som standard Àr kube-system, i en ConfigMap mÀrkt med labeln "OWNER=TILLER":

Vid övergÄngen till den tredje versionen av Helm flyttades informationen till hemligheter, i samma namespace dÀr appen körs. Detta gjorde det möjligt att köra flera appar samtidigt i olika namespaces med samma release-namn. I den andra versionen var detta en stor huvudvÀrk, eftersom namespaces var isolerade men kunde pÄverka varandra.

Andra Helm, nÀr den försöker förstÄ om en uppdatering behövs, anvÀnder endast tvÄ informationskÀllor: det som gavs nu och den interna informationen om releases, som ligger i ConfigMap.

Den tredje Helm anvÀnder en trevÀgsfusionsstrategi: utöver den information som beaktas, tar den ocksÄ hÀnsyn till applikationen som körs just nu i Kubernetes.

Av denna anledning kommer den gamla versionen av Helm inte att göra nÄgot, eftersom den inte beaktar informationen frÄn applikationen i klustret, medan Helm 3 kommer att ta emot Àndringar och skicka en ny applikation för distribution.
Metod 5. AnvĂ€nda nyckeln ârecreate-pods
Med hjÀlp av nyckeln --recreate-pods kan man uppnÄ det som ursprungligen var tÀnkt att uppnÄs med nyckeln --force. Kontainrarna kommer att startas om och, enligt policyn imagePullPolicy: Always för taggen latest (angivet ovan), kommer Kubernetes att ladda ner och starta den nya versionen av bilden. Det kommer att göras pÄ ett mindre optimalt sÀtt: utan att ta hÀnsyn till StrategyType för distributionen, kommer alla gamla instanser av applikationen plötsligt att stÀngas av och nya sÀttas igÄng. Under omstarten kommer systemet att vara nere, vilket innebÀr att anvÀndarna kommer att drabbas.
I Kubernetes har ett liknande problem ocksÄ funnits under en lÄng tid. Och nu, fyra Är efter att det öppnades , har problemet ÄtgÀrdats, och frÄn och med version 1.15 av Kubernetes finns det möjlighet till rolling-restart av pods.
Helm stÀnger helt enkelt av alla applikationer och startar nya containrar bredvid dem. SÄ hÀr fÄr man inte göra i produktion för att undvika driftstopp av applikationen. Detta behövs endast för utvecklingssyften och kan endast utföras i stage-miljöer.
Hur uppdaterar man en applikationsversion med hjÀlp av Helm?
Vi kommer att Àndra de vÀrden som skickas till Helm. Som regel Àr detta vÀrden som ersÀtter taggen för bilden. I fallet med latest, som ofta anvÀnds för icke-produktiva miljöer, fungerar en annotation som den förÀnderliga informationen, vilken Àr vÀrdelös för Kubernetes men signalerar till Helm att applikationen behöver uppdateras. Alternativ för att fylla i vÀrdet pÄ annoteringen:
- Slumptal med hjĂ€lp av standardfunktionen â
{{ randAlphaNum 6 }}.
Det finns en detalj: efter varje distribution med en chart med en sĂ„dan variabel, kommer vĂ€rdet av annoteringen att vara unikt, och Helm kommer att tro att det finns Ă€ndringar. Det gör att vi alltid kommer att starta om applikationen, Ă€ven om vi inte har Ă€ndrat dess version. Det Ă€r inte kritiskt, eftersom det inte kommer att bli nĂ„got driftstopp, men det Ă€r Ă€ndĂ„ obehagligt. - Infoga nuvarande datum och tid â
{{ .Release.Date }}.
Alternativet liknar slumptalet med en stĂ€ndigt unik variabel. - Ett mer korrekt sĂ€tt Ă€r att anvĂ€nda kontrollsummor. Det Ă€r SHA av bilden eller SHA av den senaste commit i git â
{{ .Values.sha }}.
Dessa mÄste berÀknas och skickas till Helm-klienten pÄ anropande sida, till exempel i Jenkins. Om applikationen har Àndrats, sÄ Àndras Àven kontrollsumman. DÀrför kommer Helm att uppdatera applikationen endast nÀr det behövs.
Sammanfatta vÄra försök
- Helm gör Àndringar pÄ det minst invasiva sÀttet, sÄ varje Àndring pÄ nivÄ av applikationsbild i Docker Registry kommer inte att leda till en uppdatering: efter att kommandot har körts kommer ingenting att hÀnda.
- Nyckeln
--forceanvÀnds för att ÄterstÀlla problematiska releaser och har ingen koppling till tvingad uppdatering. - Nyckeln
--recreate-podstvingar uppdateringar av applikationer, men gör det pÄ ett grymt sÀtt: det stÀnger abrupt av alla containrar. AnvÀndarna kommer att drabbas, sÄ detta bör undvikas i produktion. - Direkt göra förÀndringar i Kubernetes-klustret med kommandot
kubectl edit.bör inte göras: vi skulle störa konsistensen, och beteendet kommer att variera beroende pÄ versionen av Helm. - Med den nya versionen av Helm har det dykt upp mÄnga nyanser. Issues i Helm-förvaret Àr beskrivna pÄ ett begripligt sprÄk, de kommer att hjÀlpa till att förstÄ detaljerna.
- Att lÀgga till en Àndringsbar annotation i chartet gör det mer flexibelt. Detta gör att applikationen kan rullas ut korrekt utan driftstopp.
En tanke frÄn kategorin "fred i hela vÀrlden", som fungerar i alla livets sfÀrer: lÀs instruktionen före anvÀndning, inte efter. Endast med fullstÀndig information kan man bygga pÄlitliga system och göra anvÀndarna nöjda.
Andra lÀnkar i temat:
Denna presentation hördes först pÄ av Mail.ru Cloud Solutions. Se andra förelÀsningar och följ anmÀlningarna till evenemang pÄ Telegram .
KĂ€lla: habr.com
