{"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\/nl\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah","title":{"rendered":"3-way merge in werf: deploy in Kubernetes met Helm \"op stero\u00efden\"","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Het is gebeurd waar wij (en niet alleen wij) al lang op hebben gewacht: <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/\">werf<\/a><\/noindex>, onze Open Source-tool voor het bouwen van applicaties en hun levering aan Kubernetes ondersteunt nu het toepassen van wijzigingen met behulp van 3-way-merge-patches! Daarnaast is het nu mogelijk om bestaande K8s-resources in Helm-releases te adopteren zonder deze resources opnieuw te cre\u00ebren.<\/p>\n<p><img decoding=\"async\" alt=\"3-way merge in werf: deploy in Kubernetes met Helm &quot;op stero\u00efden&quot;\" src=\"\/wp-content\/uploads\/2019\/11\/e5be3544c201f7b2c97fba216a49506d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEen korte samenvatting: we zetten <code>WERF_THREE_WAY_MERGE=enabled<\/code> \u2014 we krijgen een uitrol \"zoals in <code>kubectl apply<\/code>\", compatibel met bestaande installaties op Helm 2 en zelfs iets meer.<\/p>\n<p>Maar laten we beginnen met de theorie: wat zijn 3-way-merge-patches, hoe zijn mensen tot deze benadering gekomen en waarom zijn ze belangrijk in CI\/CD-processen met een infrastructuur gebaseerd op Kubernetes? En daarna bekijken we wat 3-way-merge in werf inhoudt, welke modi standaard worden gebruikt en hoe je deze kunt beheren.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Wat is een 3-way-merge-patch?<\/h2>\n<p>\nLaten we beginnen met de taak om resources, beschreven in YAML-manifesten, in Kubernetes uit te rollen.<\/p>\n<p>Voor het werken met resources biedt de Kubernetes API de volgende basisbewerkingen: create, patch, replace en delete. Het idee is dat je hiermee een handige continue uitrol van resources naar het cluster kunt construeren. Hoe?<\/p>\n<h3>Imperatieve kubectl-commando's<\/h3>\n<p>\nDe eerste benadering voor het beheren van objecten in Kubernetes is het gebruik van imperatieve kubectl-commando's voor het cre\u00ebren, wijzigen en verwijderen van deze objecten. In eenvoudige bewoordingen:<\/p>\n<ul>\n<li> met het commando <code>kubectl run<\/code> je kunt een Deployment of Job starten:\n<pre><code class=\"bash\">kubectl run --generator=deployment\/apps.v1 DEPLOYMENT_NAME --image=IMAGE<\/code><\/pre>\n<\/li>\n<li> met het commando <code>kubectl scale<\/code> \u2014 wijzig het aantal replicas:\n<pre><code class=\"bash\">kubectl scale --replicas=3 deployment\/mysql<\/code><\/pre>\n<\/li>\n<li>enzovoorts.<\/li>\n<\/ul>\n<p>\nDeze aanpak lijkt misschien handig op het eerst gezicht. Maar er zijn problemen: <\/p>\n<ol>\n<li> Het is moeilijk <b>te automatiseren<\/b>.<\/li>\n<li> Zoals <b>de configuratie<\/b> in Git te reflecteren? Hoe maak je een review van de wijzigingen die plaatsvinden in het cluster?<\/li>\n<li> Hoe zorg je voor <b>reproduceerbaarheid<\/b> van de configuratie bij herstart?<\/li>\n<li>\u2026<\/li>\n<\/ol>\n<p>\nHet is duidelijk dat deze aanpak slecht past bij het opslaan met de code van de applicatie en infrastructuur als code (IaC; of zelfs <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/458878\/\">GitOps<\/a><\/noindex> als een modernere variant die steeds populairder wordt in de Kubernetes-ecosysteem). Daarom heeft deze commando's in kubectl niet verder ontwikkeld.<\/p>\n<h3>De operaties create, get, replace en delete<\/h3>\n<p>\nMet de primaire <b>creatie<\/b> is alles eenvoudig: we sturen het manifest naar de operatie <code>create<\/code> bij de kube api en de resource is aangemaakt. De YAML-representatie van het manifest kan in Git worden opgeslagen, en om te cre\u00ebren \u2014 gebruik het commando <code>kubectl create -f manifest.yaml<\/code>.<\/p>\n<p>met <b>verwijderen<\/b> is ook eenvoudig: we gebruiken hetzelfde <code>manifest.yaml<\/code> uit Git in het commando <code>kubectl delete -f manifest.yaml<\/code>.<\/p>\n<p>Operatie <b><code>replace<\/code><\/b> stelt in staat om de configuratie van een resource volledig te vervangen door een nieuwe, zonder de resource opnieuw aan te maken. Dit betekent dat het logisch is om de huidige versie op te vragen voordat je een wijziging aan de resource aanbrengt met de operatie <code>krijgen<\/code>, deze te wijzigen en de operatie bij te werken <code>replace<\/code>. In kube apiserver is ingebouwd <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Optimistic_concurrency_control\">optimistische locking<\/a><\/noindex> en, als het object na de operatie <code>krijgen<\/code> is veranderd, dan zal de operatie <code>replace<\/code> niet doorgaan.<\/p>\n<p>Om de configuratie in Git op te slaan en deze bij te werken met behulp van replace, moet je de operatie <code>krijgen<\/code>, de configuratie uit Git samenvoegen met wat we hebben ontvangen, en uitvoeren <code>replace<\/code>. Standaard laat kubectl alleen de commandoregel gebruiken <code>kubectl replace -f manifest.yaml<\/code>, waar <code>manifest.yaml<\/code> \u2014 al een volledig voorbereide (in ons geval \u2014 samengevoegde) manifest die moet worden ge\u00efnstalleerd. Dit betekent dat de gebruiker de samenvoeging van manifesten moet implementeren, wat geen triviale taak is...<\/p>\n<p>Het moet ook worden opgemerkt dat hoewel <code>manifest.yaml<\/code> het in Git is opgeslagen, we niet vooraf kunnen weten of een object moet worden gemaakt of bijgewerkt \u2014 dit moet door de gebruikerssoftware worden gedaan.<\/p>\n<p>Kortom: <b>kunnen we een continue uitrol bouwen<\/b> alleen met behulp van create, replace en delete, waarbij we de infrastructuurconfiguratie in Git opslaan samen met de code en een handige CI\/CD bieden?<\/p>\n<p>In principe kunnen we dat\u2026 Hiervoor <b>is het nodig om de operatie samenvoegen<\/b> van manifesten en een soort omhulsel te implementeren dat:<\/p>\n<ul>\n<li> de aanwezigheid van het object in de cluster controleert,<\/li>\n<li> de initi\u00eble creatie van de resource uitvoert,<\/li>\n<li> deze bijwerkt of verwijdert.<\/li>\n<\/ul>\n<p>\nBij een update moet rekening worden gehouden met het feit dat <i>de resource kan zijn veranderd<\/i> sinds de laatste <code>krijgen<\/code> en automatisch de situatie van optimistische locking moet verwerken \u2014 herhaaldelijke pogingen tot een update uitvoeren.<\/p>\n<p>Maar waarom het wiel opnieuw uitvinden, als kube-apiserver een andere manier biedt om resources bij te werken: de operatie <code>patch<\/code>, die enkele van de hierboven beschreven problemen voor de gebruiker oplost?<\/p>\n<h3>Patch<\/h3>\n<p>\nHier zijn we dan aangekomen bij patches.<\/p>\n<p>Patches zijn de belangrijkste manier om wijzigingen aan te brengen in bestaande objecten in Kubernetes. De operatie <code>patch<\/code> werkt zodanig dat:<\/p>\n<ul>\n<li> de gebruiker van kube-apiserver een patch in JSON-vorm moet versturen en het object moet opgeven,<\/li>\n<li> en de apiserver zelf de huidige staat van het object zal analyseren en het naar de vereiste toestand zal brengen.<\/li>\n<\/ul>\n<p>\nOptimistische locking is in dit geval niet vereist. Deze operatie is meer declaratief in vergelijking met replace, hoewel het in eerste instantie misschien anders lijkt.<\/p>\n<p>Dus:<\/p>\n<ul>\n<li> met de operatie <code>create<\/code> maken we een object aan volgens het manifest uit Git,<\/li>\n<li> met behulp van <code>Verwijder afbeeldingen<\/code> \u2014 verwijderen we het, als het object niet meer nodig is,<\/li>\n<li> met behulp van <code>patch<\/code> \u2014 wijzigen we het object en brengen we het in de staat zoals beschreven in Git.<\/li>\n<\/ul>\n<p>\nEchter, om dit te doen, moet je <i>de juiste patch maken<\/i>!<\/p>\n<h3>Hoe patches werken in Helm 2: 2-way-merge<\/h3>\n<p>\nBij de eerste installatie van de Helm-release voert het <code>create<\/code> een operatie uit voor de resources van de chart.<\/p>\n<p>Bij het updaten van de Helm-release:<\/p>\n<ul>\n<li> wordt de patch berekend tussen de versie van de resource uit de vorige chart en de huidige versie van de chart,<\/li>\n<li> deze patch wordt toegepast.<\/li>\n<\/ul>\n<p>\nDeze patch noemen we <b>2-way-merge patch<\/b>, omdat bij het maken ervan 2 manifesten betrokken zijn:<\/p>\n<ul>\n<li> het manifest van de resource uit de vorige release,<\/li>\n<li> het manifest van de resource uit de huidige versie.<\/li>\n<\/ul>\n<p>\nBij verwijdering wordt de operatie <code>Verwijder afbeeldingen<\/code> in kube apiserver aangeroepen voor resources die zijn verklaard in de vorige release, maar niet in de huidige.<\/p>\n<p>De aanpak van de 2 way merge patch heeft een probleem: het leidt tot <b>desynchronisatie van de werkelijke toestand van de resource in de cluster en het manifest in Git<\/b>.<\/p>\n<h3>Een illustratie van het probleem aan de hand van<\/h3>\n<p><\/p>\n<ul>\n<li> In Git wordt in de chart een manifest opgeslagen waarin het veld <code>afbeelding<\/code> bij de Deployment is ingesteld op <code>ubuntu:18.04<\/code>.<\/li>\n<li> De gebruiker via <code>kubectl edit<\/code> veranderde deze waarde naar <code>ubuntu:19.04<\/code>.<\/li>\n<li> Bij het opnieuw deployen van de Helm-chart <i>wordt er geen patch gegenereerd<\/i>, omdat het veld <code>afbeelding<\/code> in de vorige versie van de release en in de huidige chart hetzelfde is.<\/li>\n<li> Na de herdeploy blijft er <code>afbeelding<\/code> , hoewel in de chart staat <code>ubuntu:19.04<\/code>We hebben desynchronisatie gekregen en de declarativiteit verloren. <code>ubuntu:18.04<\/code>.<\/li>\n<\/ul>\n<p>\nWat is een gesynchroniseerde resource?<\/p>\n<h3>In het algemeen,<\/h3>\n<p>\nhet volledige <i>overeenkomst van het manifest van de resource in de actieve cluster en het manifest uit Git is onmogelijk te verkrijgen. Omdat in het echte manifest mogelijk operationele annotaties\/labels, extra containers en andere gegevens aanwezig zijn die dynamisch door sommige controllers aan de resource worden toegevoegd of verwijderd. Deze gegevens willen en kunnen we niet in Git houden. Echter willen we dat de velden die we expliciet in Git hebben opgegeven, de overeenkomstige waarden aannemen bij de uitrol.<\/i> Het resultaat is een algemene<\/p>\n<p>regel voor gesynchroniseerde resources: <b>bij de uitrol van de resource kunnen alleen de velden worden gewijzigd of verwijderd die expliciet in het manifest uit Git zijn vermeld (of die in de vorige versie zijn vermeld maar nu zijn verwijderd).<\/b>3-way-merge patch<\/p>\n<h3>: genereert een patch tussen de laatste toegepaste versie van het manifest uit Git en de doelversie van het manifest uit Git, rekening houdend met de huidige versie van het manifest uit de actieve cluster. De uiteindelijke patch moet voldoen aan de regel voor gesynchroniseerde resources:<\/h3>\n<p>\nHet belangrijkste idee <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Merge_(version_control)#Three-way_merge\">: genereert een patch tussen de laatste toegepaste versie van het manifest uit Git en de doelversie van het manifest uit Git, rekening houdend met de huidige versie van het manifest uit de actieve cluster. De uiteindelijke patch moet voldoen aan de regel voor gesynchroniseerde resources:<\/a><\/noindex>nieuwe velden die aan de doelversie zijn toegevoegd, worden met behulp van de patch toegevoegd;<\/p>\n<ul>\n<li> nieuwe velden die aan de doelversie zijn toegevoegd, worden toegevoegd via een patch;<\/li>\n<li> Veld die eerder bestonden in de laatst toegepaste versie en die niet bestaan in de doelversie worden op nul gezet met behulp van een patch;<\/li>\n<li> Velden in de huidige versie van het object die verschillen van de doelversie van het manifest worden bijgewerkt met behulp van een patch.<\/li>\n<\/ul>\n<p>\nOp deze manier genereert de patch <code>kubectl apply<\/code>:<\/p>\n<ul>\n<li> de laatst toegepaste versie van het manifest wordt opgeslagen in de annotatie van het object zelf, <\/li>\n<li> de doelversie wordt uit het opgegeven YAML-bestand gehaald,<\/li>\n<li> de huidige versie komt uit de actieve cluster.<\/li>\n<\/ul>\n<p>\nNu we de theorie hebben begrepen, is het tijd om te vertellen wat we in werf hebben gedaan.<\/p>\n<h2>Toepassing van wijzigingen in werf<\/h2>\n<p>\nEerder gebruikte werf, net als Helm 2, 2-way-merge patches.<\/p>\n<h3>Repair patch<\/h3>\n<p>\nOm over te schakelen naar het nieuwe type patches - 3-way-merge - hebben we als eerste stap de zogenaamde <b>repair-patches ge\u00efntroduceerd<\/b>.<\/p>\n<p>Bij het deployen wordt de standaard 2-way-merge patch gebruikt, maar werf genereert daarnaast een patch die de werkelijke staat van de bron in sync brengt met wat in Git is geschreven (deze patch wordt gemaakt met gebruik van dezelfde regels voor gesynchroniseerde bronnen die hierboven zijn beschreven).<\/p>\n<p>In het geval van desynchronisatie ontvangt de gebruiker aan het einde van de deployment een WAARSCHUWING met het bijbehorende bericht en een patch die moet worden toegepast om de bron in een gesynchroniseerde staat te brengen. Deze patch wordt ook geregistreerd in een speciale annotatie <code>werf.io\/repair-patch<\/code>. Er wordt aangenomen dat de gebruiker handmatig <b>zelf<\/b> deze patch toepast: werf zal dit principieel niet doen.<\/p>\n<p>Het genereren van repair-patches is een tijdelijke maatregel die het mogelijk maakt om het maken van patches volgens het 3-way-merge principe uit te testen, maar deze patches automatisch niet toe te passen. Momenteel is deze werkwijze standaard ingeschakeld.<\/p>\n<h3>3-way-merge patch alleen voor nieuwe releases<\/h3>\n<p>\nVanaf 1 december 2019 beginnen beta- en alpha-versies van werf <b>standaard<\/b> volwaardige 3-way-merge patches te gebruiken voor het aanbrengen van wijzigingen alleen voor nieuwe Helm-releases die via werf worden uitgerold. Bestaande releases blijven de aanpak met 2-way-merge + repair-patches gebruiken.<\/p>\n<p>Deze werkwijze kan expliciet worden ingeschakeld door de instelling <code>WERF_THREE_WAY_MERGE_MODE=onlyNewReleases<\/code> al nu beschikbaar.<\/p>\n<p><i><b>Opmerking<\/b>: de functie is door verschillende releases in werf beschikbaar gesteld: in de alpha-channel is het beschikbaar sinds versie <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\/releases\/tag\/v1.0.5-alpha.19\">v1.0.5-alpha.19<\/a><\/noindex>, en in de beta-channel sinds <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 voor alle releases<\/h3>\n<p>\nVanaf 15 december 2019 beginnen beta- en alpha-versies van werf standaard volledige 3-way-merge patches te gebruiken om wijzigingen aan te brengen voor alle releases.<\/p>\n<p>Deze werkwijze kan expliciet worden ingeschakeld door de instelling <code>WERF_THREE_WAY_MERGE_MODE=enabled<\/code> al nu beschikbaar.<\/p>\n<h3>Hoe om te gaan met de automatische schaling van middelen?<\/h3>\n<p>\nIn Kubernetes zijn er 2 typen automatische schaling: HPA (horizontaal) en VPA (verticaal).<\/p>\n<p>Horizontaal kiest automatisch het aantal replica's, verticaal de hoeveelheid middelen. Zowel het aantal replica's als de eisen voor middelen worden gespecificeerd in de manifest van de bron (zie <code>spec.replicas<\/code> of <code>spec.containers[].resources.limits.cpu<\/code>, <code>spec.containers[].resources.limits.memory<\/code> en <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/configuration\/manage-compute-resources-container\/#resource-requests-and-limits-of-pod-and-container\">andere<\/a><\/noindex>).<\/p>\n<p>Probleem: als een gebruiker de bron in de chart zo configureert dat er specifieke waarden voor middelen of replica's worden opgegeven en autoscalers zijn ingeschakeld voor deze bron, dan zal werf bij elke deployment deze waarden resetten naar wat er in de manifest van de chart is vastgelegd.<\/p>\n<p>Er zijn twee oplossingen voor het probleem. Het is het beste om expliciet vermelden van autoschaalwaarden in de manifest van de chart te vermijden. Als deze optie om een of andere reden niet geschikt is (bijvoorbeeld omdat het handig is om de initi\u00eble beperkingen voor middelen en het aantal replica's in de chart op te geven), dan biedt werf de volgende annotaties aan:<\/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>\nBij het hebben van een dergelijke annotatie zal werf de bijbehorende waarden niet bij elke deployment resetten, maar deze alleen instellen bij de eerste creatie van de bron.<\/p>\n<p>Zie voor meer informatie de projectdocumentatie over <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#deal-with-hpa\">HPA<\/a><\/noindex> en <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>Gebruik van 3-way-merge patch verbieden<\/h3>\n<p>\nDe gebruiker kan voorlopig het gebruik van nieuwe patches in werf verbieden met behulp van de omgevingsvariabele <code>WERF_THREE_WAY_MERGE_MODE=disabled<\/code>. Echter, vanaf <b>1 maart 2020 zal dit verbod niet meer van kracht zijn<\/b> en zal alleen het gebruik van 3-way-merge patches mogelijk zijn.<\/p>\n<h2>Adoptie van middelen in werf<\/h2>\n<p>\nDe implementatie van de methode voor het aanbrengen van wijzigingen via 3-way-merge patches heeft het ons mogelijk gemaakt om direct een functie te implementeren zoals de adoptie van bestaande middelen in de cluster naar de Helm-release.<\/p>\n<p>Helm 2 heeft een probleem: het is niet mogelijk om een bron die al in de cluster bestaat, aan de manifeste van de chart toe te voegen zonder deze bron vanaf nul opnieuw te cre\u00ebren (zie <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>). We hebben werf geleerd om bestaande bronnen in de release te accepteren. Hiervoor moet aan de huidige versie van de bron uit de werkende cluster een annotatie worden toegevoegd (bijvoorbeeld met behulp van <code>kubectl edit<\/code>):<\/p>\n<pre><code class=\"plaintext\">\"werf.io\/allow-adoption-by-release\": RELEASE_NAME<\/code><\/pre>\n<p>\nNu moet de bron in de chart worden beschreven en bij de volgende uitrol van de werf met de bijbehorende naam zal de bestaande bron in deze release worden opgenomen en onder zijn beheer blijven. Bovendien zal werf, tijdens het opnemen van de bron in de release, de huidige staat van de bron uit het werkende cluster naar de staat, beschreven in de chart, brengen, gebruikmakend van dezelfde 3-way-merge-patches en de regel van de gesynchroniseerde bron.<\/p>\n<p><i><b>Opmerking<\/b>: configuratie <code>WERF_THREE_WAY_MERGE_MODE<\/code> heeft geen invloed op de adoptie van bronnen \u2014 bij adoptie wordt altijd een 3-way-merge-patch gebruikt.<\/i><\/p>\n<p>Details zijn te vinden in <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#resources-adoption\">de documentatie<\/a><\/noindex>.<\/p>\n<h2>Conclusies en toekomstige plannen<\/h2>\n<p>\nIk hoop dat na dit artikel duidelijker is geworden wat 3-way-merge-patches zijn en waarom we hiervoor hebben gekozen. Vanuit praktisch oogpunt is de implementatie hiervan in het werf-project een stap voorwaarts voor het verbeteren van de Helm-achtige uitrol. We kunnen nu de synchronisatieproblemen met configuratie vergeten, die vaak voorkwamen bij het gebruik van Helm 2. Tegelijkertijd is er een nieuwe handige functie toegevoegd voor de adoptie van al gedownloade Kubernetes-bronnen in de Helm-release.<\/p>\n<p>Bij de Helm-achtige uitrol blijven er echter nog steeds enkele problemen en moeilijkheden bestaan, zoals het gebruik van Go-templates, en we zullen deze blijven oplossen.<\/p>\n<p>Informatie over de methoden voor het bijwerken van bronnen en adoptie is ook te vinden op <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html\">deze documentatiepagina<\/a><\/noindex>.<\/p>\n<h3>Helm 3<\/h3>\n<p>\nEen aparte opmerking waard is <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/news\/t\/475722\/\">de recentelijk uitgebrachte<\/a><\/noindex> letterlijk enkele dagen geleden nieuwe majeure versie van Helm \u2014 v3, \u2014 die ook 3-way-merge-patches gebruikt en zich ontdoet van Tiller. De nieuwe versie van Helm vereist <noindex><a rel=\"nofollow\" href=\"https:\/\/helm.sh\/docs\/topics\/v2_v3_migration\/\">migratie<\/a><\/noindex> van bestaande installaties om ze om te zetten naar het nieuwe opslagformaat voor releases.<\/p>\n<p>Werf heeft op dit moment al geen gebruik meer van Tiller en is overgestapt op 3-way-merge en heeft <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/differences_with_helm.html\">veel meer toegevoegd<\/a><\/noindex>, terwijl het compatibel is gebleven met de bestaande installaties op Helm 2 (er hoeven geen migratiescripts te worden uitgevoerd). Daarom, zolang werf niet is overgestapt op Helm 3, verliezen werf-gebruikers geen van de belangrijke voordelen van Helm 3 ten opzichte van Helm 2 (deze zijn er ook in werf).<\/p>\n<p>Desondanks is de overstap van werf naar de codebasis van Helm 3 onvermijdelijk en zal deze in de nabije toekomst plaatsvinden. Naar verwachting zal dit werf 1.1 of werf 1.2 zijn (op dit moment is de hoofdversie van werf \u2014 1.0; voor meer informatie over de versie-structuur van werf zie <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf#backward-compatibility-promise\">hier<\/a><\/noindex>). In de tussentijd zal Helm 3 stabieler worden.<\/p>\n<h2>P.S.<\/h2>\n<p>\nLees ook op onze blog:<\/p>\n<ul>\n<li> Een cyclus van notities over de innovaties in werf:\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/468049\/\">Het gebruik van werf voor het uitrollen van complexe Helm-charts<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465131\/\">Ondersteuning voor monorepo en multirepo in werf en wat Docker Registry hiermee te maken heeft<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/463613\/\">Docker-images kunnen nu ook met werf worden gebouwd met een gewone 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 onze tool voor CI\/CD in Kubernetes (overzicht en video van de presentatie)<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/469541\/\">Opbouw en implementatie van homogene microservices met werf en GitLab CI<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/453734\/\">Kennismaking met Helm 3<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Bron: <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\/nl\/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=\"nl_NL\" \/>\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\/nl\/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-way merge in werf: implementatie in Kubernetes met Helm 'op stero\u00efden' | ProHoster","description":"Het is gebeurt waar wij (en niet alleen wij) lang op hebben gewacht: werf, onze Open Source-tool voor het bouwen van applicaties en het uitvoeren ervan in Kubernetes, wordt nu ondersteund.","canonical_url":"https:\/\/prohoster.info\/nl\/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":"nl_NL","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\/nl\/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\/nl\/wp-json\/wp\/v2\/posts\/53120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=53120"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/53120\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/53121"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=53120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=53120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=53120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}