{"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\/ro\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah","title":{"rendered":"\u00cembinarea 3-way \u00een werf: desf\u0103\u0219urare \u00een Kubernetes cu Helm \u00abpe steroizi\u00bb","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>S-a \u00eent\u00e2mplat ceea ce noi (\u0219i nu doar noi) am a\u0219teptat mult timp: <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/\">werf<\/a><\/noindex>, utilitarul nostru Open Source pentru construirea aplica\u021biilor \u0219i livrarea acestora \u00een Kubernetes, acum suport\u0103 aplicarea modific\u0103rilor prin patch-uri de tip 3-way-merge! \u00cen plus, a ap\u0103rut posibilitatea adopt\u0103rii resurselor K8s existente \u00een lans\u0103rile Helm f\u0103r\u0103 a recrea aceste resurse.<\/p>\n<p><img decoding=\"async\" alt=\"\u00cembinarea 3-way \u00een werf: desf\u0103\u0219urare \u00een Kubernetes cu Helm \u00abpe steroizi\u00bb\" src=\"\/wp-content\/uploads\/2019\/11\/e5be3544c201f7b2c97fba216a49506d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nDac\u0103 trebuie s\u0103 fie foarte pe scurt, atunci set\u0103m <code>WERF_THREE_WAY_MERGE=enabled<\/code> \u2014 ob\u021binem un deployment \u201eca \u00een <code>kubectl apply<\/code>\u201d, compatibil cu instal\u0103rile existente pe Helm 2 \u0219i chiar pu\u021bin mai mult.<\/p>\n<p>Dar s\u0103 \u00eencepem cu teoria: ce este, de fapt, patch-ul de tip 3-way-merge, cum au ajuns oamenii la abordarea gener\u0103rii acestuia \u0219i de ce sunt importante \u00een procesele CI\/CD cu infrastructura bazat\u0103 pe Kubernetes? \u0218i dup\u0103 aceea, vom vedea ce reprezint\u0103 3-way-merge \u00een werf, ce moduri sunt folosite implicit \u0219i cum putem gestiona acest lucru.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Ce este un patch de tip 3-way-merge?<\/h2>\n<p>\nA\u0219adar, s\u0103 \u00eencepem cu sarcina de a desf\u0103\u0219ura resursele descrise \u00een manifestele YAML \u00een Kubernetes.<\/p>\n<p>Pentru a lucra cu resursele Kubernetes, API-ul ofer\u0103 urm\u0103toarele opera\u021bii de baz\u0103: create, patch, replace \u0219i delete. Se presupune c\u0103 prin intermediul acestora trebuie s\u0103 construim un rollout continuu convenabil al resurselor \u00een cluster. Cum?<\/p>\n<h3>Comenzile imperativ\u0103 kubectl<\/h3>\n<p>\nPrima abordare pentru gestionarea obiectelor \u00een Kubernetes este utilizarea comenzilor imperativ\u0103 kubectl pentru a crea, modifica \u0219i \u0219terge aceste obiecte. Cu alte cuvinte:<\/p>\n<ul>\n<li> comanda <code>kubectl run<\/code> poate lansa un Deployment sau Job:\n<pre><code class=\"bash\">kubectl run --generator=deployment\/apps.v1 DEPLOYMENT_NAME --image=IMAGE<\/code><\/pre>\n<\/li>\n<li> comanda <code>kubectl scale<\/code> \u2014 schimb\u0103 num\u0103rul de replici:\n<pre><code class=\"bash\">kubectl scale --replicas=3 deployment\/mysql<\/code><\/pre>\n<\/li>\n<li>etc.<\/li>\n<\/ul>\n<p>\nAceast\u0103 abordare poate p\u0103rea convenabil\u0103 la prima vedere. Cu toate acestea, exist\u0103 probleme: <\/p>\n<ol>\n<li> Este dificil <b>de automatizat<\/b>.<\/li>\n<li> Cum <b>a reflecta configura\u021bia<\/b> \u00een Git? Cum se face revizuirea modific\u0103rilor care au loc cu clusterul?<\/li>\n<li> Cum s\u0103 asigur\u0103m <b>reproductibilitatea<\/b> configura\u021biei la repornire?<\/li>\n<li>\u2026<\/li>\n<\/ol>\n<p>\nE clar c\u0103 aceast\u0103 abordare nu se potrive\u0219te bine cu p\u0103strarea \u00eempreun\u0103 cu codul aplica\u021biei \u0219i infrastructura ca cod (IaC; sau chiar <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/458878\/\">GitOps<\/a><\/noindex> ca o variant\u0103 mai modern\u0103, care c\u00e2\u0219tig\u0103 popularitate \u00een ecosistemul Kubernetes). Prin urmare, aceste comenzi din kubectl nu au primit dezvolt\u0103ri ulterioare.<\/p>\n<h3>Opera\u021biile create, ob\u021bine, \u00eenlocuie\u0219te \u0219i \u0219terge<\/h3>\n<p>\nCu crearea ini\u021bial\u0103 <b>totul este simplu: trimitem manifestul la opera\u021bia<\/b> la kube api \u0219i resursa este creat\u0103. Reprezentarea YAML a manifestului poate fi p\u0103strat\u0103 \u00een Git, iar pentru creare se poate folosi comanda <code>create<\/code> kubectl create -f manifest.yaml <code>\u0219tergerea<\/code>.<\/p>\n<p>Cu <b>de asemenea, este simpl\u0103: introducem acela\u0219i<\/b> manifest.yaml <code>din Git \u00een comanda<\/code> kubectl delete -f manifest.yaml <code>replace<\/code>.<\/p>\n<p>Opera\u021bia <b><code>replace<\/code><\/b> permite \u00eenlocuirea complet\u0103 a configura\u021biei unei resurse cu una nou\u0103, f\u0103r\u0103 a recrea resursa. Acest lucru \u00eenseamn\u0103 c\u0103, \u00eenainte de a efectua modific\u0103ri asupra resursei, este logic s\u0103 cerem versiunea curent\u0103 printr-o opera\u021biune <code>get<\/code>, s\u0103 o modific\u0103m \u0219i s\u0103 actualiz\u0103m printr-o opera\u021biune <code>replace<\/code>. \u00cen kube apiserver este integrat <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Optimistic_concurrency_control\">optimistic locking<\/a><\/noindex> , iar dac\u0103 obiectul a fost modificat dup\u0103 opera\u021biune <code>get<\/code> , opera\u021biunea <code>replace<\/code> nu va reu\u0219i.<\/p>\n<p>Pentru a stoca configura\u021bia \u00een Git \u0219i a actualiza folosind replace, trebuie s\u0103 efectuezi opera\u021biunea <code>get<\/code>, s\u0103 faci un merge al configura\u021biei din Git cu ceea ce am ob\u021binut \u0219i s\u0103 execut\u0103m <code>replace<\/code>. \u00cen mod standard, kubectl permite doar utilizarea comenzii <code>kubectl replace -f manifest.yaml<\/code>, unde <code>din Git \u00een comanda<\/code> \u2014 un manifest complet preg\u0103tit (\u00een cazul nostru, \u00eembinat) care trebuie instalat. A\u0219adar, utilizatorului \u00eei revine sarcina de a realiza un merge al manifestelor, lucru ce nu este trivial...<\/p>\n<p>De asemenea, merit\u0103 men\u021bionat c\u0103, de\u0219i <code>din Git \u00een comanda<\/code> este stocat \u00een Git, nu putem \u0219ti dinainte dac\u0103 trebuie s\u0103 cre\u0103m obiectul sau s\u0103-l actualiz\u0103m \u2014 acest lucru trebuie s\u0103-l fac\u0103 software-ul utilizatorului.<\/p>\n<p>\u00cen total: <b>putem construi un rollout continuu<\/b> doar cu ajutorul create, replace \u0219i delete, asigur\u00e2nd stocarea configura\u021biei infrastructurii \u00een Git \u00eempreun\u0103 cu codul \u0219i un CI\/CD convenabil?<\/p>\n<p>\u00cen principiu, putem... Pentru aceasta <b>va trebui s\u0103 implement\u0103m opera\u021biunea de merge<\/b> a manifestelor \u0219i o anumit\u0103 interfa\u021b\u0103 care:<\/p>\n<ul>\n<li> verific\u0103 existen\u021ba obiectului \u00een cluster,<\/li>\n<li> efectueaz\u0103 crearea ini\u021bial\u0103 a resursei,<\/li>\n<li> o actualizeaz\u0103 sau o \u0219terge.<\/li>\n<\/ul>\n<p>\nLa actualizare trebuie s\u0103 \u021binem cont c\u0103 <i>resursa ar fi putut fi modificat\u0103<\/i> \u00eentre timp <code>get<\/code> \u0219i s\u0103 gestion\u0103m automat cazul de optimistic locking \u2014 s\u0103 facem \u00eencerc\u0103ri repetate de actualizare.<\/p>\n<p>Totu\u0219i, de ce s\u0103 invent\u0103m bicicleta, c\u00e2nd kube-apiserver ofer\u0103 o alt\u0103 modalitate de a actualiza resursele: opera\u021biunea <code>patch<\/code>, care ia de pe umerii utilizatorului o parte din problemele descrise?<\/p>\n<h3>Patch<\/h3>\n<p>\nIat\u0103 c\u0103 am ajuns la patch-uri.<\/p>\n<p>Patch-urile sunt modul principal de a aplica modific\u0103ri obiectelor existente \u00een Kubernetes. Opera\u021biunea <code>patch<\/code> func\u021bioneaz\u0103 astfel \u00eenc\u00e2t:<\/p>\n<ul>\n<li> utilizatorul kube-apiserver trebuie s\u0103 trimit\u0103 un patch \u00een format JSON \u0219i s\u0103 indice obiectul,<\/li>\n<li> iar apiserver-ul se va descurca singur cu starea curent\u0103 a obiectului \u0219i \u00eel va aduce \u00een forma dorit\u0103.<\/li>\n<\/ul>\n<p>\nOptimistic locking \u00een acest caz nu este necesar. Aceast\u0103 opera\u021biune este mai declarativ\u0103 \u00een compara\u021bie cu replace, de\u0219i ini\u021bial poate p\u0103rea invers.<\/p>\n<p>Astfel:<\/p>\n<ul>\n<li> prin opera\u021biunea <code>create<\/code> cre\u0103m un obiect conform manifestului din Git,<\/li>\n<li> folosind <code>delete<\/code> \u2014 \u0219tergem, dac\u0103 obiectul nu mai este necesar,<\/li>\n<li> folosind <code>patch<\/code> \u2014 modific\u0103m obiectul, adapt\u00e2ndu-l la forma descris\u0103 \u00een Git.<\/li>\n<\/ul>\n<p>\nCu toate acestea, pentru a face acest lucru, trebuie s\u0103 cre\u0103m <i>patch-ul corect<\/i>!<\/p>\n<h3>Cum func\u021bioneaz\u0103 patch-urile \u00een Helm 2: 2-way-merge<\/h3>\n<p>\nLa prima instalare a release-ului, Helm execut\u0103 opera\u021bia <code>create<\/code> pentru resursele chart-ului.<\/p>\n<p>La actualizarea release-ului Helm pentru fiecare resurs\u0103:<\/p>\n<ul>\n<li> calculeaz\u0103 patch-ul \u00eentre versiunea resursei din chart-ul anterior \u0219i versiunea curent\u0103 a chart-ului,<\/li>\n<li> aplic\u0103 acest patch.<\/li>\n<\/ul>\n<p>\nAcest patch \u00eel vom numi <b>2-way-merge patch<\/b>, pentru c\u0103 \u00een crearea sa sunt implicate 2 manifest\u0103ri:<\/p>\n<ul>\n<li> manifestarea resursei din release-ul anterior,<\/li>\n<li> manifestarea resursei din resursa curent\u0103.<\/li>\n<\/ul>\n<p>\nLa eliminare, opera\u021bia <code>delete<\/code> \u00een kube apiserver este apelat\u0103 pentru resursele care au fost declarate \u00een release-ul anterior, dar nu sunt declarate \u00een cel curent.<\/p>\n<p>Abordarea cu 2-way merge patch are o problem\u0103: duce la <b>desincronizarea st\u0103rii reale a resursei \u00een cluster \u0219i a manifestului din Git<\/b>.<\/p>\n<h3>Ilustrarea problemei prin exemplu<\/h3>\n<p><\/p>\n<ul>\n<li> \u00cen Git, \u00een chart se p\u0103streaz\u0103 un manifest, \u00een care c\u00e2mpul <code>imagine<\/code> la Deployment are valoarea <code>ubuntu:18.04<\/code>.<\/li>\n<li> Utilizatorul a <code>kubectl edit<\/code> schimbat valoarea acestui c\u00e2mp \u00een <code>ubuntu:19.04<\/code>.<\/li>\n<li> La redeploy-ul chart-ului Helm, <i>nu se genereaz\u0103 patch,<\/i>deoarece c\u00e2mpul <code>imagine<\/code> \u00een versiunea anterioar\u0103 a release-ului \u0219i \u00een chart-ul curent sunt identice.<\/li>\n<li> Dup\u0103 redeploy, <code>imagine<\/code> r\u0103m\u00e2ne <code>ubuntu:19.04<\/code>, de\u0219i \u00een chart scrie <code>ubuntu:18.04<\/code>.<\/li>\n<\/ul>\n<p>\nAm ob\u021binut desincronizare \u0219i am pierdut caracterul declarativ.<\/p>\n<h3>Ce este o resurs\u0103 sincronizat\u0103?<\/h3>\n<p>\n\u00cen general, <i>completa<\/i> coresponden\u021b\u0103 a manifestului resursei din cluster-ul activ \u0219i a manifestului din Git nu este posibil\u0103. Pentru c\u0103 \u00een manifestul real pot exista juc\u0103rii de servicii\/etichete, containere adi\u021bionale \u0219i alte date, ad\u0103ugate \u0219i eliminate din resurs\u0103 dinamic de c\u0103tre anumi\u021bi controleri. Aceste date nu putem \u0219i nu vrem s\u0103 le p\u0103str\u0103m \u00een Git. Totu\u0219i, dorim ca \u00een momentul roll-out-ului, c\u00e2mpurile pe care le-am specificat clar \u00een Git s\u0103 aib\u0103 valorile corespunz\u0103toare.<\/p>\n<p>Se ob\u021bine o astfel de regul\u0103 general\u0103 <b>pentru resursa sincronizat\u0103<\/b>: la roll-out-ul resursei se pot schimba sau elimina doar acele c\u00e2mpuri care sunt specificate clar \u00een manifestul din Git (sau care au fost specificate \u00een versiunea anterioar\u0103 \u0219i acum au fost eliminate).<\/p>\n<h3>3-way-merge patch<\/h3>\n<p>\nIdeea principal\u0103 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Merge_(version_control)#Three-way_merge\">3-way-merge patch<\/a><\/noindex>: gener\u0103m un patch \u00eentre cea mai recent aplicat\u0103 versiune a manifestului din Git \u0219i versiunea \u021bint\u0103 a manifestului din Git, av\u00e2nd \u00een vedere versiunea curent\u0103 a manifestului din cluster-ul activ. Patch-ul final trebuie s\u0103 respecte regula resursei sincronizate:<\/p>\n<ul>\n<li> C\u00e2mpurile noi ad\u0103ugate \u00een versiunea \u021bint\u0103 sunt integrate printr-un patch;<\/li>\n<li> C\u00e2mpurile existente \u00een ultima versiune aplicat\u0103 \u0219i care nu exist\u0103 \u00een cea \u021bint\u0103 sunt resetate prin patch;<\/li>\n<li> C\u00e2mpurile din versiunea curent\u0103 a obiectului, diferite de versiunea \u021bint\u0103 a manifestului, sunt actualizate prin patch.<\/li>\n<\/ul>\n<p>\nAcesta este principiul de baz\u0103 pe care patch-urile sunt generate <code>kubectl apply<\/code>:<\/p>\n<ul>\n<li> ultima versiune aplicat\u0103 a manifestului este p\u0103strat\u0103 \u00een adnotarea obiectului \u00eensu\u0219i, <\/li>\n<li> versiunea \u021bint\u0103 este preluat\u0103 din fi\u0219ierul YAML specificat,<\/li>\n<li> versiunea curent\u0103 este din clusterul activ.<\/li>\n<\/ul>\n<p>\nAcum c\u0103 am clarificat teoria, este timpul s\u0103 discut\u0103m ce am realizat \u00een werf.<\/p>\n<h2>Aplicarea modific\u0103rilor \u00een werf<\/h2>\n<p>\nAnterior, werf, la fel ca Helm 2, folosea patch-uri de tip 2-way-merge.<\/p>\n<h3>Repair patch<\/h3>\n<p>\nPentru a trece la un nou tip de patch-uri \u2014 3-way-merge \u2014 primul pas a fost introducerea a\u0219a-numitelor <b>repair-patch-uri<\/b>.<\/p>\n<p>La desf\u0103\u0219urare se folose\u0219te un patch standard de tip 2-way-merge, dar werf genereaz\u0103 suplimentar un patch care sincronizeaz\u0103 starea real\u0103 a resursei cu ceea ce este scris \u00een Git (se creeaz\u0103 un astfel de patch folosind aceea\u0219i regul\u0103 de resurs\u0103 sincronizat\u0103, descris\u0103 mai sus).<\/p>\n<p>\u00cen caz de desincronizare, la finalul desf\u0103\u0219ur\u0103rii, utilizatorul prime\u0219te un WARNING cu un mesaj corespunz\u0103tor \u0219i un patch care trebuie aplicat pentru a readuce resursa \u00een starea sincronizat\u0103. De asemenea, acest patch este \u00eenregistrat \u00eentr-o adnotare special\u0103 <code>werf.io\/repair-patch<\/code>. Se preconizeaz\u0103 c\u0103 utilizatorul \u00eel va aplica manual, <b>singur<\/b> acest patch: werf nu \u00eel va aplica \u00een mod automat.<\/p>\n<p>Generarea repair-patch-urilor este o m\u0103sur\u0103 temporar\u0103 care permite testarea cre\u0103rii patch-urilor pe baza principiului 3-way-merge, dar aceste patch-uri nu sunt aplicate automat. \u00cen prezent, acest mod de func\u021bionare este activat \u00een mod implicit.<\/p>\n<h3>Patch-ul 3-way-merge este disponibil doar pentru noi versiuni<\/h3>\n<p>\n\u00cencep\u00e2nd cu 1 decembrie 2019, versiunile beta \u0219i alpha ale werf \u00eencep <b>implicit<\/b> s\u0103 foloseasc\u0103 patch-uri 3-way-merge complete pentru aplicarea modific\u0103rilor doar pentru noile release-uri Helm desf\u0103\u0219urate prin werf. Versiunile deja existente vor continua s\u0103 utilizeze abordarea 2-way-merge + repair-patch-uri.<\/p>\n<p>Acest mod de func\u021bionare poate fi activat explicit prin configurarea <code>WERF_THREE_WAY_MERGE_MODE=onlyNewReleases<\/code> \u00een prezent.<\/p>\n<p><i><b>Not\u0103<\/b>: func\u021bionalitatea a fost introdus\u0103 \u00een werf \u00een mai multe release-uri: \u00een canalul alpha a devenit disponibil\u0103 cu versiunea <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\/releases\/tag\/v1.0.5-alpha.19\">v1.0.5-alpha.19<\/a><\/noindex>, iar \u00een canalul beta \u2014 cu <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>patch-ul 3-way-merge pentru toate versiunile<\/h3>\n<p>\n\u00cencep\u00e2nd cu 15 decembrie 2019, versiunile beta \u0219i alpha ale werf vor utiliza implicit patch-uri complete 3-way-merge pentru aplicarea modific\u0103rilor \u00een toate versiunile.<\/p>\n<p>Acest mod de func\u021bionare poate fi activat explicit prin configurarea <code>WERF_THREE_WAY_MERGE_MODE=enabled<\/code> \u00een prezent.<\/p>\n<h3>Ce trebuie s\u0103 facem \u00een leg\u0103tur\u0103 cu scalarea automat\u0103 a resurselor?<\/h3>\n<p>\n\u00cen Kubernetes exist\u0103 2 tipuri de scalare automat\u0103: HPA (orizontal) \u0219i VPA (vertical).<\/p>\n<p>Scalarea orizontal\u0103 alege automat num\u0103rul de replici, iar scalarea vertical\u0103 \u2013 resursele necesare. At\u00e2t num\u0103rul de replici, c\u00e2t \u0219i cerin\u021bele de resurse sunt specificate \u00een manifestul resursei (vezi. <code>spec.replicas<\/code> sau <code>spec.containers[].resources.limits.cpu<\/code>, <code>spec.containers[].resources.limits.memory<\/code> \u0219i <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/configuration\/manage-compute-resources-container\/#resource-requests-and-limits-of-pod-and-container\">altele<\/a><\/noindex>).<\/p>\n<p>Problema: dac\u0103 utilizatorul configureaz\u0103 resursa \u00een chart astfel \u00eenc\u00e2t s\u0103 con\u021bin\u0103 valori definite pentru resurse sau replici \u0219i pentru aceast\u0103 resurs\u0103 sunt activate autoscaler-ii, atunci la fiecare deploy, werf va reseta aceste valori la cele specificate \u00een manifestul chart-ului.<\/p>\n<p>Sunt dou\u0103 solu\u021bii pentru aceast\u0103 problem\u0103. \u00cen primul r\u00e2nd, este cel mai bine s\u0103 renun\u021be la specificarea explicit\u0103 a valorilor scalabile \u00een manifestul chart-ului. Dac\u0103 totu\u0219i aceast\u0103 op\u021biune nu este potrivit\u0103 din diverse motive (de exemplu, deoarece este convenabil s\u0103 define\u0219ti limit\u0103rile ini\u021biale ale resurselor \u0219i num\u0103rul de replici \u00een chart), werf ofer\u0103 urm\u0103toarele anota\u021bii:<\/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>\n\u00cen cazul \u00een care exist\u0103 o astfel de anota\u021bie, werf nu va reseta valorile corespunz\u0103toare la fiecare deploy, ci le va stabili doar la crearea ini\u021bial\u0103 a resursei.<\/p>\n<p>Mai multe detalii \u2013 vezi \u00een documenta\u021bia proiectului privind <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#deal-with-hpa\">HPA<\/a><\/noindex> \u0219i <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>Interzice utilizarea patch-urilor 3-way-merge<\/h3>\n<p>\nUtilizatorul poate interzice deocamdat\u0103 utilizarea noilor patch-uri \u00een werf utiliz\u00e2nd variabila de mediu <code>WERF_THREE_WAY_MERGE_MODE=disabled<\/code>. Cu toate acestea, \u00eencep\u00e2nd cu <b>1 martie 2020, aceast\u0103 interdic\u021bie va \u00eenceta s\u0103 mai func\u021bioneze<\/b> \u0219i va fi posibil\u0103 doar utilizarea patch-urilor 3-way-merge.<\/p>\n<h2>Adoptarea resurselor \u00een werf<\/h2>\n<p>\nAdoptarea metodei de aplicare a modific\u0103rilor prin patch-uri 3-way-merge ne-a permis s\u0103 implement\u0103m imediat o caracteristic\u0103, cum ar fi adoptarea resurselor existente \u00een cluster \u00een release-urile Helm.<\/p>\n<p>Helm 2 are o problem\u0103: nu po\u021bi ad\u0103uga \u00een manifestele chart-ului o resurs\u0103 care exist\u0103 deja \u00een cluster, f\u0103r\u0103 a o recrea de la zero (vezi. <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>). Am \u00eenv\u0103\u021bat werf s\u0103 accepte resursele existente \u00een release. Pentru aceasta, trebuie s\u0103 instalezi pe versiunea curent\u0103 a resursei din cluster-ul activ o anota\u021bie (de exemplu, folosind <code>kubectl edit<\/code>):<\/p>\n<pre><code class=\"plaintext\">\"werf.io\/allow-adoption-by-release\": RELEASE_NAME<\/code><\/pre>\n<p>\nAcum resursa trebuie descris\u0103 \u00een chart \u0219i la urm\u0103torul deploy cu werf al release-ului cu numele corespunz\u0103tor, resursa existent\u0103 va fi inclus\u0103 \u00een acest release \u0219i va r\u0103m\u00e2ne sub gestionarea sa. Mai mult, \u00een procesul de acceptare a resursei \u00een release, werf va aduce starea curent\u0103 a resursei din clusterul de lucru \u00een starea descris\u0103 \u00een chart, folosind acelea\u0219i patch-uri 3-way-merge \u0219i regula resursei sincronizate.<\/p>\n<p><i><b>Not\u0103<\/b>: configurare <code>WERF_THREE_WAY_MERGE_MODE<\/code> nu afecteaz\u0103 adoptarea resurselor \u2014 \u00een cazul adopt\u0103rii se folose\u0219te \u00eentotdeauna patch-ul 3-way-merge.<\/i><\/p>\n<p>Detalii \u2014 \u00een <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#resources-adoption\">documentation<\/a><\/noindex>.<\/p>\n<h2>Concluzii \u0219i planuri viitoare<\/h2>\n<p>\nSper c\u0103, dup\u0103 acest articol, este mai clar ce sunt patch-urile 3-way-merge \u0219i de ce s-a ajuns la ele. Din perspectiva practic\u0103 a dezvolt\u0103rii proiectului werf, implementarea lor a devenit \u00eenc\u0103 un pas pe calea \u00eembun\u0103t\u0103\u021birii deploy-ului similar Helm. Acum putem uita de problemele de sincronizare a configura\u021biei, care ap\u0103reau adesea c\u00e2nd se folosea Helm 2. \u00cen acela\u0219i timp, a fost ad\u0103ugat\u0103 o nou\u0103 caracteristic\u0103 util\u0103 pentru adoptarea resurselor Kubernetes deja extrase \u00een release-urile Helm.<\/p>\n<p>\u00cen deploy-urile similare Helm r\u0103m\u00e2n \u00eenc\u0103 unele probleme \u0219i dificult\u0103\u021bi, cum ar fi utilizarea template-urilor Go, \u0219i vom continua s\u0103 le rezolv\u0103m.<\/p>\n<p>Informa\u021bii despre metodele de actualizare a resurselor \u0219i adop\u021bie pot fi g\u0103site de asemenea pe <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html\">aceast\u0103 pagin\u0103 de documenta\u021bie<\/a><\/noindex>.<\/p>\n<h3>Helm 3<\/h3>\n<p>\nMerit\u0103 men\u021bionat\u0103 \u00een mod special <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/news\/t\/475722\/\">noua versiune major\u0103 a Helm \u2014 v3, \u2014 care de asemenea utilizeaz\u0103 patch-uri 3-way-merge \u0219i renun\u021b\u0103 la Tiller. Noua versiune a Helm necesit\u0103<\/a><\/noindex> instal\u0103ri existente pentru a le transforma \u00een noul format de stocare a release-urilor. <noindex><a rel=\"nofollow\" href=\"https:\/\/helm.sh\/docs\/topics\/v2_v3_migration\/\">migrare<\/a><\/noindex> Werf, din partea sa, \u00een prezent, deja a renun\u021bat la utilizarea Tiller, a trecut la 3-way-merge \u0219i a ad\u0103ugat<\/p>\n<p>, r\u0103m\u00e2n\u00e2nd \u00een acela\u0219i timp compatibil cu instal\u0103rile existente pe Helm 2 (nu este nevoie s\u0103 se execute scripturi de migrare). Prin urmare, p\u00e2n\u0103 c\u00e2nd werf nu va trece la Helm 3, utilizatorii werf nu pierd avantajele principale ale Helm 3 fa\u021b\u0103 de Helm 2 (acestea sunt prezente \u0219i \u00een werf). <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/differences_with_helm.html\">multe altele<\/a><\/noindex>Cu toate acestea, tranzi\u021bia werf la baza de cod Helm 3 este inevitabil\u0103 \u0219i va avea loc \u00een viitorul apropiat. Se estimeaz\u0103 c\u0103 va fi werf 1.1 sau werf 1.2 (\u00een prezent, versiunea principal\u0103 a werf este 1.0; mai multe detalii despre structurarea versiunilor werf se g\u0103sesc<\/p>\n<p>). P\u00e2n\u0103 atunci, Helm 3 va avea timp s\u0103 se stabilizeze. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf#backward-compatibility-promise\">aici<\/a><\/noindex>Ciclul notelor despre nout\u0103\u021bile \u00een werf:<\/p>\n<h2>P.S.<\/h2>\n<p>\nCiti\u021bi \u0219i \u00een blogul nostru:<\/p>\n<ul>\n<li> Utilizarea werf pentru lansarea chart-urilor complexe Helm\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/468049\/\">Utilizarea werf pentru implementarea chart-urilor complex Helm<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465131\/\">Suport pentru monorepo \u0219i multirepo \u00een werf \u0219i ce leg\u0103tur\u0103 are cu Docker Registry<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/463613\/\">Acum, pute\u021bi construi imagini Docker \u00een werf \u0219i folosind un Dockerfile obi\u0219nuit<\/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 our tool for CI\/CD in Kubernetes (overview and presentation video)<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/469541\/\">Compilarea \u0219i implementarea microserviciilor asem\u0103n\u0103toare cu werf \u0219i GitLab CI<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/453734\/\">Introducere \u00een Helm 3<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Sursa: <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.2.1 - 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\/ro\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\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\/ro\/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\udd47\u00cembinarea 3-way \u00een werf: implementare \u00een Kubernetes cu Helm \u00abpe steroizi\u00bb | ProHoster","description":"S-a \u00eent\u00e2mplat ceea ce noi (\u0219i nu doar noi) a\u0219teptam de mult: werf, utilitarul nostru Open Source pentru construirea aplica\u021biilor \u0219i livrarea lor \u00een Kubernetes, acum ofer\u0103 suport.","canonical_url":"https:\/\/prohoster.info\/ro\/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":"ro_RO","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\/ro\/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\/ro\/wp-json\/wp\/v2\/posts\/53120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=53120"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/53120\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/53121"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=53120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=53120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=53120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}