Tagging basato sul contenuto nel werf builder: perché e come funziona?

Tagging basato sul contenuto nel werf builder: perché e come funziona?

werf è la nostra utility CLI GitOps open source per la creazione e la distribuzione di applicazioni su Kubernetes. IN rilasciare la versione 1.1 è stata introdotta una nuova funzionalità nel raccoglitore di immagini: taggare le immagini per contenuto o tagging basato sul contenuto. Fino ad ora, il tipico schema di tagging in werf prevedeva il tagging delle immagini Docker tramite tag Git, ramo Git o commit Git. Ma tutti questi schemi presentano degli svantaggi che vengono completamente risolti dalla nuova strategia di tagging. I dettagli su di esso e perché è così buono sono sotto il taglio.

Implementazione di una serie di microservizi da un repository Git

Spesso si verifica una situazione in cui un'applicazione è suddivisa in molti servizi più o meno indipendenti. I rilasci di questi servizi possono avvenire in modo indipendente: uno o più servizi possono essere rilasciati alla volta, mentre il resto deve continuare a funzionare senza alcuna modifica. Ma dal punto di vista dell'archiviazione del codice e della gestione dei progetti, è più conveniente mantenere tali servizi applicativi in ​​un unico repository.

Ci sono situazioni in cui i servizi sono veramente indipendenti e non associati a una singola applicazione. In questo caso, verranno posizionati in progetti separati e il loro rilascio verrà effettuato tramite processi CI/CD separati in ciascuno dei progetti.

Tuttavia, in realtà, gli sviluppatori spesso dividono una singola applicazione in diversi microservizi, ma creare un repository e un progetto separati per ciascuno... è chiaramente eccessivo. È questa situazione che verrà discussa ulteriormente: molti di questi microservizi si trovano in un unico repository di progetto e i rilasci avvengono attraverso un unico processo in CI/CD.

Tagging tramite ramo Git e tag Git

Supponiamo che venga utilizzata la strategia di tagging più comune: tag-o-ramo. Per i rami Git, le immagini sono taggate con il nome del ramo, per un ramo alla volta c'è solo un'immagine pubblicata con il nome di quel ramo. Per i tag Git, le immagini vengono contrassegnate in base al nome del tag.

Quando viene creato un nuovo tag Git, ad esempio quando viene rilasciata una nuova versione, verrà creato un nuovo tag Docker per tutte le immagini del progetto nel registro Docker:

  • 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 di immagine vengono passati attraverso i modelli Helm alla configurazione Kubernetes. Quando si avvia la distribuzione con il comando werf deploy il campo è in fase di aggiornamento image nei manifesti delle risorse Kubernetes e riavviando le risorse corrispondenti a causa del nome dell'immagine modificato.

Problema: nel caso in cui, infatti, non sia cambiato il contenuto dell'immagine rispetto al rollout precedente (tag Git), ma solo il suo tag Docker, ciò accade eccesso riavviando questa applicazione e, di conseguenza, sono possibili tempi di inattività. Sebbene non vi fosse alcun motivo reale per eseguire questo riavvio.

Di conseguenza, con l’attuale schema di tagging è necessario delimitare diversi repository Git separati e sorge il problema di organizzare l’implementazione di questi diversi repository. In generale, un tale schema risulta sovraccarico e complesso. È meglio combinare molti servizi in un unico repository e creare tag Docker in modo che non vi siano riavvii non necessari.

Etichettatura tramite commit Git

werf ha anche una strategia di tagging associata ai commit Git.

Git-commit è un identificatore per il contenuto di un repository Git e dipende dalla cronologia delle modifiche dei file nel repository Git, quindi sembra logico utilizzarlo per taggare le immagini nel registro Docker.

Tuttavia, il tagging tramite commit Git presenta gli stessi svantaggi del tagging tramite rami Git o tag Git:

  • Potrebbe essere creato un commit vuoto che non modifica alcun file, ma verrà modificato il tag Docker dell'immagine.
  • Potrebbe essere creato un commit di unione che non modifica i file, ma verrà modificato il tag Docker dell'immagine.
  • Potrebbe essere effettuato un commit che modifichi i file in Git che non sono importati nell'immagine e il tag Docker dell'immagine verrà modificato nuovamente.

Il tagging del nome del ramo Git non riflette la versione dell'immagine

C'è un altro problema associato alla strategia di tagging per i rami Git.

L'etichettatura in base al nome del ramo funziona finché i commit su quel ramo vengono raccolti sequenzialmente in ordine cronologico.

Se nello schema attuale l'utente inizia a ricostruire un vecchio commit associato a un determinato ramo, werf riscriverà l'immagine utilizzando il tag Docker corrispondente con una versione appena creata dell'immagine per il vecchio commit. Le distribuzioni che utilizzano questo tag da ora in poi corrono il rischio di estrarre una versione diversa dell'immagine al riavvio dei pod, di conseguenza la nostra applicazione perderà la connessione con il sistema CI e verrà desincronizzata.

