{"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":"3-way merge in werf: deployment in Kubernetes con Helm \"potenziato\"","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>, la nostra utility Open Source per la costruzione di applicazioni e la loro distribuzione in Kubernetes ora supporta l'applicazione delle modifiche tramite patch 3-way-merge! Inoltre, \u00e8 stata introdotta la possibilit\u00e0 di adottare risorse K8s esistenti nei rilasci Helm senza ricreare queste risorse.<\/p>\n<p><img decoding=\"async\" alt=\"3-way merge in werf: deployment in Kubernetes con Helm &quot;potenziato&quot;\" src=\"\/wp-content\/uploads\/2019\/11\/e5be3544c201f7b2c97fba216a49506d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn sintesi, impostiamo <code>WERF_THREE_WAY_MERGE=enabled<\/code> \u2014 otteniamo un deployment \u00abcome in <code>kubectl apply<\/code>\u00bb, compatibile con le installazioni esistenti su Helm 2 e anche un po' di pi\u00f9.<\/p>\n<p>Ma cominciamo con la teoria: cosa sono esattamente le patch 3-way-merge, come le persone sono arrivate all'approccio per la loro generazione e perch\u00e9 sono importanti nei processi CI\/CD con un'infrastruttura basata su Kubernetes? E dopo di questo, vedremo cos'\u00e8 il 3-way-merge in werf, quali modalit\u00e0 vengono utilizzate per impostazione predefinita e come gestirle.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Cosa \u00e8 una patch 3-way-merge?<\/h2>\n<p>\nQuindi, cominciamo con l'argomento del rollout delle risorse descritte nei manifest YAML in Kubernetes.<\/p>\n<p>Per lavorare con le risorse, l'API Kubernetes offre le seguenti operazioni principali: create, patch, replace e delete. Si presume che con esse si debba costruire un rollout continuo delle risorse nel cluster. Come?<\/p>\n<h3>Comandi imperativi kubectl<\/h3>\n<p>\nIl primo approccio alla gestione degli oggetti in Kubernetes \u00e8 l'uso di comandi imperativi kubectl per creare, modificare ed eliminare questi oggetti. In termini semplici:<\/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 problemi: <\/p>\n<ol>\n<li> \u00c8 difficile <b>automatizzare<\/b>.<\/li>\n<li> Come <b>riflettere la configurazione<\/b> in Git? Come fare una revisione delle modifiche che avvengono nel cluster?<\/li>\n<li> Come garantire <b>riproducibilit\u00e0<\/b> la configurazione al riavvio?<\/li>\n<li>\u2026<\/li>\n<\/ol>\n<p>\n\u00c8 chiaro che questo approccio si integra male con la memorizzazione insieme al codice dell'applicazione e l'infrastruttura come codice (IaC; o anche <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/458878\/\">GitOps<\/a><\/noindex> come una versione pi\u00f9 moderna che sta acquisendo popolarit\u00e0 nell'ecosistema Kubernetes). Pertanto, non ha ottenuto ulteriore sviluppo in kubectl.<\/p>\n<h3>Operazioni create, get, replace e delete<\/h3>\n<p>\nPer la creazione iniziale <b>\u00e8 tutto semplice: inviamo il manifesto all'operazione<\/b> a kube api e la risorsa \u00e8 creata. La rappresentazione YAML del manifesto pu\u00f2 essere memorizzata in Git, e per la creazione \u2014 utilizzare il comando <code>create<\/code> kubectl create -f manifest.yaml <code>eliminazione<\/code>.<\/p>\n<p>C <b>\u00e8 semplice anche: sostituiamo lo stesso<\/b> manifest.yaml <code>da Git nel comando<\/code> kubectl delete -f manifest.yaml <code>kubectl delete -f manifest.yaml<\/code>.<\/p>\n<p>Operazione <b><code>replace<\/code><\/b> consente di sostituire completamente la configurazione della risorsa con una nuova, senza dover ricreare la risorsa. Ci\u00f2 significa che, prima di apportare una modifica alla risorsa, \u00e8 logico richiedere la versione attuale tramite l'operazione <code>get<\/code>, modificarla e aggiornare tramite l'operazione <code>replace<\/code>. All'interno di kube apiserver \u00e8 integrato <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Optimistic_concurrency_control\">il blocco ottimistico<\/a><\/noindex> , e, se dopo l'operazione <code>get<\/code> l'oggetto \u00e8 cambiato, allora l'operazione <code>replace<\/code> non avr\u00e0 successo.<\/p>\n<p>Per memorizzare la configurazione in Git e aggiornare utilizzando replace, bisogna eseguire l'operazione <code>get<\/code>, unire la configurazione da Git con ci\u00f2 che abbiamo ricevuto e procedere con <code>replace<\/code>. In modo predefinito, kubectl consente solo di utilizzare il comando <code>kubectl replace -f manifest.yaml<\/code>, dove <code>da Git nel comando<\/code> \u2014 un manifesto gi\u00e0 completamente preparato (nel nostro caso \u2014 unito) che deve essere installato. Dunque, l'utente deve implementare la fusione dei manifesti, il che non \u00e8 un compito banale...<\/p>\n<p>Vale anche la pena notare che, anche se <code>da Git nel comando<\/code> \u00e8 memorizzato in Git, non possiamo sapere in anticipo se bisogna creare un oggetto o aggiornarlo \u2014 questo deve essere fatto dal software dell'utente.<\/p>\n<p>In totale: <b>possiamo costruire un rilascio continuo<\/b> solo con create, replace e delete, garantendo il mantenimento della configurazione dell'infrastruttura in Git insieme al codice e un CI\/CD conveniente?<\/p>\n<p>In linea di principio, possiamo... Per questo <b>\u00e8 necessario implementare l'operazione di fusione<\/b> dei manifesti e qualche tipo di interfaccia, che:<\/p>\n<ul>\n<li> verifica la presenza dell'oggetto nel cluster,<\/li>\n<li> esegue la creazione iniziale della risorsa,<\/li>\n<li> la aggiorna o la elimina.<\/li>\n<\/ul>\n<p>\nDurante l'aggiornamento \u00e8 necessario considerare che <i>la risorsa potrebbe essere cambiata<\/i> dalla volta precedente <code>get<\/code> e gestire automaticamente il caso del blocco ottimistico \u2014 effettuando tentativi ripetuti di aggiornamento.<\/p>\n<p>Tuttavia, perch\u00e9 inventare la ruota, quando kube-apiserver offre un altro modo per aggiornare le risorse: l'operazione <code>patch<\/code>, che solleva l'utente da parte dei problemi descritti?<\/p>\n<h3>Patch<\/h3>\n<p>\nEcco che arriviamo ai patch.<\/p>\n<p>I patch sono il modo principale per applicare modifiche agli oggetti esistenti in Kubernetes. L'operazione <code>patch<\/code> funziona in modo tale che:<\/p>\n<ul>\n<li> l'utente del kube-apiserver deve inviare un 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 richiesto.<\/li>\n<\/ul>\n<p>\nIn questo caso non \u00e8 necessario il blocco ottimistico. Questa operazione \u00e8 pi\u00f9 dichiarativa rispetto a replace, anche se inizialmente potrebbe sembrare il contrario.<\/p>\n<p>Pertanto:<\/p>\n<ul>\n<li> tramite l'operazione <code>create<\/code> creiamo un oggetto dal manifesto di Git,<\/li>\n<li> utilizzando <code>delete<\/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 farlo, \u00e8 necessario creare <i>una patch corretta<\/i>!<\/p>\n<h3>Come funzionano le 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 la patch tra la versione della risorsa del chart precedente e la versione attuale del chart,<\/li>\n<li> applica questa patch.<\/li>\n<\/ul>\n<p>\nQuesta patch la 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 dal rilascio precedente,<\/li>\n<li> il manifesto della risorsa dall'attuale risorsa.<\/li>\n<\/ul>\n<p>\nDurante la cancellazione, l'operazione <code>delete<\/code> nel kube apiserver viene chiamata per le risorse che sono state dichiarate nel rilascio precedente, ma non sono dichiarate in quello attuale.<\/p>\n<p>L'approccio della 2 way merge patch presenta un problema: porta a <b>una desincronizzazione dello stato reale della risorsa nel cluster e del manifesto in Git<\/b>.<\/p>\n<h3>Illustrazione del problema con un esempio<\/h3>\n<p><\/p>\n<ul>\n<li> In Git, nel chart \u00e8 memorizzato 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 una patch<\/i>, perch\u00e9 il campo <code>image<\/code> nella versione precedente del rilascio e nell'attuale chart sono uguali.<\/li>\n<li> Dopo il ridispiegamento <code>image<\/code> rimane <code>ubuntu:19.04<\/code>, anche se nel chart \u00e8 scritto <code>ubuntu:18.04<\/code>.<\/li>\n<\/ul>\n<p>\nAbbiamo ottenuto una desincronizzazione e perso la dichiarativit\u00e0.<\/p>\n<h3>Che cos'\u00e8 una risorsa sincronizzata?<\/h3>\n<p>\nIn generale, <i>\u00e8 impossibile ottenere una corrispondenza completa<\/i> tra il manifesto della risorsa nel cluster in funzione e il manifesto in Git. Perch\u00e9 nel manifesto reale potrebbero esserci annotazioni\/etichette di servizio, contenitori aggiuntivi e altri dati, aggiunti e rimossi dalla risorsa in modo dinamico da alcuni controller. Questi dati non possiamo e non vogliamo tenerli in Git. Tuttavia, vogliamo che quando viene distribuita, i campi che abbiamo esplicitamente indicato in Git assumano i valori corrispondenti.<\/p>\n<p>Si ottiene quindi una regola generale <b>per le risorse sincronizzate<\/b>: durante la distribuzione di una risorsa \u00e8 possibile modificare o rimuovere solo quei campi che sono esplicitamente indicati nel manifesto di Git (o che erano stati indicati nella versione precedente e ora sono stati rimossi).<\/p>\n<h3>3-way-merge patch<\/h3>\n<p>\nL'idea principale <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Merge_(version_control)#Three-way_merge\">3-way-merge patch<\/a><\/noindex>: genera una patch tra l'ultima versione applicata del manifesto da Git e la versione target del manifesto da Git, tenendo conto dell'attuale versione del manifesto nel cluster in funzione. La patch finale deve rispettare la regola della risorsa sincronizzata:<\/p>\n<ul>\n<li> i nuovi campi aggiunti alla versione target vengono aggiunti tramite patch;<\/li>\n<li> I campi precedentemente esistenti nell'ultima versione applicata e non esistenti nella versione target vengono azzerati con la patch;<\/li>\n<li> I campi nella versione attuale dell'oggetto, diversi dalla versione target del manifesto, vengono aggiornati tramite patch.<\/li>\n<\/ul>\n<p>\nQuesto \u00e8 esattamente il principio secondo cui vengono generate le patch <code>kubectl apply<\/code>:<\/p>\n<ul>\n<li> l'ultima versione applicata del manifesto viene salvata nell'annotazione dell'oggetto stesso, <\/li>\n<li> la target viene presa dal file YAML specificato,<\/li>\n<li> l'attuale viene dal cluster in uso.<\/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 di unione a 2 vie.<\/p>\n<h3>Patch di riparazione<\/h3>\n<p>\nPer passare a un nuovo tipo di patch \u2014 unione a 3 vie \u2014 abbiamo prima introdotto cos\u00ec chiamate <b>patch di riparazione<\/b>.<\/p>\n<p>Durante il deployment viene utilizzata una patch standard di unione a 2 vie, ma werf genera inoltre una patch che sincronizza lo stato reale della risorsa con ci\u00f2 che \u00e8 scritto in Git (viene creata una patch utilizzando la stessa regola di risorsa sincronizzata descritta sopra).<\/p>\n<p>In caso di disallineamento, al termine del deployment l'utente riceve un AVVISO con un messaggio pertinente e una patch che deve essere applicata per riportare la risorsa a uno stato sincronizzato. Questa patch viene inoltre registrata in un'annotazione speciale <code>werf.io\/repair-patch<\/code>. Si presuppone che l'utente la <b>applicher\u00e0<\/b> manualmente: werf non la applicher\u00e0 in modo principiale.<\/p>\n<p>La generazione di patch di riparazione \u00e8 una misura temporanea che consente di testare la creazione di patch secondo il principio dell'unione a 3 vie, ma queste patch non vengono applicate automaticamente. Attualmente, questa modalit\u00e0 operativa \u00e8 abilitata per impostazione predefinita.<\/p>\n<h3>Patch di unione a 3 vie solo per nuove versioni<\/h3>\n<p>\nA partire dal 1 dicembre 2019, le versioni beta e alpha di werf iniziano <b>predefinito<\/b> a utilizzare patch di unione a 3 vie complete per l'applicazione delle modifiche solo per le nuove versioni Helm distribuite tramite werf. Le versioni gi\u00e0 esistenti continueranno a utilizzare l'approccio con patch a 2 vie + patch di riparazione.<\/p>\n<p>Questa modalit\u00e0 operativa pu\u00f2 essere attivata esplicitamente impostando <code>WERF_THREE_WAY_MERGE_MODE=onlyNewReleases<\/code> gi\u00e0 adesso.<\/p>\n<p><i><b>Nota<\/b>: la funzionalit\u00e0 \u00e8 stata presente in werf per diverse versioni: nel canale alpha \u00e8 diventata stabile con la 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>, mentre 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>patch di unione a 3 vie per tutte le versioni<\/h3>\n<p>\nA partire dal 15 dicembre 2019, le versioni beta e alpha di werf iniziano a utilizzare per impostazione predefinita patch 3-way-merge complete per applicare modifiche a tutte le release.<\/p>\n<p>Questa modalit\u00e0 operativa pu\u00f2 essere attivata esplicitamente impostando <code>WERF_THREE_WAY_MERGE_MODE=enabled<\/code> gi\u00e0 adesso.<\/p>\n<h3>Come gestire l'autoscaling delle risorse?<\/h3>\n<p>\nIn Kubernetes esistono 2 tipi di autoscaling: HPA (orizzontale) e VPA (verticale).<\/p>\n<p>Quello orizzontale seleziona automaticamente il numero di repliche, quello verticale il numero di risorse. Sia il numero di repliche che i requisiti delle risorse sono specificati nel manifesto della risorsa (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 l'utente configura una risorsa nel chart in modo tale che siano specificati valori per risorse o repliche e per questa risorsa sono abilitati gli autoscaler, ad ogni deploy werf ripristiner\u00e0 questi valori a quelli registrati nel manifesto del chart.<\/p>\n<p>Ci sono due soluzioni al problema. Per iniziare, \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 \u00e8 comodo definire le limitazioni iniziali delle risorse e il numero di repliche nel chart), 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 ripristiner\u00e0 i valori corrispondenti ad ogni deploy, ma li setter\u00e0 solo al momento della creazione iniziale della risorsa.<\/p>\n<p>Per maggiori dettagli - vedi 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 di 3-way-merge patch<\/h3>\n<p>\nL'utente pu\u00f2 attualmente vietare l'uso di nuove patch in werf tramite la variabile di 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>Adoption delle risorse in werf<\/h2>\n<p>\nL'adozione del metodo applicativo delle modifiche tramite patch 3-way-merge ci ha permesso di implementare immediatamente una funzionalit\u00e0 come l'adozione delle risorse esistenti nel cluster in una release di Helm.<\/p>\n<p>Helm 2 ha un problema: non \u00e8 possibile aggiungere al manifesto del chart una risorsa che esiste gi\u00e0 nel cluster senza ricreare quella risorsa da zero (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 nella release. Per farlo, \u00e8 necessario impostare sul versione attuale della risorsa nel cluster in esecuzione 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 \u00e8 necessario descrivere la risorsa nella chart e al prossimo deploy con werf del rilascio con il nome corrispondente, la risorsa esistente verr\u00e0 accettata in questo rilascio e rimarr\u00e0 sotto il suo controllo. Inoltre, nel processo di accettazione della risorsa nel rilascio, werf porter\u00e0 lo stato attuale della risorsa dal cluster funzionante allo stato descritto nella chart, utilizzando gli stessi patch di 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: in caso di adozione viene sempre utilizzato il patch di 3-way-merge.<\/i><\/p>\n<p>Dettagli \u2014 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 futuri piani<\/h2>\n<p>\nSpero che dopo questo articolo sia pi\u00f9 chiaro cosa siano i patch di 3-way-merge e perch\u00e9 siano stati adottati. Dal punto di vista pratico dello sviluppo del progetto werf, la loro implementazione \u00e8 stato un ulteriore passo verso il miglioramento del deploy simile a Helm. Ora possiamo dimenticare i problemi di sincronizzazione della configurazione che spesso si presentavano con l'uso di Helm 2. Inoltre, \u00e8 stata aggiunta una nuova utile funzionalit\u00e0 di adozione delle risorse Kubernetes gi\u00e0 estratte nel rilascio Helm.<\/p>\n<p>Nel deploy simile a Helm rimangono comunque alcuni problemi e difficolt\u00e0, come l'uso dei template Go, e continueremo a risolverli.<\/p>\n<p>Le informazioni sui metodi di aggiornamento delle risorse e sull'adozione possono essere trovate anche in <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>\nMerita una nota separata <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/news\/t\/475722\/\">la recente<\/a><\/noindex> nuova versione principale di Helm \u2014 v3, \u2014 che usa anch'essa i patch di 3-way-merge e si libera di Tiller. La nuova versione di Helm richiede <noindex><a rel=\"nofollow\" href=\"https:\/\/helm.sh\/docs\/topics\/v2_v3_migration\/\">la migrazione<\/a><\/noindex> delle installazioni esistenti per convertirle nel nuovo formato di archiviazione dei rilasci.<\/p>\n<p>Werf, da parte sua, ha gi\u00e0 eliminato l'uso di Tiller, \u00e8 passato ai patch di 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>, restando compatibile con le installazioni esistenti su Helm 2 (non \u00e8 necessario eseguire script di migrazione). Pertanto, finch\u00e9 werf non passer\u00e0 a Helm 3, gli utenti di werf non perderanno i principali vantaggi di Helm 3 rispetto a Helm 2 (essi sono presenti anche in werf).<\/p>\n<p>Tuttavia, il passaggio di werf alla base di codice di Helm 3 \u00e8 inevitabile e avverr\u00e0 nel prossimo futuro. Presumibilmente sar\u00e0 werf 1.1 o werf 1.2 (attualmente, la versione principale di werf \u00e8 1.0; ulteriori dettagli sul sistema di versioning di werf si trovano <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>\nLeggi 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\/\">Uso di werf per il rilascio di chart Helm complessi<\/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 cosa c'entra Docker Registry<\/a><\/noindex>\u00bb;<\/li>\n<li> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/flant\/blog\/463613\/\">Ora puoi costruire immagini Docker in werf anche usando 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\/\">Build e deployment 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.1.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.1.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\udd47Merge 3-way in werf: distribuzione in Kubernetes con Helm \u00absui steroidi\u00bb | ProHoster","description":"\u00c8 accaduto 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 su 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}]}}