{"id":53120,"date":"2019-11-24T00:00:00","date_gmt":"2019-11-23T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah"},"modified":"2020-02-18T14:00:59","modified_gmt":"2020-02-18T11:00:59","slug":"3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah","status":"publish","type":"post","link":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah","title":{"rendered":"3-vejs sammensmeltning i werf: implementering i Kubernetes med Helm \"p\u00e5 steroider\"","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Det, vi (og ikke kun vi) har ventet l\u00e6nge p\u00e5, er sket: <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/\">werf<\/a><\/noindex>, vores Open Source-v\u00e6rkt\u00f8j til opbygning af applikationer og levering til Kubernetes, underst\u00f8tter nu anvendelse af \u00e6ndringer ved hj\u00e6lp af 3-way-merge-patches! Derudover er det blevet muligt at adoptere eksisterende K8s-ressourcer i Helm-udgivelser uden at skulle genoprette disse ressourcer.<\/p>\n<p><img decoding=\"async\" alt=\"3-vejs sammensmeltning i werf: implementering i Kubernetes med Helm &quot;p\u00e5 steroider&quot;\" src=\"\/wp-content\/uploads\/2019\/11\/e5be3544c201f7b2c97fba216a49506d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKort sagt, s\u00e5 s\u00e6tter vi <code>WERF_THREE_WAY_MERGE=enabled<\/code> \u2014 og f\u00e5r en deploy \"som i <code>kubectl apply<\/code>\", som er kompatibel med eksisterende installationer p\u00e5 Helm 2, og lidt mere.<\/p>\n<p>Men lad os starte med teorien: hvad er 3-way-merge-patches overhovedet, hvordan kom folk p\u00e5 id\u00e9en med at generere dem, og hvorfor er de vigtige i CI\/CD-processer med infrastruktur baseret p\u00e5 Kubernetes? Herefter vil vi se p\u00e5, hvad 3-way-merge i werf indeb\u00e6rer, hvilke standardindstillinger der bruges, og hvordan man styrer dem.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Hvad er et 3-way-merge-patch?<\/h2>\n<p>\nLad os starte med opgaven at implementere ressourcer, der er beskrevet i YAML-manifester, i Kubernetes.<\/p>\n<p>For at arbejde med ressourcer tilbyder Kubernetes API de grundl\u00e6ggende operationer: create, patch, replace og delete. Det forventes, at disse anvendes til at konstruere en behagelig kontinuerlig implementering af ressourcer i klyngen. Hvordan?<\/p>\n<h3>Imperative kubectl-kommandoer<\/h3>\n<p>\nDen f\u00f8rste tilgang til at styre objekter i Kubernetes er at bruge imperative kubectl-kommandoer til at oprette, \u00e6ndre og slette disse objekter. Kort sagt:<\/p>\n<ul>\n<li> med kommandoen <code>kubectl run<\/code> kan bruges til at starte en Deployment eller Job:\n<pre><code class=\"bash\">kubectl run --generator=deployment\/apps.v1 DEPLOYMENT_NAME --image=IMAGE<\/code><\/pre>\n<\/li>\n<li> med kommandoen <code>kubectl scale<\/code> \u2014 \u00e6ndre antallet af replikaer:\n<pre><code class=\"bash\">kubectl scale --replicas=3 deployment\/mysql<\/code><\/pre>\n<\/li>\n<li>osv.<\/li>\n<\/ul>\n<p>\nDenne tilgang kan virke praktisk ved f\u00f8rste \u00f8jekast. Men der er problemer: <\/p>\n<ol>\n<li> Det er sv\u00e6rt at <b>automatisere<\/b>.<\/li>\n<li> siger <b>spejle konfigurationen<\/b> i Git? Hvordan foretager man review af \u00e6ndringer, der sker med klyngen?<\/li>\n<li> Hvordan sikrer man <b>reproducerbarhed<\/b> af konfigurationen ved genstart?<\/li>\n<li>\u2026<\/li>\n<\/ol>\n<p>\nDet st\u00e5r klart, at denne tilgang h\u00e6nger d\u00e5rligt sammen med lagring af koden sammen med applikationen og infrastruktur som kode (IaC; eller endda <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/458878\/\">GitOps<\/a><\/noindex> som et mere moderne alternativ, der vinder popularitet i Kubernetes-\u00f8kosystemet). Derfor fik disse kommandoer i kubectl ikke yderligere udvikling.<\/p>\n<h3>Operationer: create, get, replace og delete<\/h3>\n<p>\nMed den f\u00f8rste <b>oprettelse<\/b> er det hele simpelt: vi sender manifestet til operationen <code>create<\/code> til kube API, og ressourcen er oprettet. YAML-repr\u00e6sentationen af manifestet kan opbevares i Git, og til oprettelse kan vi bruge kommandoen <code>kubectl create -f manifest.yaml<\/code>.<\/p>\n<p>Med <b>sletning<\/b> er ogs\u00e5 simpel: vi inds\u00e6tter det samme <code>manifest.yaml<\/code> fra Git i kommandoen <code>kubectl delete -f manifest.yaml<\/code>.<\/p>\n<p>Operation <b><code>replace<\/code><\/b> g\u00f8r det muligt at helt erstatte en ressourcekonfiguration med en ny, uden at genskabe ressourcen. Det betyder, at f\u00f8r man \u00e6ndrer ressourcen, giver det mening at anmode om den nuv\u00e6rende version med en operation <code>get<\/code>, \u00e6ndre den og opdatere med en operation <code>replace<\/code>. I kube apiserver er der indbygget <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Optimistic_concurrency_control\">optimistic locking<\/a><\/noindex> , og hvis objektet er \u00e6ndret efter operationen <code>get<\/code> , vil operationen <code>replace<\/code> ikke g\u00e5 igennem.<\/p>\n<p>For at gemme konfigurationen i Git og opdatere ved hj\u00e6lp af replace, skal du udf\u00f8re operationen <code>get<\/code>, merge konfigurationen fra Git med det, vi har modtaget, og udf\u00f8re <code>replace<\/code>. Standard kubectl tillader kun at bruge kommandoen <code>kubectl replace -f manifest.yaml<\/code>, hvor <code>manifest.yaml<\/code> \u2014 allerede helt forberedt (i vores tilf\u00e6lde \u2014 merged) manifest, som skal installeres. Det vil sige, at brugeren skal implementere merge af manifester, og det er en kompliceret opgave...<\/p>\n<p>Det skal ogs\u00e5 n\u00e6vnes, at selvom <code>manifest.yaml<\/code> opbevares i Git, kan vi ikke vide p\u00e5 forh\u00e5nd, om vi skal oprette objektet eller opdatere det \u2014 det skal g\u00f8res af brugerdefineret software.<\/p>\n<p>I alt: <b>kan vi bygge en kontinuerlig implementering<\/b> kun ved hj\u00e6lp af create, replace og delete, sikrende opbevaring af infrastrukturens konfiguration i Git sammen med koden og en praktisk CI\/CD?<\/p>\n<p>I princippet kan vi... For dette <b>skal vi implementere en merge operation<\/b> af manifester og en eller anden indpakning, der:<\/p>\n<ul>\n<li> kontrollerer eksistensen af objektet i klyngen,<\/li>\n<li> udf\u00f8rer den f\u00f8rste oprettelse af ressourcen,<\/li>\n<li> opdaterer eller sletter den.<\/li>\n<\/ul>\n<p>\nVed opdatering skal det tages i betragtning, at <i>ressourcen kan v\u00e6re \u00e6ndret<\/i> siden sidst <code>get<\/code> og automatisk h\u00e5ndtere optimistisk l\u00e5sning \u2014 fors\u00f8ge at opdatere igen.<\/p>\n<p>Men hvorfor opfinde hjulet igen, n\u00e5r kube-apiserver tilbyder en anden m\u00e5de at opdatere ressourcer: operationen <code>patch<\/code>, som fjerner nogle af de beskrevne problemer fra brugeren?<\/p>\n<h3>Patch<\/h3>\n<p>\nS\u00e5 er vi n\u00e5et til patches.<\/p>\n<p>Patches er den prim\u00e6re m\u00e5de at anvende \u00e6ndringer p\u00e5 eksisterende objekter i Kubernetes. Operationen <code>patch<\/code> funktionerer s\u00e5ledes, at:<\/p>\n<ul>\n<li> brugeren af kube-apiserver skal sende et patch i JSON-format og angive objektet,<\/li>\n<li> og apiserver vil selv finde ud af den nuv\u00e6rende tilstand af objektet og bringe det til den \u00f8nskede tilstand.<\/li>\n<\/ul>\n<p>\nOptimistic locking er ikke n\u00f8dvendig i dette tilf\u00e6lde. Denne operation er mere deklarativ i forhold til replace, selvom det ved f\u00f8rste \u00f8jekast kan virke omvendt.<\/p>\n<p>Dermed:<\/p>\n<ul>\n<li> ved hj\u00e6lp af operationen <code>create<\/code> opretter vi et objekt baseret p\u00e5 manifestet fra Git,<\/li>\n<li> ved hj\u00e6lp af <code>slet<\/code> \u2014 sletter, hvis objektet ikke l\u00e6ngere er n\u00f8dvendigt,<\/li>\n<li> ved hj\u00e6lp af <code>patch<\/code> \u2014 \u00e6ndrer objektet, s\u00e5 det svarer til det beskrevne i Git.<\/li>\n<\/ul>\n<p>\nMen for at g\u00f8re dette, er det n\u00f8dvendigt at oprette <i>den rigtige patch<\/i>!<\/p>\n<h3>S\u00e5dan fungerer patches i Helm 2: 2-way-merge<\/h3>\n<p>\nVed f\u00f8rste installation af en Helm-udgivelse udf\u00f8rer den en operation <code>create<\/code> for chartets ressourcer.<\/p>\n<p>Ved opdatering af Helm-udgivelsen:<\/p>\n<ul>\n<li> beregner den patchen mellem versionen af ressourcen fra det tidligere chart og den nuv\u00e6rende version af chartet,<\/li>\n<li> og anvender denne patch.<\/li>\n<\/ul>\n<p>\nDenne patch vil vi kalde <b>2-way-merge patch<\/b>, fordi oprettelsen involverer 2 manifests:<\/p>\n<ul>\n<li> manifestet af ressourcen fra den tidligere udgivelse,<\/li>\n<li> manifestet af ressourcen fra den nuv\u00e6rende ressource.<\/li>\n<\/ul>\n<p>\nVed sletning kaldes operationen <code>slet<\/code> i kube apiserver for ressourcer, der blev erkl\u00e6ret i den tidligere udgivelse, men ikke erkl\u00e6ret i den nuv\u00e6rende.<\/p>\n<p>2-way merge patch-tilgangen har et problem: det f\u00f8rer til <b>desynkronisering af den faktiske tilstand af ressourcen i klyngen og manifestet i Git<\/b>.<\/p>\n<h3>Illustration af problemet med et eksempel<\/h3>\n<p><\/p>\n<ul>\n<li> I Git, i chartet, er der et manifest, hvor feltet <code>billede<\/code> i Deployment har v\u00e6rdien <code>ubuntu:18.04<\/code>.<\/li>\n<li> Brugeren \u00e6ndrede v\u00e6rdien af dette felt til <code>kubectl edit<\/code> \u00e6ndret til <code>ubuntu:19.04<\/code>.<\/li>\n<li> Ved re-deployment af chartet genererer Helm <i>ikke en patch,<\/i>fordi feltet <code>billede<\/code> i den tidligere udgave og i det nuv\u00e6rende chart er ens.<\/li>\n<li> Efter om-deployment <code>billede<\/code> forbliver <code>ubuntu:19.04<\/code>, selvom det i chartet st\u00e5r <code>ubuntu:18.04<\/code>.<\/li>\n<\/ul>\n<p>\nVi har f\u00e5et desynkronisering og mistet deklarativitet.<\/p>\n<h3>Hvad er en synkroniseret ressource?<\/h3>\n<p>\nGenerelt set, <i>fuld<\/i> overensstemmelse mellem ressourcens manifest i den k\u00f8rende klynge og manifestet fra Git er umuligt at opn\u00e5. Fordi der i det faktiske manifest kan v\u00e6re systemanmodninger\/labels, yderligere containere og andre data, der dynamisk tilf\u00f8jes og fjernes fra ressourcen af bestemte controllere. Disse data \u00f8nsker vi ikke at gemme i Git. Men vi \u00f8nsker, at de felter, vi specifikt angav i Git, f\u00e5r de tilsvarende v\u00e6rdier ved implementeringen.<\/p>\n<p>Det resulterer i en generel <b>regel for synkroniseret ressource<\/b>: ved implementering af ressourcen kan man kun \u00e6ndre eller fjerne de felter, der tydeligt er angivet i manifestet fra Git (eller som blev angivet i den tidligere version, men nu er fjernet).<\/p>\n<h3>3-way-merge patch<\/h3>\n<p>\nDen grundl\u00e6ggende id\u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Merge_(version_control)#Three-way_merge\">3-way-merge patch<\/a><\/noindex>: genererer en patch mellem den senest anvendte version af manifestet fra Git og den m\u00e5lrettede version af manifestet fra Git med hensyn til den nuv\u00e6rende version af manifestet fra den k\u00f8rende klynge. Den endelige patch skal overholde synkroniseringsreglen for ressourcen:<\/p>\n<ul>\n<li> nye felter, der er tilf\u00f8jet til den m\u00e5lrettede version, tilf\u00f8jes ved hj\u00e6lp af patchen;<\/li>\n<li> Tidligere eksisterende felter i den senest anvendte version, som ikke findes i m\u00e5let, nulstilles ved hj\u00e6lp af en patch;<\/li>\n<li> Felter i den aktuelle version af objektet, der adskiller sig fra den m\u00e5lversion af manifestet, opdateres via en patch.<\/li>\n<\/ul>\n<p>\nDet er pr\u00e6cist efter denne metode, at patches genereres <code>kubectl apply<\/code>:<\/p>\n<ul>\n<li> Den senest anvendte version af manifestet gemmes i annotationen af selve objektet, <\/li>\n<li> m\u00e5let tages fra den angivne YAML-fil,<\/li>\n<li> den aktuelle tages fra det fungerende cluster.<\/li>\n<\/ul>\n<p>\nNu, n\u00e5r vi har forst\u00e5et teorien, er det tid til at fort\u00e6lle, hvad vi har gjort i werf.<\/p>\n<h2>Anvendelse af \u00e6ndringer i werf<\/h2>\n<p>\nTidligere brugte werf, ligesom Helm 2, 2-way-merge-patches.<\/p>\n<h3>Repair patch<\/h3>\n<p>\nFor at skifte til den nye type patches \u2014 3-way-merge \u2014 har vi som det f\u00f8rste skridt indf\u00f8rt s\u00e5kaldte <b>repair-patches<\/b>.<\/p>\n<p>Ved deployment bruges den standard 2-way-merge patch, men werf genererer desuden en patch, der synkroniserer den faktiske tilstand af ressourcen med det, der er skrevet i Git (denne patch oprettes ved anvendelse af de samme regler for synkroniserede ressourcer, som beskrevet ovenfor).<\/p>\n<p>I tilf\u00e6lde af, at der opst\u00e5r en desynkronisering, modtager brugeren ved slutningen af deployment en WARNING med den relevante besked og en patch, som skal anvendes for at bringe ressourcen tilbage til en synkroniseret tilstand. Denne patch gemmes ogs\u00e5 i en speciel annotation <code>werf.io\/repair-patch<\/code>. Det forventes, at brugeren selv <b>manuelt<\/b> anvender denne patch: werf vil ikke anvende den principielt.<\/p>\n<p>Genereringen af repair-patches er en midlertidig foranstaltning, der g\u00f8r det muligt at teste oprettelsen af patches baseret p\u00e5 princippet om 3-way-merge, men at anvende disse patches automatisk.<\/p>\n<h3>3-way-merge patch kun for nye udgivelser<\/h3>\n<p>\nFra den 1. december 2019 begynder beta- og alpha-versioner af werf at <b>som standard<\/b> anvende fuldt ud 3-way-merge-patches til anvendelse af \u00e6ndringer kun for nye Helm-udgivelser, der distribueres gennem werf. Allerede eksisterende udgivelser vil forts\u00e6tte med at anvende tilgangen med 2-way-merge + repair-patches.<\/p>\n<p>Denne driftsform kan eksplicit aktiveres ved at indstille <code>WERF_THREE_WAY_MERGE_MODE=onlyNewReleases<\/code> allerede nu.<\/p>\n<p><i><b>Bem\u00e6rk<\/b>: funktionen er kommet til werf over flere udgivelser: i alpha-kanalen blev den klar med versionen <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\/releases\/tag\/v1.0.5-alpha.19\">v1.0.5-alpha.19<\/a><\/noindex>, og i beta-kanalen \u2014 med <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\/releases\/tag\/v1.0.4-beta.20\">v1.0.4-beta.20<\/a><\/noindex>.<\/i><\/p>\n<h3>3-way-merge patch for alle udgivelser<\/h3>\n<p>\nFra den 15. december 2019 vil beta- og alpha-versioner af werf som standard bruge fuld 3-vejs-merge-patches til at anvende \u00e6ndringer til alle udgivelser.<\/p>\n<p>Denne driftsform kan eksplicit aktiveres ved at indstille <code>WERF_THREE_WAY_MERGE_MODE=enabled<\/code> allerede nu.<\/p>\n<h3>Hvordan h\u00e5ndteres autoskalering af ressourcer?<\/h3>\n<p>\nI Kubernetes findes der 2 typer af autoskalering: HPA (horisontal) og VPA (vertikal).<\/p>\n<p>Horisontal v\u00e6lger automatisk antallet af replikaer, mens vertikal v\u00e6lger m\u00e6ngden af ressourcer. B\u00e5de antallet af replikaer og kravene til ressourcer angives i ressourcemanifestet (se <code>spec.replicas<\/code> eller <code>spec.containers[].resources.limits.cpu<\/code>, <code>spec.containers[].resources.limits.memory<\/code> og <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/configuration\/manage-compute-resources-container\/#resource-requests-and-limits-of-pod-and-container\">andre<\/a><\/noindex>).<\/p>\n<p>Problemet er: hvis brugeren konfigurerer ressourcen i chartet, s\u00e5 den indeholder bestemte v\u00e6rdier for ressourcer eller replikaer, og autoskalere er aktiveret for den p\u00e5g\u00e6ldende ressource, s\u00e5 vil werf ved hver deployment nulstille disse v\u00e6rdier til dem, der er skrevet i chartmanifestet.<\/p>\n<p>Der er to l\u00f8sninger p\u00e5 problemet. For det f\u00f8rste er det bedst at undg\u00e5 at angive autoskalere v\u00e6rdier eksplicit i chartmanifestet. Hvis denne mulighed af en eller anden grund ikke er passende (f.eks. fordi det er praktisk at angive oprindelige ressourcebegr\u00e6nsninger og antallet af replikaer i chartet), s\u00e5 tilbyder werf f\u00f8lgende annotationer:<\/p>\n<ul>\n<li> <code>werf.io\/set-replicas-only-on-creation=true<\/code><\/li>\n<li> <code>werf.io\/set-resources-only-on-creation=true<\/code><\/li>\n<\/ul>\n<p>\nMed en s\u00e5dan annotation vil werf ikke nulstille de relevante v\u00e6rdier ved hver deployment, men kun indstille dem ved den oprindelige oprettelse af ressourcen.<\/p>\n<p>For mere information \u2013 se projektets dokumentation om <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#deal-with-hpa\">HPA<\/a><\/noindex> og <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#deal-with-vpa\">VPA<\/a><\/noindex>.<\/p>\n<h3>Forbyd brug af 3-vejs-merge patch<\/h3>\n<p>\nBrugeren kan midlertidigt forbyde brugen af nye patches i werf ved hj\u00e6lp af milj\u00f8variablen <code>WERF_THREE_WAY_MERGE_MODE=disabled<\/code>. Men fra <b>den 1. marts 2020 vil dette forbud oph\u00f8re med at fungere<\/b> og det vil kun v\u00e6re muligt at bruge 3-vejs-merge-patches.<\/p>\n<h2>Adoption af ressourcer i werf<\/h2>\n<p>\nImplementeringen af 3-vejs-merge-patch-\u00e6ndringer har gjort os i stand til straks at underst\u00f8tte en funktion som adoption af eksisterende ressourcer i klyngen i Helm-udgivelser.<\/p>\n<p>Helm 2 har et problem: Man kan ikke tils\u00e6tte en ressource, der allerede eksisterer i klyngen, i chartmanifestet uden at genskabe ressourcen fra bunden (se <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/helm\/helm\/issues\/6031#issuecomment-531579500\">#6031<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/helm\/helm\/issues\/3275\">#3275<\/a><\/noindex>). Vi har l\u00e6rt werf at acceptere eksisterende ressourcer i udgivelsen. For at g\u00f8re dette skal man tilf\u00f8je en annotation til den nuv\u00e6rende version af ressourcen fra den k\u00f8rende klynge (f.eks. ved hj\u00e6lp af <code>kubectl edit<\/code>):<\/p>\n<pre><code class=\"plaintext\">\"werf.io\/allow-adoption-by-release\": RELEASE_NAME<\/code><\/pre>\n<p>\nNu skal ressourcen beskrives i diagrammet, og ved den n\u00e6ste deployment med werf af en version med det tilsvarende navn, vil den eksisterende ressourc blive optaget i denne version og forblive under dens kontrol. Desuden vil werf under optagelsen af ressourcen bringe den nuv\u00e6rende tilstand af ressourcen fra det fungerende cluster til den tilstand, der er beskrevet i diagrammet, ved at bruge de samme 3-way-merge-patches og reglen for synkroniserede ressourcer.<\/p>\n<p><i><b>Bem\u00e6rk<\/b>: indstilling <code>WERF_THREE_WAY_MERGE_MODE<\/code> p\u00e5virker ikke adoption af ressourcer \u2014 ved adoption bruges der altid 3-way-merge-patch.<\/i><\/p>\n<p>Detaljer findes i <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#resources-adoption\">dokumentationen<\/a><\/noindex>.<\/p>\n<h2>Konklusioner og fremtidige planer<\/h2>\n<p>\nJeg h\u00e5ber, at det efter denne artikel er blevet klarere, hvad 3-way-merge-patches er, og hvorfor vi kom til dem. Set fra et praktisk perspektiv for projektudviklingen af werf er deres implementering et yderligere skridt mod forbedring af Helm-lignende deployment. Nu kan vi glemme problemerne med synkronisering af konfigurationer, som ofte opstod ved brug af Helm 2. Samtidig er der tilf\u00f8jet en ny nyttig funktion til adoption af allerede downloadede Kubernetes-ressourcer i Helm-versionen.<\/p>\n<p>Der er stadig nogle problemer og vanskeligheder, s\u00e5som brugen af Go-skabeloner, i Helm-lignende deployment, og vi vil forts\u00e6tte med at l\u00f8se dem.<\/p>\n<p>Oplysninger om metoder til opdatering af ressourcer og adoption kan ogs\u00e5 findes p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html\">denne dokumentationsside<\/a><\/noindex>.<\/p>\n<h3>Helm 3<\/h3>\n<p>\nDet fortjener at blive bem\u00e6rket, at <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/news\/t\/475722\/\">den nye<\/a><\/noindex> store version af Helm \u2014 v3, udgivet for nylig, som ogs\u00e5 bruger 3-way-merge-patches og fjerner Tiller. Den nye version af Helm kr\u00e6ver <noindex><a rel=\"nofollow\" href=\"https:\/\/helm.sh\/docs\/topics\/v2_v3_migration\/\">migration<\/a><\/noindex> af allerede eksisterende installationer for at konvertere dem til det nye format til lagring af versioner.<\/p>\n<p>Werf har p\u00e5 sin side allerede opgivet brugen af Tiller, skiftet til 3-way-merge og tilf\u00f8jet <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/differences_with_helm.html\">meget mere<\/a><\/noindex>, mens den forbliver kompatibel med allerede eksisterende installationer p\u00e5 Helm 2 (der skal ikke udf\u00f8res migrationsscripts). Derfor, mens werf ikke er skiftet til Helm 3, mister brugerne af werf ikke de grundl\u00e6ggende fordele, som Helm 3 har i forhold til Helm 2 (de er ogs\u00e5 til stede i werf).<\/p>\n<p>Ikke desto mindre er skiftet af werf til Helm 3-koden uundg\u00e5eligt og vil ske i den n\u00e6rmeste fremtid. Det forventes at v\u00e6re werf 1.1 eller werf 1.2 (for \u00f8jeblikket er hovedversionen af werf \u2014 1.0; for mere information om versioneringsstrukturen for werf, se <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf#backward-compatibility-promise\">her<\/a><\/noindex>). I mellemtiden vil Helm 3 f\u00e5 tid til at stabilisere sig.<\/p>\n<h2>P.S.<\/h2>\n<p>\nL\u00e6s ogs\u00e5 p\u00e5 vores blog:<\/p>\n<ul>\n<li> Cykelnotater om nyheder i werf:\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/468049\/\">Brug af werf til implementering af komplekse Helm-diagrammer<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465131\/\">Underst\u00f8ttelse af monorepo og multirepo i werf og hvad Docker Registry har at g\u00f8re med det<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/463613\/\">Byg Docker-billeder i werf kan nu ogs\u00e5 g\u00f8res med en almindelig Dockerfile<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/460351\/\">werf \u2014 vores v\u00e6rkt\u00f8j til CI\/CD i Kubernetes (oversigt og video af pr\u00e6sentationen)<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/469541\/\">Bygning og udrulning af ensartede mikrotjenester med werf og GitLab CI<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/453734\/\">Introduktion til Helm 3<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/476646\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0421\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0442\u043e, \u0447\u0435\u0433\u043e \u043c\u044b (\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b) \u0434\u043e\u043b\u0433\u043e \u0436\u0434\u0430\u043b\u0438: werf, \u043d\u0430\u0448\u0430 Open Source-\u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0438\u0445 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0432 Kubernetes, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e 3-way-merge-\u043f\u0430\u0442\u0447\u0435\u0439! \u0412 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a \u044d\u0442\u043e\u043c\u0443, \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c adoption\u2019\u0430 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 K8s-\u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0432 Helm-\u0440\u0435\u043b\u0438\u0437\u044b \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u0415\u0441\u043b\u0438 \u0441\u043e\u0432\u0441\u0435\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u043e, \u0442\u043e \u0441\u0442\u0430\u0432\u0438\u043c WERF_THREE_WAY_MERGE=enabled \u2014 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0435\u043f\u043b\u043e\u0439 \u00ab\u043a\u0430\u043a \u0432 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":53121,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-53120","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0421\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0442\u043e, \u0447\u0435\u0433\u043e \u043c\u044b (\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b) \u0434\u043e\u043b\u0433\u043e \u0436\u0434\u0430\u043b\u0438: werf, \u043d\u0430\u0448\u0430 Open Source-\u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0438\u0445 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0432 Kubernetes, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd473-way merge \u0432 werf: \u0434\u0435\u043f\u043b\u043e\u0439 \u0432 Kubernetes \u0441 Helm \u00ab\u043d\u0430 \u0441\u0442\u0435\u0440\u043e\u0438\u0434\u0430\u0445\u00bb | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0421\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0442\u043e, \u0447\u0435\u0433\u043e \u043c\u044b (\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b) \u0434\u043e\u043b\u0433\u043e \u0436\u0434\u0430\u043b\u0438: werf, \u043d\u0430\u0448\u0430 Open Source-\u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0438\u0445 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0432 Kubernetes, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-23T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:59+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd473-vejs sammensmeltning i werf: Deployment i Kubernetes med Helm \"p\u00e5 steroider\" | ProHoster","description":"Det, vi (og ikke kun vi) har ventet l\u00e6nge p\u00e5, er nu sket: werf, vores Open Source-v\u00e6rkt\u00f8j til at bygge applikationer og levere dem til Kubernetes, underst\u00f8tter nu.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd473-way merge \u0432 werf: \u0434\u0435\u043f\u043b\u043e\u0439 \u0432 Kubernetes \u0441 Helm \u00ab\u043d\u0430 \u0441\u0442\u0435\u0440\u043e\u0438\u0434\u0430\u0445\u00bb | ProHoster","og:description":"\u0421\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0442\u043e, \u0447\u0435\u0433\u043e \u043c\u044b (\u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b) \u0434\u043e\u043b\u0433\u043e \u0436\u0434\u0430\u043b\u0438: werf, \u043d\u0430\u0448\u0430 Open Source-\u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u0438\u0445 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0432 Kubernetes, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442.","og:url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-23T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:59+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"53120","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 06:11:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:31:28","updated":"2026-01-24 06:11:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/53120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=53120"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/53120\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/53121"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=53120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=53120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=53120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}