Inoltre, con push successivi in ​​un ramo con un breve periodo di tempo tra loro, il vecchio commit potrebbe essere compilato più tardi di quello nuovo: la vecchia versione dell'immagine sovrascriverà quella nuova utilizzando il tag del ramo Git. Tali problemi possono essere risolti da un sistema CI/CD (ad esempio, in GitLab CI la pipeline di quest'ultimo viene avviata per una serie di commit). Tuttavia, non tutti i sistemi lo supportano e deve esserci un modo più affidabile per prevenire un problema così fondamentale.

Cos'è il tagging basato sul contenuto?

Allora, cos'è il tagging basato sul contenuto: taggare le immagini in base al contenuto.

Per creare i tag Docker non vengono utilizzate le primitive Git (ramo Git, tag Git...), ma un checksum associato a:

  • contenuto dell'immagine. Il tag ID immagine riflette il suo contenuto. Quando si crea una nuova versione, questo identificatore non cambierà se i file nell'immagine non sono cambiati;
  • storia della creazione di questa immagine in Git. Le immagini associate a diversi rami Git e a una diversa cronologia di build tramite werf avranno tag ID diversi.

Tale tag identificativo è il cosiddetto firma della fase dell'immagine.

Ogni immagine è composta da una serie di fasi: from, before-install, git-archive, install, imports-after-install, before-setup, ... git-latest-patch eccetera. Ogni fase ha un identificatore che ne riflette il contenuto − firma scenica (firma scenica).

L'immagine finale, composta da queste fasi, è contrassegnata con la cosiddetta firma dell'insieme di queste fasi - firma delle fasi, - che sta generalizzando per tutte le fasi dell'immagine.

Per ogni immagine dalla configurazione werf.yaml nel caso generale ci sarà la propria firma e, di conseguenza, un tag Docker.

La segnatura scenica risolve tutti questi problemi:

  • Resistente ai commit Git vuoti.
  • Resistente ai commit Git che modificano i file non rilevanti per l'immagine.
  • Non porta al problema di revisionare la versione corrente dell'immagine quando si riavviano le build per i vecchi commit Git di un ramo.

Questa è ora la strategia di tagging consigliata ed è quella predefinita in werf per tutti i sistemi CI.

Come abilitare e utilizzare in werf

Il comando ora ha un'opzione corrispondente werf publish: --tag-by-stages-signature=true|false

In un sistema CI, la strategia di tagging è specificata dal comando werf ci-env. In precedenza, il parametro era definito per questo werf ci-env --tagging-strategy=tag-or-branch. Ora, se specifichi werf ci-env --tagging-strategy=stages-signature oppure non specifichi questa opzione, werf utilizzerà la strategia di tagging per impostazione predefinita stages-signature. Squadra werf ci-env imposterà automaticamente i flag necessari per il comando werf build-and-publish (o werf publish), quindi non è necessario specificare opzioni aggiuntive 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ò creare le seguenti immagini:

  • registry.hello.com/web/core/system/backend:4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d
  • registry.hello.com/web/core/system/frontend:f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6

Qui 4ef339f84ca22247f01fb335bb19f46c4434014d8daa3d5d6f0e386d è una firma delle fasi dell'immagine backendE f44206457e0a4c8a54655543f749799d10a9fe945896dab1c16996c6 - firma delle fasi dell'immagine frontend.

Quando si utilizzano funzioni speciali werf_container_image и werf_container_env Non è necessario modificare nulla nei modelli Helm: queste funzioni genereranno automaticamente i nomi delle immagini corretti.

Configurazione di esempio in un sistema CI:

type multiwerf && source <(multiwerf use 1.1 beta)
type werf && source <(werf ci-env gitlab)
werf build-and-publish|deploy

Maggiori informazioni sulla configurazione sono disponibili nella documentazione:

In 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, il valore predefinito sarà stages-signature).
  • Se in precedenza hai utilizzato le opzioni di tagging per i commit Git (WERF_TAG_GIT_COMMIT o opzione werf publish --tag-git-commit COMMIT), quindi assicurati di passare alla strategia di tagging tappe-firma.
  • È meglio passare immediatamente ai nuovi progetti con il nuovo schema di tagging.
  • Quando si passa a werf 1.1, è consigliabile trasferire i vecchi progetti al nuovo schema di tagging, ma il vecchio tag-o-ramo è ancora supportato.

Il tagging basato sul contenuto risolve tutti i problemi trattati nell'articolo:

  • Resistenza al nome del tag Docker ai commit Git vuoti.
  • La resilienza del nome del tag Docker nei commit Git modifica i file irrilevanti per l'immagine.
  • Non porta al problema di revisionare la versione corrente dell'immagine quando si riavviano le build per i vecchi commit Git per i rami Git.

Usalo! E non dimenticare di venirci a trovare GitHubper creare un problema o trovarne uno esistente, aggiungere un plus, creare un PR o semplicemente osservare lo sviluppo del progetto.

PS

Leggi anche sul nostro blog:

Fonte: habr.com

Aggiungi un commento