{"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\/it\/blog\/administrirovanie\/3-way-merge-v-werf-deploj-v-kubernetes-s-helm-na-steroidah","title":{"rendered":"Merge a tre in werf: deployment in Kubernetes con Helm \u00abpotenziato\u00bb","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>\u00c8 successo ci\u00f2 che noi (e non solo noi) aspettavamo da tempo: <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/\">werf<\/a><\/noindex>, il nostro strumento Open Source per la creazione di applicazioni e la loro distribuzione in Kubernetes ora supporta l'applicazione delle modifiche tramite patch di 3-way-merge! In aggiunta, \u00e8 stata introdotta la possibilit\u00e0 di adottare risorse K8s esistenti nei rilasci Helm senza dover ricreare queste risorse.<\/p>\n<p><img decoding=\"async\" alt=\"Merge a tre in werf: deployment in Kubernetes con Helm \u00abpotenziato\u00bb\" src=\"\/wp-content\/uploads\/2019\/11\/e5be3544c201f7b2c97fba216a49506d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn breve, impostiamo <code>WERF_THREE_WAY_MERGE=enabled<\/code> \u2014 otteniamo un deploy \"come in <code>kubectl apply<\/code>\", compatibile con le installazioni esistenti su Helm 2 e anche un po' di pi\u00f9.<\/p>\n<p>Ma iniziamo con la teoria: che cos'\u00e8 esattamente una patch 3-way-merge, come si \u00e8 arrivati a questo approccio per la loro generazione e perch\u00e9 sono importanti nei processi CI\/CD basati su un'infrastruttura Kubernetes? Dopo di che, daremo un'occhiata a cosa rappresenta il 3-way-merge in werf, quali modalit\u00e0 sono utilizzate per impostazione predefinita e come gestirle.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Che cos'\u00e8 una patch 3-way-merge?<\/h2>\n<p>\nIniziamo con il compito di distribuire le risorse descritte nei manifest YAML in Kubernetes.<\/p>\n<p>Per lavorare con le risorse, l'API di Kubernetes offre le seguenti operazioni fondamentali: create, patch, replace e delete. Si presume che queste siano utilizzate per costruire una distribuzione continua delle risorse nel cluster. Come?<\/p>\n<h3>Comandi imperativi kubectl<\/h3>\n<p>\nIl primo approccio per gestire gli oggetti in Kubernetes \u00e8 l'uso di comandi imperativi kubectl per creare, modificare e cancellare questi oggetti. In parole povere:<\/p>\n<ul>\n<li> comando <code>kubectl run<\/code> pu\u00f2 avviare un Deployment o un Job:\n<pre><code class=\"bash\">kubectl run --generator=deployment\/apps.v1 NOME_DEPLOYMENT --image=IMMAGINE<\/code><\/pre>\n<\/li>\n<li> comando <code>kubectl scale<\/code> \u2014 cambia il numero di repliche:\n<pre><code class=\"bash\">kubectl scale --replicas=3 deployment\/mysql<\/code><\/pre>\n<\/li>\n<li>ecc.<\/li>\n<\/ul>\n<p>\nQuesto approccio pu\u00f2 sembrare conveniente a prima vista. Tuttavia, ci sono dei problemi: <\/p>\n<ol>\n<li> \u00c8 difficile <b>automatizzare<\/b>.<\/li>\n<li> Come <b>riflettere la configurazione<\/b> in Git? Come revisionare le modifiche che avvengono nel cluster?<\/li>\n<li> Come garantire <b>riproducibilit\u00e0<\/b> le configurazioni durante il riavvio?<\/li>\n<li>\u2026<\/li>\n<\/ol>\n<p>\n\u00c8 chiaro che questo approccio si adatta male all'archiviazione insieme al codice dell'applicazione e all'infrastruttura come codice (IaC; o persino <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/458878\/\">GitOps<\/a><\/noindex> come una versione pi\u00f9 moderna che sta guadagnando popolarit\u00e0 nell'ecosistema Kubernetes). Pertanto, queste comandi non hanno avuto ulteriore sviluppo.<\/p>\n<h3>Operazioni create, get, replace e delete<\/h3>\n<p>\nCon la creazione <b>iniziale<\/b> \u00e8 tutto semplice: inviamo il manifesto all'operazione <code>create<\/code> al kube api e la risorsa viene creata. La rappresentazione YAML del manifesto pu\u00f2 essere archiviata in Git, e per la creazione si pu\u00f2 usare il comando <code>kubectl create -f manifest.yaml<\/code>.<\/p>\n<p>C <b>la cancellazione<\/b> \u00e8 altrettanto semplice: inseriamo lo stesso <code>manifest.yaml<\/code> da Git nel comando <code>kubectl delete -f manifest.yaml<\/code>.<\/p>\n<p>Operazione <b><code>replace<\/code><\/b> permette di sostituire completamente la configurazione della risorsa con una nuova, senza dover ricreare la risorsa. Questo significa che prima di apportare una modifica alla risorsa, \u00e8 logico richiedere la versione corrente con l'operazione <code>get<\/code>, modificarla e aggiornarla con l'operazione <code>replace<\/code>. Nel kube apiserver \u00e8 integrato <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Optimistic_concurrency_control\">l'ottimistic locking<\/a><\/noindex> e se dopo l'operazione <code>get<\/code> l'oggetto \u00e8 stato modificato, allora l'operazione <code>replace<\/code> non andr\u00e0 a buon fine.<\/p>\n<p>Per archiviare la configurazione in Git e aggiornare usando replace, \u00e8 necessario eseguire l'operazione <code>get<\/code>, unire la configurazione da Git con quella che abbiamo ottenuto e quindi eseguire <code>replace<\/code>. Standardmente, kubectl consente solo di utilizzare il comando <code>kubectl replace -f manifest.yaml<\/code>, dove <code>manifest.yaml<\/code> \u2014 gi\u00e0 il manifesto completamente preparato (nel nostro caso \u2014 unito) che deve essere installato. Pertanto, l'utente deve implementare la fusione dei manifesti, che non \u00e8 un compito semplice...<\/p>\n<p>Vale anche la pena notare che, sebbene <code>manifest.yaml<\/code> sia archiviato in Git, non possiamo sapere in anticipo se bisogna creare l'oggetto o aggiornarlo \u2014 questo deve farlo il software dell'utente.<\/p>\n<p>In totale: <b>possiamo costruire un rollout continuo<\/b> solo con create, replace e delete, garantendo l'archiviazione della configurazione dell'infrastruttura in Git insieme al codice e un CI\/CD conveniente?<\/p>\n<p>In linea di principio, possiamo\u2026 Per questo <b>dovremmo implementare un'operazione di fusione<\/b> dei manifesti e un certo tipo di interfaccia che:<\/p>\n<ul>\n<li> verifica l'esistenza dell'oggetto nel cluster,<\/li>\n<li> esegue la creazione iniziale della risorsa,<\/li>\n<li> aggiorna o la elimina.<\/li>\n<\/ul>\n<p>\nDurante l'aggiornamento, occorre tenere presente che <i>la risorsa potrebbe essere cambiata<\/i> dall'ultimo <code>get<\/code> e gestire automaticamente il caso di ottimistic locking \u2014 effettuare tentativi ripetuti di aggiornamento.<\/p>\n<p>Ma perch\u00e9 reinventare la ruota, quando kube-apiserver offre un altro modo per aggiornare le risorse: l'operazione <code>patch<\/code>, che allevia l'utente da alcune delle problematiche descritte?<\/p>\n<h3>Patch<\/h3>\n<p>\nEccoci arrivati ai patch.<\/p>\n<p>Le patch sono il principale metodo per applicare modifiche agli oggetti esistenti in Kubernetes. L'operazione <code>patch<\/code> funziona in modo tale che:<\/p>\n<ul>\n<li> all'utente del kube-apiserver \u00e8 richiesto di inviare una patch in formato JSON e specificare l'oggetto,<\/li>\n<li> e l'apiserver si occuper\u00e0 dello stato attuale dell'oggetto e lo porter\u00e0 allo stato desiderato.<\/li>\n<\/ul>\n<p>\nIn questo caso, l'ottimistic locking non \u00e8 necessario. Questa operazione \u00e8 pi\u00f9 dichiarativa rispetto a replace, anche se inizialmente pu\u00f2 sembrare il contrario.<\/p>\n<p>Pertanto:<\/p>\n<ul>\n<li> con l'operazione <code>create<\/code> creiamo l'oggetto secondo il manifesto da Git,<\/li>\n<li> utilizzando <code>elimina<\/code> \u2014 lo eliminiamo, se l'oggetto non \u00e8 pi\u00f9 necessario,<\/li>\n<li> utilizzando <code>patch<\/code> \u2014 modifichiamo l'oggetto, portandolo allo stato descritto in Git.<\/li>\n<\/ul>\n<p>\nTuttavia, per fare ci\u00f2, \u00e8 necessario creare <i>patch corretto<\/i>!<\/p>\n<h3>Come funzionano i patch in Helm 2: 2-way-merge<\/h3>\n<p>\nDurante la prima installazione del rilascio, Helm esegue l'operazione <code>create<\/code> per le risorse del chart.<\/p>\n<p>Durante l'aggiornamento del rilascio, Helm per ogni risorsa:<\/p>\n<ul>\n<li> calcola il patch tra la versione della risorsa del chart precedente e la versione attuale del chart,<\/li>\n<li> applica questo patch.<\/li>\n<\/ul>\n<p>\nQuesto patch lo chiameremo <b>2-way-merge patch<\/b>, perch\u00e9 nella sua creazione sono coinvolti 2 manifesti:<\/p>\n<ul>\n<li> il manifesto della risorsa del rilascio precedente,<\/li>\n<li> il manifesto della risorsa del rilascio attuale.<\/li>\n<\/ul>\n<p>\nDurante la rimozione, l'operazione <code>elimina<\/code> viene chiamata nel kube apiserver per risorse che sono state dichiarate nel rilascio precedente, ma non dichiarate in quello attuale.<\/p>\n<p>L'approccio con il 2-way-merge patch presenta un problema: porta a <b>una desincronizzazione tra lo stato reale della risorsa nel cluster e il manifesto in Git<\/b>.<\/p>\n<h3>Un'illustrazione del problema \u00e8 il seguente esempio<\/h3>\n<p><\/p>\n<ul>\n<li> In Git, nel chart, viene conservato un manifesto in cui il campo <code>image<\/code> del Deployment ha il valore <code>ubuntu:18.04<\/code>.<\/li>\n<li> L'utente tramite <code>kubectl edit<\/code> ha cambiato il valore di questo campo in <code>ubuntu:19.04<\/code>.<\/li>\n<li> Durante il ridispiegamento del chart Helm <i>non genera un patch<\/i>, perch\u00e9 il campo <code>image<\/code> nella versione precedente del rilascio e nel chart attuale sono identici.<\/li>\n<li> Dopo il ridispiegamento <code>image<\/code> rimane <code>ubuntu:19.04<\/code>, anche se nel chart \u00e8 indicato <code>ubuntu:18.04<\/code>.<\/li>\n<\/ul>\n<p>\nAbbiamo ottenuto una desincronizzazione e perso la dichiarativit\u00e0.<\/p>\n<h3>Cos'\u00e8 una risorsa sincronizzata?<\/h3>\n<p>\nIn generale, <i>la piena<\/i> corrispondenza del manifesto della risorsa nel cluster in esecuzione e del manifesto in Git non pu\u00f2 essere ottenuta. Perch\u00e9 nel manifesto reale possono esserci annotazioni\/etichette di servizio, contenitori aggiuntivi e altri dati, aggiunti e rimossi dalla risorsa dinamicamente da alcuni controller. Questi dati non possiamo e non vogliamo tenerli in Git. Tuttavia, vogliamo che durante il rollout i campi che abbiamo esplicitamente indicato in Git assumano i valori corrispondenti.<\/p>\n<p>Ne deriva una regola generale per una risorsa sincronizzata <b>: durante il rollout di una risorsa si possono modificare o rimuovere solo quei campi che sono esplicitamente riportati nel manifesto di Git (o erano riportati nella versione precedente e ora sono stati rimossi).<\/b>3-way-merge patch<\/p>\n<h3>: genera un patch tra l'ultima versione applicata del manifesto di Git e la versione obiettivo del manifesto di Git, tenendo conto dell'attuale versione del manifesto del cluster in esecuzione. Il patch finale deve conformarsi alla regola della risorsa sincronizzata:<\/h3>\n<p>\nL'idea principale <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Merge_(version_control)#Three-way_merge\">: genera un patch tra l'ultima versione applicata del manifesto di Git e la versione obiettivo del manifesto di Git, tenendo conto dell'attuale versione del manifesto del cluster in esecuzione. Il patch finale deve conformarsi alla regola della risorsa sincronizzata:<\/a><\/noindex>i nuovi campi, aggiunti nella versione obiettivo, vengono aggiunti tramite il patch;<\/p>\n<ul>\n<li> i campi precedentemente esistenti nell'ultima versione applicata e non esistenti nella versione obiettivo \u2014 vengono azzerati tramite il patch;<\/li>\n<li> i campi nell'attuale versione dell'oggetto, che differiscono dalla versione obiettivo del manifesto, vengono aggiornati tramite il patch.<\/li>\n<li> E proprio su questo principio vengono generati i patch<\/li>\n<\/ul>\n<p>\nl'ultima versione applicata del manifesto \u00e8 conservata nell'annotazione dell'oggetto stesso, <code>kubectl apply<\/code>:<\/p>\n<ul>\n<li> l'obiettivo \u00e8 preso dal file YAML specificato, <\/li>\n<li> l'attuale \u2014 dal cluster in esecuzione.<\/li>\n<li> attuale \u2014 da un cluster attivo.<\/li>\n<\/ul>\n<p>\nOra che abbiamo chiarito la teoria, \u00e8 tempo di raccontare cosa abbiamo fatto in werf.<\/p>\n<h2>Applicazione delle modifiche in werf<\/h2>\n<p>\nIn precedenza, werf, come Helm 2, utilizzava patch 2-way-merge.<\/p>\n<h3>Repair patch<\/h3>\n<p>\nPer passare a un nuovo tipo di patch \u2014 3-way-merge, \u2014 come primo passo abbiamo introdotto i cosiddetti <b>repair patch<\/b>.<\/p>\n<p>Durante il deployment viene utilizzato il patch standard 2-way-merge, ma werf genera anche un patch che sincronizza lo stato reale della risorsa con ci\u00f2 che \u00e8 scritto in Git (viene creato un patch utilizzando la stessa regola della risorsa sincronizzata descritta sopra).<\/p>\n<p>In caso di desincronizzazione, alla fine del deployment l'utente riceve un WARNING con un messaggio pertinente e un patch che deve essere applicato per riportare la risorsa a uno stato sincronizzato. Inoltre, questo patch viene registrato in un'annotazione speciale <code>werf.io\/repair-patch<\/code>. Si presume che l'utente applicher\u00e0 manualmente <b>questo patch: werf non lo applicher\u00e0 per principio.<\/b> applicher\u00e0 questa patch: werf non la applicher\u00e0 in modo decisivo.<\/p>\n<p>La generazione di repair patch \u00e8 una misura temporanea che consente di testare concretamente la creazione di patch secondo il principio del 3-way-merge, ma questi patch non vengono applicati automaticamente. Al momento, questa modalit\u00e0 di funzionamento \u00e8 abilitata di default.<\/p>\n<h3>3-way-merge patch solo per nuovi rilasci<\/h3>\n<p>\nA partire dal 1 dicembre 2019, le versioni beta e alpha di werf iniziano <b>predefinito<\/b> a utilizzare patch 3-way-merge completi per l'applicazione delle modifiche solo per i nuovi rilasci di Helm, distribuiti tramite werf. I rilasci gi\u00e0 esistenti continueranno a utilizzare l'approccio con patch 2-way-merge + patch di riparazione.<\/p>\n<p>Questa modalit\u00e0 di funzionamento pu\u00f2 essere abilitata esplicitamente impostando <code>WERF_THREE_WAY_MERGE_MODE=onlyNewReleases<\/code> adesso.<\/p>\n<p><i><b>Nota<\/b>: la funzione \u00e8 stata introdotta in werf nel corso di diversi rilasci: nel canale alpha \u00e8 stata completata dalla versione <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf\/releases\/tag\/v1.0.5-alpha.19\">v1.0.5-alpha.19<\/a><\/noindex>, e nel canale beta \u2014 da <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 per tutti i rilasci<\/h3>\n<p>\nA partire dal 15 dicembre 2019, le versioni beta e alpha di werf iniziano a utilizzare di default patch 3-way-merge completi per l'applicazione delle modifiche per tutti i rilasci.<\/p>\n<p>Questa modalit\u00e0 di funzionamento pu\u00f2 essere abilitata esplicitamente impostando <code>WERF_THREE_WAY_MERGE_MODE=enabled<\/code> adesso.<\/p>\n<h3>Come gestire il ridimensionamento automatico delle risorse?<\/h3>\n<p>\nIn Kubernetes ci sono 2 tipi di autoscalamento: HPA (orizzontale) e VPA (verticale).<\/p>\n<p>L'orizzontale sceglie automaticamente il numero di repliche, il verticale \u2013 la quantit\u00e0 di risorse. Sia il numero di repliche che i requisiti delle risorse sono specificati nel manifesto delle risorse (vedi <code>spec.replicas<\/code> o <code>spec.containers[].resources.limits.cpu<\/code>, <code>spec.containers[].resources.limits.memory<\/code> e <noindex><a rel=\"nofollow\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/configuration\/manage-compute-resources-container\/#resource-requests-and-limits-of-pod-and-container\">altri<\/a><\/noindex>).<\/p>\n<p>Problema: se un utente configura una risorsa nel chart in modo da specificare valori definiti per le risorse o le repliche e per questa risorsa vengono abilitati gli autoscalatori, ad ogni deploy werf reimposter\u00e0 questi valori a quelli riportati nel manifesto del chart.<\/p>\n<p>Ci sono due soluzioni al problema. Inizialmente, \u00e8 meglio evitare di specificare esplicitamente i valori autoscalabili nel manifesto del chart. Se questa opzione non \u00e8 praticabile per qualche motivo (ad esempio, perch\u00e9 nel chart \u00e8 comodo impostare i limiti iniziali delle risorse e il numero di repliche), werf offre le seguenti annotazioni:<\/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>\nCon tale annotazione, werf non ridurr\u00e0 i valori corrispondenti ad ogni deploy, ma li imposter\u00e0 solo alla creazione iniziale della risorsa.<\/p>\n<p>Maggiore approfondimento \u2013 vedere nella documentazione del progetto su <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#deal-with-hpa\">HPA<\/a><\/noindex> e <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>Impedire l'uso del patch 3-way-merge<\/h3>\n<p>\nL'utente pu\u00f2 attualmente impedire l'uso di nuovi patch in werf tramite la variabile d'ambiente <code>WERF_THREE_WAY_MERGE_MODE=disabled<\/code>. Tuttavia, a partire <b>dal 1 marzo 2020, questo divieto smetter\u00e0 di funzionare<\/b> e sar\u00e0 possibile utilizzare solo patch 3-way-merge.<\/p>\n<h2>Adozione delle risorse in werf<\/h2>\n<p>\nL'apprendimento del metodo di applicazione delle modifiche tramite patch 3-way-merge ci ha permesso subito di implementare una funzionalit\u00e0 come l'adozione delle risorse esistenti nel cluster in un rilascio Helm.<\/p>\n<p>Helm 2 ha un problema: non \u00e8 possibile aggiungere una risorsa che esiste gi\u00e0 nel cluster ai manifesti del chart senza ricreare da zero questa risorsa (vedi <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>). Abbiamo insegnato a werf ad accettare risorse esistenti nel rilascio. Per fare ci\u00f2, \u00e8 necessario installare sull'attuale versione della risorsa nel cluster attivo un'annotazione (ad esempio, tramite <code>kubectl edit<\/code>):<\/p>\n<pre><code class=\"plaintext\">\"werf.io\/allow-adoption-by-release\": RELEASE_NAME<\/code><\/pre>\n<p>\nOra la risorsa deve essere descritta nel chart e al prossimo deploy del rilascio con il nome corrispondente, la risorsa esistente sar\u00e0 accettata in questo rilascio e rimarr\u00e0 sotto il suo controllo. Inoltre, durante il processo di adozione, werf porter\u00e0 lo stato attuale della risorsa dal cluster attivo allo stato descritto nel chart, utilizzando le stesse patch 3-way-merge e la regola della risorsa sincronizzata.<\/p>\n<p><i><b>Nota<\/b>: configurazione <code>WERF_THREE_WAY_MERGE_MODE<\/code> non influisce sull'adozione delle risorse \u2013 in caso di adozione viene sempre utilizzata una patch 3-way-merge.<\/i><\/p>\n<p>Dettagli \u2013 in <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html#resources-adoption\">documentazione<\/a><\/noindex>.<\/p>\n<h2>Conclusioni e piani futuri<\/h2>\n<p>\nSpero che dopo questo articolo risulti pi\u00f9 chiaro cosa siano le patch 3-way-merge e perch\u00e8 sono state integrate. Dal punto di vista pratico dello sviluppo del progetto werf, la loro implementazione rappresenta un ulteriore passo verso il miglioramento del deploy simile a Helm. Ora possiamo dimenticare i problemi di sincronizzazione della configurazione che spesso si presentano con Helm 2. Inoltre, \u00e8 stata aggiunta una nuova funzionalit\u00e0 utile per l'adozione delle risorse Kubernetes gi\u00e0 esistenti nei rilasci Helm.<\/p>\n<p>Nel deploy simile a Helm permangono comunque alcuni problemi e difficolt\u00e0, come l'uso dei template Go, e continueremo a risolverli.<\/p>\n<p>Informazioni sui metodi di aggiornamento delle risorse e sull'adozione si possono anche trovare su <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/resources_update_methods_and_adoption.html\">questa pagina di documentazione<\/a><\/noindex>.<\/p>\n<h3>Helm 3<\/h3>\n<p>\nUn'ulteriore nota merita <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/news\/t\/475722\/\">la recente<\/a><\/noindex> uscita della nuova versione principale di Helm \u2013 v3, \u2013 che utilizza anche patch 3-way-merge ed elimina Tiller. La nuova versione di Helm richiede <noindex><a rel=\"nofollow\" href=\"https:\/\/helm.sh\/docs\/topics\/v2_v3_migration\/\">migrazione<\/a><\/noindex> installazioni gi\u00e0 esistenti per convertirle nel nuovo formato di archiviazione dei rilasci.<\/p>\n<p>Da parte sua, werf attualmente ha gi\u00e0 eliminato l'uso di Tiller, ha adottato le patch 3-way-merge e ha aggiunto <noindex><a rel=\"nofollow\" href=\"https:\/\/werf.io\/documentation\/reference\/deploy_process\/differences_with_helm.html\">molto altro<\/a><\/noindex>, rimanendo comunque compatibile con le installazioni gi\u00e0 esistenti su Helm 2 (non \u00e8 necessario eseguire script di migrazione). Pertanto, finch\u00e9 werf non \u00e8 stato migrato a Helm 3, gli utenti di werf non perdono i principali vantaggi di Helm 3 rispetto a Helm 2 (essi sono presenti anche in werf).<\/p>\n<p>Tuttavia, la migrazione di werf sulla base di codice di Helm 3 \u00e8 inevitabile e avverr\u00e0 nel prossimo futuro. Si prevede che sar\u00e0 werf 1.1 o werf 1.2 (attualmente, la principale versione di werf \u00e8 1.0; per ulteriori dettagli sul sistema di versionamento di werf vedi <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/flant\/werf#backward-compatibility-promise\">qui<\/a><\/noindex>). Nel frattempo, Helm 3 avr\u00e0 il tempo di stabilizzarsi.<\/p>\n<h2>P.S.<\/h2>\n<p>\nLeggete anche nel nostro blog:<\/p>\n<ul>\n<li> Ciclo di note sulle novit\u00e0 in werf:\n<ul>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/468049\/\">Utilizzo di werf per il rilascio di complessi Helm charts<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/465131\/\">Supporto monorepo e multirepo in werf e qual \u00e8 il legame con Docker Registry<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/463613\/\">Ora \u00e8 possibile costruire immagini Docker in werf anche tramite un normale 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 il nostro strumento per CI\/CD in Kubernetes (panoramica e video della presentazione)<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/469541\/\">Costruzione e deploy di microservizi simili con werf e GitLab CI<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/453734\/\">Introduzione a Helm 3<\/a><\/noindex>\u00bb.<\/li>\n<\/ul>\n<p>Fonte: <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.0.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\/it\/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.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\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\/it\/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: deployment in Kubernetes with Helm \u00abon steroids\u00bb | ProHoster","description":"\u00c8 successo ci\u00f2 che noi (e non solo noi) aspettavamo da tempo: werf, il nostro strumento Open Source per la costruzione di applicazioni e la loro distribuzione in Kubernetes, ora \u00e8 supportato.","canonical_url":"https:\/\/prohoster.info\/it\/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":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/53120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=53120"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/53120\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/53121"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=53120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=53120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=53120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}