Abbiamo già parlato del nostro strumento GitOps , e questa volta vorremmo condividere l'esperienza di assemblare il sito con la documentazione del progetto stesso — (la sua versione in lingua russa è — ). Si tratta di un sito statico ordinario, tuttavia, la sua costruzione è interessante perché si basa su un numero dinamico di artefatti.

Non ci soffermeremo sui dettagli della struttura del sito: generazione di un menu comune per tutte le versioni, pagine con informazioni sulle versioni, ecc. — invece, ci concentreremo su questioni e particolarità della costruzione dinamica e un po' sui processi collegati CI/CD.
Introduzione: come è strutturato il sito
Iniziamo dicendo che la documentazione di werf è conservata insieme al suo codice. Questo presenta alcune esigenze per lo sviluppo, che in generale esulano dall'ambito di questo articolo; ma almeno possiamo dire che:
- Nuove funzionalità di werf non devono essere rilasciate senza un aggiornamento della documentazione e, viceversa, eventuali modifiche alla documentazione implicano il rilascio di una nuova versione di werf;
- Il progetto ha uno sviluppo piuttosto intenso: nuove versioni possono essere rilasciate più volte al giorno;
- Qualsiasi operazione manuale per distribuire il sito con una nuova versione della documentazione è almeno noiosa;
- Nel progetto è adottato un approccio semantico , con 5 canali di stabilità. Il processo di rilascio implica un passaggio sequenziale delle versioni attraverso i canali in ordine crescente di stabilità: da alpha a rock-solid;
- Il sito ha una versione in lingua russa, che 'vive e si sviluppa' (cioè il cui contenuto viene aggiornato) parallelamente alla versione principale (cioè la versione in lingua inglese).
Per nascondere all'utente tutto questo 'dietro le quinte', offrendogli ciò che 'funziona semplicemente', abbiamo creato uno strumento separato per installare e aggiornare werf è . È sufficiente specificare il numero di versione e il canale di stabilità che si è disposti a utilizzare, e multiwerf verificherà se ci sono nuove versioni nel canale e le scaricherà se necessario.
Nel menu di selezione delle versioni sul sito sono disponibili le ultime versioni di werf in ogni canale. Per impostazione predefinita, all'indirizzo si apre la versione del canale più stabile per l'ultimo rilascio — essa viene indicizzata dai motori di ricerca. La documentazione per il canale è disponibile a indirizzi separati (ad esempio, per il rilascio beta 1.0).
In totale, il sito presenta le seguenti versioni:
- la radice (si apre per impostazione predefinita),
- per ogni canale di aggiornamento attivo di ciascun rilascio (ad esempio, ).
Per generare una versione specifica del sito, in generale è sufficiente compilare utilizzando , eseguendo nella directory /docs del repository werf il comando appropriato (jekyll build), dopo aver effettuato il checkout del tag Git della versione necessaria.
Rimane solo da aggiungere che:
- per la compilazione si utilizza lo strumento stesso (werf);
- i processi CI/CD sono costruiti su base GitLab CI;
- e tutto ciò, ovviamente, funziona in Kubernetes.
Problemi
Ora formuliamo compiti considerando tutta la specificità descritta:
- Dopo aver cambiato versione di werf su qualsiasi canale di aggiornamento la documentazione sul sito deve aggiornarsi automaticamente.
- Per lo sviluppo è necessario avere la possibilità di visualizzare occasionalmente le versioni preliminari del sito.
La ricompilazione del sito deve essere eseguita dopo aver cambiato la versione in qualsiasi canale dai rispettivi tag Git, ma nel processo di creazione dell'immagine otterremo le seguenti peculiarità:
- Poiché l'elenco delle versioni sui canali cambia, è necessario ricompilare solo la documentazione per i canali dove è cambiata la versione. Infatti, ricompilare tutto da capo non è molto elegante.
- L'insieme stesso dei canali per i rilasci può cambiare. In un certo momento, ad esempio, potrebbe non esserci una versione sui canali più stabili del rilascio early-access 1.1, ma col tempo appariranno — non è il caso di cambiare la compilazione manualmente?
Quindi, risulta che la compilazione dipende da dati esterni in mutamento.
Implementazione
Scelta dell'approccio
Come opzione, è possibile eseguire ogni versione necessaria in un pod separato in Kubernetes. Questa opzione implica un numero maggiore di oggetti nel cluster, che aumenterà con l'aumentare del numero di rilasci stabili di werf. Questo a sua volta implica una manutenzione più complessa: per ciascuna versione appare il proprio server HTTP, sebbene con un carico ridotto. Certo, ciò comporta anche maggiori spese in termini di risorse.
Noi abbiamo scelto la strada di compilare tutte le versioni necessarie in un'unica immagine. La statica compilata di tutte le versioni del sito si trova in un contenitore con NGINX, e il traffico verso il corrispondente Deployment arriva tramite NGINX Ingress. Una struttura semplice - un'applicazione stateless - consente di scalare facilmente il Deployment (a seconda del carico) con gli strumenti stessi di Kubernetes.
Per essere più precisi, raccogliamo due immagini: una per l'ambiente di produzione, l'altra - aggiuntiva - per l'ambiente di sviluppo. L'immagine aggiuntiva viene utilizzata (eseguita) solo nell'ambiente di sviluppo insieme a quella principale e contiene la versione del sito dal commit di revisione, mentre la routing tra di esse avviene tramite le risorse Ingress.
werf vs git clone e artefatti
Come già accennato, per generare la statica del sito per una versione specifica della documentazione, è necessario eseguire la build, passando al tag corrispondente del repository. Si potrebbe fare anche clonando il repository ogni volta durante la build, selezionando i tag appropriati dalla lista. Tuttavia, questa è un'operazione piuttosto onerosa e, inoltre, richiede di scrivere istruzioni non banali... Un altro serio svantaggio è che con questo approccio non è possibile memorizzare in cache qualcosa durante la build.
Qui ci viene in aiuto l'utilità werf, che implementa caching intelligente e consente di utilizzare . L'uso di werf per aggiungere codice dal repository accelera notevolmente la build, poiché werf sostanzialmente clona il repository una sola volta e poi esegue solo fetch se necessario. Inoltre, quando aggiungiamo dati dal repository possiamo scegliere solo le directory necessarie (nel nostro caso è la cartella docs), il che riduce notevolmente il volume dei dati aggiunti.
Poiché Jekyll è uno strumento progettato per compilare la statica e non è necessario nell'immagine finale, sarebbe logico eseguire la compilazione in , e nell'immagine finale importare solo il risultato della compilazione.
Scriviamo werf.yaml
Quindi, abbiamo deciso di compilare ogni versione in un artefatto werf separato. Tuttavia, noi non sappiamo quante di queste artefatti ci saranno durante la build, quindi non possiamo scrivere una configurazione di build fissa (strictly speaking, potremmo farlo, ma non sarebbe molto efficiente).
werf consente di utilizzare nel proprio file di configurazione (werf.yaml), e questo offre la possibilità generare la configurazione "al volo" a seconda dei dati esterni (quello che serve!). I dati esterni in questo caso sono rappresentati da informazioni sulle versioni e rilasci, sulla base delle quali raccogliamo il numero necessario di artefatti e otteniamo come risultato due immagini: werf-doc e werf-dev per l'esecuzione su diversi ambienti.
I dati esterni vengono passati attraverso variabili d'ambiente. Ecco la loro composizione:
-
RELEASES— una stringa con l'elenco dei rilasci e la corrispondente versione attuale di werf, sotto forma di elenco separato da spazi in formato%. Esempio:1.0%v1.0.4-beta.20 -
CHANNELS— una stringa con l'elenco dei canali e la corrispondente versione attuale di werf, sotto forma di elenco separato da spazi in formato%. Esempio:1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22 -
ROOT_VERSION— la versione di rilascio di werf che sarà visualizzata per impostazione predefinita sul sito (non è sempre necessario mostrare la documentazione per il numero di rilascio più alto). Esempio:v1.0.4-beta.20 -
REVIEW_SHA— il hash del commit di revisione, da cui è necessario raccogliere la versione per l'ambiente di test.
Queste variabili saranno popolati nel pipeline GitLab CI, e come precisamente — è scritto qui sotto.
Per prima cosa, per comodità, definiamo in werf.yaml variabili dei template Go, assegnando loro valori da variabili d'ambiente:
{{ $_ := set . "WerfVersions" (cat (env "CHANNELS") (env "RELEASES") | splitList " ") }}
{{ $Root := . }}
{{ $_ := set . "WerfRootVersion" (env "ROOT_VERSION") }}
{{ $_ := set . "WerfReviewCommit" (env "REVIEW_SHA") }} La descrizione dell'artefatto per la compilazione della statica della versione del sito è sostanzialmente identica per tutti i casi necessari (inclusa la generazione della versione radice e della versione per l'ambiente di sviluppo). Pertanto, la estrarremo in un blocco separato utilizzando la funzione define — per un successivo riutilizzo tramite include. Al modello passeremo i seguenti argomenti:
-
Version— la versione generata (nome del tag); -
Channel— il nome del canale di aggiornamento, per il quale viene generato l'artefatto; -
Commit— il hash del commit, se l'artefatto viene generato per il commit di revisione; - contesto.
Descrizione del modello di artefatto
{{- define "doc_artifact" -}}
{{- $Root := index . "Root" -}}
artifact: doc-{{ .Channel }}
from: jekyll/builder:3
mount:
- from: build_dir
to: /usr/local/bundle
ansible:
install:
- shell: |
export PATH=/usr/jekyll/bin/:$PATH
- name: "Installa le Dipendenze"
shell: bundle install
args:
executable: /bin/bash
chdir: /app/docs
beforeSetup:
{{- if .Commit }}
- shell: echo "Controlla SHA - {{ .Commit }}."
{{- end }}
{{- if eq .Channel "root" }}
- name: "releases.yml HASH: {{ $Root.Files.Get "releases.yml" | sha256sum }}"
copy:
content: |
{{ $Root.Files.Get "releases.yml" | indent 8 }}
dest: /app/docs/_data/releases.yml
{{- else }}
- file:
path: /app/docs/_data/releases.yml
state: touch
{{- end }}
- file:
path: "{{`{{ item }}`}}"
state: directory
mode: 0777
with_items:
- /app/main_site/
- /app/it_site/
- file:
dest: /app/docs/pages_it/cli
state: link
src: /app/docs/pages/cli
- shell: |
echo -e "werfVersion: {{ .Version }}nwerfChannel: {{ .Channel }}" > /tmp/_config_additional.yml
export PATH=/usr/jekyll/bin/:$PATH
{{- if and (ne .Version "review") (ne .Channel "root") }}
{{- $_ := set . "BaseURL" ( printf "v%s" .Channel ) }}
{{- else if ne .Channel "root" }}
{{- $_ := set . "BaseURL" .Channel }}
{{- end }}
jekyll build -s /app/docs -d /app/_main_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/tmp/_config_additional.yml
jekyll build -s /app/docs -d /app/_it_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/app/docs/_config_it.yml,/tmp/_config_additional.yml
args:
executable: /bin/bash
chdir: /app/docs
git:
- url: https://github.com/flant/werf.git
to: /app/
owner: jekyll
group: jekyll
{{- if .Commit }}
commit: {{ .Commit }}
{{- else }}
tag: {{ .Version }}
{{- end }}
stageDependencies:
install: ['docs/Gemfile','docs/Gemfile.lock']
beforeSetup: '**/*'
includePaths: 'docs'
excludePaths: '**/*.sh'
{{- end }} Il nome dell'artefatto deve essere unico. Possiamo raggiungere questo obiettivo, ad esempio, aggiungendo il nome del canale (il valore della variabile .Channel) come suffisso del nome dell'artefatto: artifact: doc-{{ .Channel }}. Ma bisogna tenere presente che durante l'importazione dagli artefatti sarà necessario fare riferimento a nomi simili.
Nella descrizione dell'artefatto si utilizza una funzionalità di werf chiamata . Il montaggio con la directory di servizio build_dir permette di conservare la cache di Jekyll tra i lanci della pipeline, il che accelera notevolmente la ricompilazione.
Potresti anche aver notato l'uso del file releases.yml — è un file YAML contenente dati sui rilasci, richiesto da (l'artefatto ottenuto durante l'esecuzione della pipeline). È necessario durante la compilazione del sito, ma nel contesto dell'articolo è interessante perché il suo stato influisce sulla ricompilazione di un solo artefatto — l'artefatto della versione principale del sito (negli altri artefatti non è necessario).
Questo è implementato tramite un operatore condizionale if dei template Go e della costruzione {{ $Root.Files.Get "releases.yml" | sha256sum }} nella fase . Funziona nel seguente modo: durante la costruzione dell'artefatto per la versione radice (la variabile .Channel è uguale a root) l'hash del file releases.yml influenza la firma dell'intero stadio, poiché è una componente del nome del task Ansible (parametro name). Pertanto, al cambiamento del contenuto del file releases.yml , l'artefatto corrispondente verrà ricostruito.
Prestare attenzione anche al lavoro con il repository esterno. Nell'immagine dell'artefatto da , viene aggiunta solo la directory /docs, mentre a seconda dei parametri forniti si aggiungono i dati del tag necessario o della review-commit.
Per utilizzare il modello dell'artefatto per generare la descrizione dell'artefatto delle versioni delle canalizzazioni e dei rilasci forniti, organizziamo un ciclo sulla variabile .WerfVersions in werf.yaml:
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ dict "Version" $VersionsDict._1 "Channel" $VersionsDict._0 "Root" $Root | include "doc_artifact" }}
---
{{ end -}} Poiché il ciclo genererà più artefatti (ci aspettiamo di sì), è necessario considerare il separatore tra di essi — la sequenza --- (per ulteriori dettagli sulla sintassi del file di configurazione, vedere ). Come stabilito in precedenza, durante la chiamata del modello nel ciclo, passiamo i parametri della versione, URL e contesto radice.
Analogamente, ma senza ciclo, chiamiamo il modello dell'artefatto per «casi speciali»: per la versione radice e anche la versione della review-commit:
{{ dict "Version" .WerfRootVersion "Channel" "root" "Root" $Root | include "doc_artifact" }}
---
{{- if .WerfReviewCommit }}
{{ dict "Version" "review" "Channel" "review" "Commit" .WerfReviewCommit "Root" $Root | include "doc_artifact" }}
{{- end }} Si noti che l'artefatto per la review-commit verrà costruito solo se è impostata la variabile .WerfReviewCommit.
Gli artefatti sono pronti: è ora di occuparsi dell'importazione!
L'immagine finale destinata a essere eseguita in Kubernetes è un normale NGINX, a cui è stato aggiunto il file di configurazione del server nginx.conf e la statica degli artefatti. Oltre all'artefatto della versione radice del sito, dobbiamo ripetere il ciclo sulla variabile .WerfVersions per importare gli artefatti delle versioni delle canalizzazioni e dei rilasci + attenersi alla regola di denominazione degli artefatti che abbiamo adottato in precedenza. Poiché ogni artefatto memorizza le versioni del sito per due lingue, le importeremo nei luoghi previsti dalla configurazione.
Descrizione dell'immagine finale werf-doc
immagine: werf-doc
from: nginx:stable-alpine
ansible:
setup:
- name: "Configura \/etc\/nginx\/nginx.conf"
copy:
content: |
{{ .Files.Get ".werf\/nginx.conf" | indent 8 }}
dest: \/etc\/nginx\/nginx.conf
- file:
path: "{{`{{ item }}`}}"
state: directory
mode: 0777
with_items:
- \/app\/main_site\/assets
- \/app\/ru_site\/assets
import:
- artifact: doc-root
add: \/app\/_main_site
to: \/app\/main_site
before: setup
- artifact: doc-root
add: \/app\/_ru_site
to: \/app\/ru_site
before: setup
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ $Channel := $VersionsDict._0 -}}
{{ $Version := $VersionsDict._1 -}}
- artifact: doc-{{ $Channel }}
add: \/app\/_main_site
to: \/app\/main_site\/v{{ $Channel }}
before: setup
{{ end -}}
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ $Channel := $VersionsDict._0 -}}
{{ $Version := $VersionsDict._1 -}}
- artifact: doc-{{ $Channel }}
add: \/app\/_ru_site
to: \/app\/ru_site\/v{{ $Channel }}
before: setup
{{ end -}}Un'immagine aggiuntiva, che viene eseguita insieme a quella principale nel contesto dev, contiene solo due versioni del sito: la versione della revisione e la versione principale del sito (dove si trovano le risorse comuni e, se ricordi, i dati sui rilasci). Pertanto, l'immagine aggiuntiva varierà dalla principale solo nella sezione di importazione (e, naturalmente, nel nome):
immagine: werf-dev
...
import:
- artifact: doc-root
add: \/app\/_main_site
to: \/app\/main_site
before: setup
- artifact: doc-root
add: \/app\/_ru_site
to: \/app\/ru_site
before: setup
{{- if .WerfReviewCommit }}
- artifact: doc-review
add: \/app\/_main_site
to: \/app\/main_site\/review
before: setup
- artifact: doc-review
add: \/app\/_ru_site
to: \/app\/ru_site\/review
before: setup
{{- end }} Come già accennato sopra, l'artefatto per la revisione verrà generato solo quando viene impostata la variabile d'ambiente. REVIEW_SHANon sarebbe necessario generare affatto l'immagine werf-dev se non ci fosse una variabile d'ambiente. REVIEW_SHA, ma per garantire che delle immagini Docker in werf funzioni per l'immagine werf-dev, la lasceremo essere costruita solo con l'artefatto della versione principale (è già stata costruita), per semplificare la struttura del pipeline.
La costruzione è pronta! Passiamo a CI\/CD e ai dettagli importanti.
Pipeline in GitLab CI e caratteristiche della costruzione dinamica
Durante l'avvio della costruzione, dobbiamo impostare le variabili d'ambiente utilizzate in werf.yaml. Questo non riguarda la variabile REVIEW_SHA, che imposteremo durante la chiamata del pipeline dal webhook di GitHub.
Esternalizzeremo la generazione dei dati necessari in uno script Bash generate_artifacts, che genererà due artefatti per il pipeline GitLab:
- un file
releases.ymlcontenente i dati sui rilasci, - un file
common_envs.sh, contenente le variabili d'ambiente per l'esportazione.
Il contenuto del file generate_artifacts lo troverai nel nostro . L'ottenimento dei dati non è oggetto dell'articolo, mentre il file common_envs.sh è importante poiché influisce sul funzionamento di werf. Ecco un esempio del suo contenuto:
export RELEASES='1.0%v1.0.6-4'
export CHANNELS='1.0-alpha%v1.0.7-1 1.0-beta%v1.0.7-1 1.0-ea%v1.0.6-4 1.0-stable%v1.0.6-4 1.0-rock-solid%v1.0.6-4'
export ROOT_VERSION='v1.0.6-4' È possibile utilizzare il risultato di questo script, ad esempio, tramite una funzione Bash source.
E ora la parte più interessante. Affinché sia la build che il deployment dell'applicazione funzionino correttamente, è necessario assicurarsi che werf.yaml è stata sia identico almeno nell'ambito di un pipeline. Se questa condizione non viene rispettata, le firme delle fasi calcolate da werf durante la build e, ad esempio, il deployment, saranno diverse. Questo porterà a un errore di deployment, poiché l'immagine necessaria per il deployment sarà assente.
In altre parole, se durante la build dell'immagine del sito le informazioni su rilasci e versioni sono una, mentre al momento del deployment esce una nuova versione e le variabili d'ambiente hanno valori diversi, il deployment terminerà con un errore: poiché l'artefatto della nuova versione non è ancora stato costruito.
Se la generazione werf.yaml dipende da dati esterni (ad esempio, un elenco di versioni attuali, come nel nostro caso), la composizione e i valori di questi dati devono essere fissati nell'ambito del pipeline. Questo è particolarmente importante se i parametri esterni cambiano abbastanza frequentemente.
Noi ottimizzeremo e fisseremo i dati esterni nella prima fase del pipeline in GitLab (Prebuild) e li passeremo ulteriormente come artefatto GitLab CI. Questo permetterà di eseguire e rieseguire i compiti del pipeline (build, deployment, pulizia) con una configurazione identica in werf.yaml.
Contenuto della fase Prebuild del file .gitlab-ci.yml:
Prebuild:
stage: prebuild
script:
- bash .\/generate_artifacts 1> common_envs.sh
- cat .\/common_envs.sh
artifacts:
paths:
- releases.yml
- common_envs.sh
expire_in: 2 weekFissando i dati esterni nell'artefatto, è possibile eseguire la build e il deployment utilizzando le fasi standard del pipeline GitLab CI: Build e Deploy. Avviamo il pipeline tramite gli hook dal repository GitHub di werf (cioè in caso di modifiche nel repository su GitHub). I dati per questi possono essere presi nelle proprietà del progetto GitLab nella sezione CI / CD Settings -> Pipeline triggers, e poi creeremo in GitHub il corrispondente Webhook (Settings -> Webhooks).
La fase di build apparirà come segue:
Build:
stage: build
script:
- type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- source common_envs.sh
- werf build-and-publish --stages-storage :local
except:
refs:
- schedules
dependencies:
- Prebuild GitLab aggiungerà alla fase di build due artefatti dalla fase Prebuild, così esporteremo le variabili con i dati di input preparati utilizzando la costruzione source common_envs.sh. Avviamo la fase di assemblaggio in tutti i casi, ad eccezione dell'avvio del pipeline su base programmata. Il pipeline per la pulizia verrà attivato secondo il programma — non è necessario eseguire l'assemblaggio in questo caso.
Nella fase di deployment descriveremo due task — separatamente per il deployment sugli ambienti production e dev, utilizzando il modello YAML:
.base_deploy: &base_deploy
stage: deploy
script:
- type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- source common_envs.sh
- werf deploy --stages-storage :local
dependencies:
- Prebuild
except:
refs:
- schedules
Deploy to Production:
<<: *base_deploy
variables:
WERF_KUBE_CONTEXT: prod
environment:
name: production
url: werf.io
only:
refs:
- master
except:
variables:
- $REVIEW_SHA
refs:
- schedules
Deploy to Test:
<<: *base_deploy
variables:
WERF_KUBE_CONTEXT: dev
environment:
name: test
url: werf.test.flant.com
except:
refs:
- schedules
only:
variables:
- $REVIEW_SHA I task si distinguono essenzialmente solo per l'indicazione del contesto del cluster in cui werf deve eseguire il deployment (WERF_KUBE_CONTEXT), e per l'impostazione delle variabili d'ambiente dell'ambiente (environment.name e environment.url), che vengono poi utilizzate nei modelli del chart Helm. Non presenteremo il contenuto dei modelli, poiché non ci sono elementi interessanti per l'argomento in questione, ma puoi trovarli nel .
Ultimo ritocco
Poiché le versioni di werf vengono rilasciate abbastanza frequentemente, verranno anche costruite nuove immagini, e il Docker Registry continuerà a crescere. È quindi indispensabile configurare la pulizia automatica delle immagini secondo le politiche. Farlo è molto semplice.
Per implementare ciò sarà necessario:
- Aggiungere una fase di pulizia in
.gitlab-ci.yml; - Aggiungere l'esecuzione periodica del task di pulizia;
- Configurare la variabile d'ambiente con il token di accesso in scrittura.
Aggiungiamo una fase di pulizia in .gitlab-ci.yml:
Cleanup:
stage: cleanup
script:
- type multiwerf && . $(multiwerf use 1.0 alpha --as-file)
- type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose)
- source common_envs.sh
- docker login -u nobody -p ${WERF_IMAGES_CLEANUP_PASSWORD} ${WERF_IMAGES_REPO}
- werf cleanup --stages-storage :local
only:
refs:
- schedules
Quasi tutto ciò l'abbiamo già visto poco sopra — solo per la pulizia è necessario autenticarsi in precedenza nel Docker Registry con un token che ha diritti di cancellazione delle immagini nel Docker Registry (il token generato automaticamente per i job di GitLab CI non ha tali diritti). È necessario creare il token in GitLab in anticipo e indicare il suo valore nella variabile d'ambiente WERF_IMAGES_CLEANUP_PASSWORD del progetto (CI/CD Settings -> Variables).
L'aggiunta del task di pulizia con il programma necessario viene effettuata in CI/CD ->
Programmi.
Tutto: il progetto nel Docker Registry non crescerà più costantemente a causa di immagini non utilizzate.
Alla fine della parte pratica, ricordo che i listing completi dell'articolo sono disponibili in :
- ;
- .
Risultato
- Abbiamo ottenuto una struttura di build logica: un artefatto per ogni versione.
- La build è universale e non richiede modifiche manuali con il rilascio di nuove versioni di werf: la documentazione sul sito viene automaticamente aggiornata.
- Vengono creati due immagini per contorni diversi.
- Funziona rapidamente, poiché sfrutta al massimo la memorizzazione nella cache: con il rilascio di una nuova versione di werf o l'invocazione di un hook di GitHub per un commit di revisione, viene effettuata la ricostruzione solo dell'artefatto corrispondente con la versione modificata.
- Non è necessario pensare alla rimozione di immagini non utilizzate: la pulizia secondo le politiche di werf manterrà l'ordine nel Docker Registry.
Conclusioni
- L'uso di werf consente alla build di funzionare rapidamente grazie alla memorizzazione nella cache sia della build stessa che della memorizzazione nella cache durante il lavoro con repository esterni.
- Lavorare con repository Git esterni elimina la necessità di clonare nuovamente l'intero repository ogni volta o di reinventare la ruota con logiche di ottimizzazione complesse. werf utilizza la cache e clona solo una volta, e poi utilizza
fetche solo se necessario. - La possibilità di utilizzare modelli Go nel file di configurazione della build
werf.yamlconsente di descrivere una build il cui risultato dipende da dati esterni. - L'uso del montaggio in werf accelera significativamente la raccolta di artefatti — grazie alla cache condivisa tra tutti i pipeline.
- werf consente di configurare facilmente la pulizia, particolarmente rilevante in una build dinamica.
P.S.
Leggi anche nel nostro blog:
- «»;
- «»;
- «»;
- «».
Fonte: habr.com
