
— il nostro strumento CLI GitOps open source per la creazione e la distribuzione di applicazioni su Kubernetes. Nel è stata introdotta una nuova funzionalità nel builder delle immagini: il tagging delle immagini in base al contenuto o tagging basato sul contenuto. Fino ad ora, lo schema di tagging tipico in werf prevedeva il tagging delle immagini Docker in base al tag Git, al ramo Git o al commit Git. Tuttavia, tutti questi schemi presentano svantaggi che vengono completamente risolti dalla nuova strategia di tagging. Maggiori dettagli su di essa e perché è così vantaggiosa — dopo il salto.
Distribuzione di un set di microservizi da un singolo repository Git
Capita spesso che un'applicazione sia suddivisa in molti servizi più o meno indipendenti. Le release di questi servizi possono avvenire indipendentemente: può essere rilasciato un solo servizio o più servizi alla volta, mentre gli altri devono continuare a funzionare senza alcuna modifica. Ma, dal punto di vista della gestione del codice e del progetto, è più comodo tenere tali servizi dell'applicazione in un unico repository.
Ci sono situazioni in cui i servizi sono realmente indipendenti e non collegati a un'unica applicazione. In questo caso, saranno collocati in progetti separati e il loro rilascio avverrà tramite processi CI/CD distinti in ciascun progetto.
Tuttavia, nella realtà i programmatori spesso suddividono una singola applicazione in più microservizi, ma creare un repository e un progetto separati per ciascuno di essi... è un evidente overkill. È proprio di questa situazione che si parlerà: diversi microservizi si trovano in un unico repository di progetto e i rilasci avvengono tramite un unico processo in CI/CD.
Tagging tramite branch e tag Git
Supponiamo di utilizzare la strategia di tagging più comune — tag-or-branch. Per i branch Git, le immagini vengono taggate con il nome del branch; per ogni branch esiste solo un'immagine pubblicata con quel nome in un momento dato. Per i tag Git, le immagini vengono taggate rispettivamente con il nome del tag.
Quando viene creato un nuovo tag Git — ad esempio, con il rilascio di una nuova versione — verrà creato un nuovo tag Docker per tutte le immagini del progetto nel Docker Registry:
-
myregistry.org/myproject/frontend:v1.1.10 -
myregistry.org/myproject/myservice1:v1.1.10 -
myregistry.org/myproject/myservice2:v1.1.10 -
myregistry.org/myproject/myservice3:v1.1.10 -
myregistry.org/myproject/myservice4:v1.1.10 -
myregistry.org/myproject/myservice5:v1.1.10 -
myregistry.org/myproject/database:v1.1.10
Questi nuovi nomi delle immagini vengono inseriti tramite template Helm nella configurazione di Kubernetes. Durante l'implementazione con il comando werf deploy si aggiorna il campo image nei manifesti delle risorse di Kubernetes e si riavviano le risorse corrispondenti a causa della modifica del nome dell'immagine.
Problema: nel caso in cui il contenuto dell'immagine non sia effettivamente cambiato rispetto al precedente rilascio (tag Git), ma esclusivamente il suo tag Docker, avviene un inutile riavvio di questa applicazione e, di conseguenza, c'è la possibilità di un semplice downtime. Anche se non ci sono stati motivi reali per eseguire questo riavvio.
Di conseguenza, con l'attuale schema di tagging è necessario gestire diversi repository Git separati e si pone il problema di organizzare il rilascio di questi diversi repository. In generale, questo schema risulta sovraccaricato e complicato. È meglio unire più servizi in un unico repository e creare tag Docker in modo da evitare riavvii non necessari.
Tagging tramite commit Git
In werf è presente anche una strategia di tagging legata ai commit Git.
Il commit Git è un identificatore del contenuto del repository Git e dipende dalla storia delle modifiche dei file nel repository Git, quindi è logico utilizzarlo per etichettare le immagini nel Docker Registry.
Tuttavia, l'etichettatura basata sul commit Git presenta gli stessi svantaggi di quella basata su ramificazioni o tag Git:
- Potrebbe essere stato creato un commit vuoto che non cambia i file, mentre il tag Docker dell'immagine sarà cambiato.
- Potrebbe essere stato creato un merge commit che non cambia i file, mentre il tag Docker dell'immagine sarà cambiato.
- Potrebbe essere stato creato un commit che modifica file in Git che non vengono importati nell'immagine, e il tag Docker dell'immagine sarà nuovamente cambiato.
L'etichettatura basata sul nome della ramificazione Git non riflette la versione dell'immagine.
C'è anche un'altra problematica legata alla strategia di etichettatura basata sulle ramificazioni Git.
L'etichettatura basata sul nome della ramificazione funziona finché i commit di quella ramificazione vengono raccolti in modo sequenziale in ordine cronologico.
Se un utente ricompone un vecchio commit associato a un certo branch nell'attuale schema, werf sovrascriverà l'immagine con la versione appena ricompilata dell'immagine per il vecchio commit, usando il corrispondente tag Docker. Da questo momento in poi, i Deployment che utilizzano questo tag rischiano di eseguire un pull di un'altra versione dell'immagine al riavvio dei pod, il che porterà alla perdita di connessione con il sistema CI, causando una desincronizzazione della nostra applicazione.
Inoltre, quando si eseguono push consecutivi su un branch con un breve intervallo di tempo tra di loro, il vecchio commit potrebbe essere ricompilato dopo un commit più recente: la vecchia versione dell'immagine sovrascrive la nuova con il tag del branch Git. Questi problemi possono essere risolti da un sistema CI/CD (ad esempio, in GitLab CI viene avviato un pipeline per una serie di commit), ma non tutte le piattaforme supportano questa funzionalità e quindi è necessario trovare un modo più affidabile per prevenire tale problema fondamentale.
Che cos'è il content-based tagging?
Quindi, che cos'è il content-based tagging — la taggatura delle immagini in base al contenuto.
Per creare i tag Docker non si utilizzano le primitive di Git (branch Git, tag Git…), ma un checksum associato a:
- il contenuto dell'immagine. L'identificatore del tag dell'immagine riflette il suo contenuto. Durante la creazione di una nuova versione, questo identificatore non cambierà se i file nell'immagine non sono stati modificati;
- la storia di creazione di quest'immagine in Git. Le immagini collegate a rami Git diversi e con istorie di build diverse tramite werf avranno identificatori di tag diversi.
Come identificatore di questo tipo, viene utilizzata la cosiddetta firma delle fasi dell'immagine.
Ogni immagine è composta da un insieme di fasi: from, before-install, git-archive, install, imports-after-install, before-setup,… git-latest-patch ecc. Ogni fase ha un identificatore che riflette il suo contenuto, — firma della fase (stage signature).
L'immagine finale, composta da queste fasi, viene contrassegnata con la cosiddetta firma dell'insieme di queste fasi — stages signature, — che è generale per tutte le fasi dell'immagine.
Ogni immagine dalla configurazione werf.yaml in generale avrà la sua firma e, di conseguenza, un tag Docker.
La firma delle fasi risolve tutti i problemi indicati:
- È resistente ai commit Git vuoti.
- È resistente ai commit Git che modificano file non rilevanti per l'immagine.
- Non porta a problemi di sovrascrittura della versione attuale dell'immagine al riavvio delle build per vecchi commit Git del ramo.
Questa è ora la strategia di tagging raccomandata e viene utilizzata per impostazione predefinita in werf per tutti i sistemi CI.
Come abilitare e utilizzare in werf
L'opzione corrispondente è stata aggiunta al comando werf publish: --tag-by-stages-signature=true|false
Nella CI, la strategia di tagging è impostata dal comando werf ci-env. In precedenza era definito dal parametro werf ci-env --tagging-strategy=tag-or-branch. Ora, se si specifica werf ci-env --tagging-strategy=stages-signature o se non si specifica questa opzione, werf utilizzerà per impostazione predefinita la strategia di tagging stages-signature. Comando werf ci-env imposterà automaticamente i flag necessari per il comando werf build-and-publish (o werf publish), quindi non è necessario specificare ulteriori opzioni per questi comandi.
Ad esempio, il comando:
werf publish --stages-storage :local --images-repo registry.hello.com/web/core/system --tag-by-stages-signature… può generare le seguenti immagini:
-
registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d -
registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6
Qui 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d — questa è la firma delle fasi dell'immagine backend, e f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 — firma delle fasi dell'immagine frontend.
Utilizzando funzioni speciali werf_container_image e werf_container_env non è necessario modificare nulla nei modelli Helm: queste funzioni genereranno automaticamente i nomi delle immagini corretti.
Esempio di configurazione nel sistema CI:
type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deployMaggiore informazione sulla configurazione è disponibile nella documentazione:
- ;
- ;
- .
Totale
- Nuova opzione
werf publish --tag-by-stages-signature=true|false. - Nuovo valore dell'opzione
werf ci-env --tagging-strategy=stages-signature|tag-or-branch(se non specificato, sarà di defaultstages-signature). - Se precedentemente sono state utilizzate opzioni di tagging per commit Git (
WERF_TAG_GIT_COMMIToppure l'opzionewerf publish --tag-git-commit COMMIT), è necessario passare alla strategia di tagging stages-signature. - I nuovi progetti dovrebbero essere subito impostati sulla nuova strategia di tagging.
- Per i vecchi progetti, quando si passa a werf 1.1, è consigliabile passare alla nuova strategia di tagging, tuttavia, la vecchia tag-or-branch è ancora supportata.
Il tagging basato sui contenuti risolve tutti i problemi discussi nell'articolo:
- La resilienza del nome del tag Docker ai commit Git vuoti.
- La robustezza del nome del tag Docker rispetto ai commit Git che cambiano file non rilevanti per l'immagine.
- Non comporta problemi di sovrascrittura della versione attuale dell'immagine durante il riavvio delle build per vecchi commit Git delle branche Git.
Usate! E non dimenticate di visitarci su , per creare un'issue o trovare già esistente, lasciare un like, creare una PR o semplicemente osservare l'evoluzione del progetto.
P.S.
Leggete anche nel nostro blog:
- «»
- «»
- «»;
- Ciclo di note sulle novità in werf:
- «»;
- «»;
- «»;
- «».
Fonte: habr.com
