Asamblarea dinamică și implementarea imaginilor Docker cu werf folosind exemplul unui site de documentație cu versiuni

Am vorbit deja despre instrumentul nostru GitOps de mai multe ori. werf, și de data aceasta am dori să împărtășim experiența noastră în asamblarea șantierului cu documentația proiectului în sine - werf.io (versiunea sa în limba rusă este en.werf.io). Acesta este un site static obișnuit, dar ansamblul său este interesant prin faptul că este construit folosind un număr dinamic de artefacte.

Asamblarea dinamică și implementarea imaginilor Docker cu werf folosind exemplul unui site de documentație cu versiuni

Intrați în nuanțele structurii site-ului: generarea unui meniu comun pentru toate versiunile, pagini cu informații despre lansări etc. - nu vom. În schimb, să ne concentrăm pe problemele și caracteristicile asamblarii dinamice și puțin pe procesele CI/CD însoțitoare.

Introducere: cum funcționează site-ul

Pentru început, documentația werf este stocată împreună cu codul său. Acest lucru impune anumite cerințe de dezvoltare care depășesc, în general, domeniul de aplicare al acestui articol, dar cel puțin se poate spune că:

  • Noile funcții werf nu trebuie lansate fără actualizarea documentației și, dimpotrivă, orice modificare a documentației implică lansarea unei noi versiuni de werf;
  • Proiectul are o dezvoltare destul de intensivă: versiuni noi pot fi lansate de mai multe ori pe zi;
  • Orice operațiuni manuale de implementare a unui site cu o nouă versiune de documentație sunt cel puțin plictisitoare;
  • Proiectul adoptă o abordare semantică versiunea, cu 5 canale de stabilitate. Procesul de lansare presupune trecerea secvențială a versiunilor prin canale în ordinea creșterii stabilității: de la alfa la solid;
  • Site-ul are o versiune în limba rusă, care „trăiește și se dezvoltă” (adică, al cărei conținut este actualizat) în paralel cu versiunea principală (adică, în limba engleză).

Pentru a ascunde toată această „bucătărie interioară” de utilizator, oferindu-i ceva care „pur și simplu funcționează”, am făcut instrument separat de instalare și actualizare werf - E multiwerf. Trebuie doar să specificați numărul de lansare și canalul de stabilitate pe care sunteți gata să îl utilizați, iar multiwerf va verifica dacă există o versiune nouă pe canal și o va descărca dacă este necesar.

În meniul de selecție a versiunilor de pe site, cele mai recente versiuni de werf sunt disponibile pe fiecare canal. Implicit, după adresă werf.io/documentation se deschide versiunea celui mai stabil canal pentru cea mai recentă lansare - este indexată și de motoarele de căutare. Documentația pentru canal este disponibilă la adrese separate (de exemplu, werf.io/v1.0-beta/documentation pentru versiunea beta 1.0).

În total, site-ul are următoarele versiuni disponibile:

  1. root (se deschide implicit),
  2. pentru fiecare canal de actualizare activ al fiecărei versiuni (de exemplu, werf.io/v1.0-beta).

Pentru a genera o anumită versiune a unui site, în general, este suficient să o compilați folosind Jekyllrulând în director /docs comanda corespunzătoare pentru depozitul werf (jekyll build), după trecerea la eticheta Git a versiunii necesare.

Rămâne doar să adăugăm că:

  • utilitatea în sine (werf) este folosită pentru asamblare;
  • Procesele CI/CD sunt construite pe baza GitLab CI;
  • și toate acestea, desigur, rulează în Kubernetes.

sarcini

Acum să formulăm sarcini care iau în considerare toate specificul descris:

  1. După schimbarea versiunii werf pe orice canal de actualizare documentația de pe site ar trebui actualizată automat.
  2. Pentru dezvoltare trebuie să fii capabil uneori vizualizați versiunile de previzualizare ale site-ului.

Site-ul trebuie recompilat după schimbarea versiunii pe orice canal din etichetele Git corespunzătoare, dar în procesul de construire a imaginii vom obține următoarele caracteristici:

  • Deoarece lista versiunilor de pe canale se modifică, este necesar doar să reconstruiți documentația pentru canalele în care versiunea sa schimbat. La urma urmei, a reconstrui totul din nou nu este foarte frumos.
  • Setul de canale pentru lansări se poate schimba. La un moment dat, de exemplu, este posibil să nu existe o versiune pe canale mai stabilă decât versiunea 1.1 cu acces anticipat, dar în timp vor apărea - în acest caz, nu ar trebui să schimbați ansamblul manual?

Se pare că asamblarea depinde de modificarea datelor externe.

punerea în aplicare

Alegerea unei abordări

Alternativ, puteți rula fiecare versiune necesară ca un pod separat în Kubernetes. Această opțiune implică un număr mai mare de obiecte în cluster, care va crește odată cu creșterea numărului de lansări stabile de werf. Și aceasta, la rândul său, implică o întreținere mai complexă: fiecare versiune are propriul server HTTP și cu o încărcare mică. Desigur, acest lucru implică și costuri mai mari ale resurselor.

Am urmat aceeași cale asamblarea tuturor versiunilor necesare într-o singură imagine. Statica compilată a tuturor versiunilor site-ului se află într-un container cu NGINX, iar traficul către implementarea corespunzătoare vine prin NGINX Ingress. O structură simplă - o aplicație fără stat - vă permite să scalați cu ușurință Deployment (în funcție de încărcare) folosind Kubernetes însuși.

Pentru a fi mai precis, colectăm două imagini: una pentru circuitul de producție, a doua este una suplimentară pentru circuitul de dezvoltare. Imaginea suplimentară este folosită (lansată) doar pe circuitul dev împreună cu cel principal și conține versiunea site-ului din comiterea de revizuire, iar rutarea între ele se realizează folosind resursele Ingress.

clona și artefacte werf vs git

După cum sa menționat deja, pentru a genera statice de site pentru o anumită versiune a documentației, trebuie să construiți prin trecerea la eticheta de depozit corespunzătoare. De asemenea, puteți face acest lucru prin clonarea depozitului de fiecare dată când construiți, selectând etichetele corespunzătoare dintr-o listă. Cu toate acestea, aceasta este o operațiune destul de intensivă în resurse și, în plus, necesită scrierea unor instrucțiuni non-triviale... Un alt dezavantaj serios este că prin această abordare nu există nicio modalitate de a stoca ceva în cache în timpul asamblarii.

Aici ne vine în ajutor utilitatea werf în sine, implementând cache inteligentă și vă permite să utilizați depozite externe. Utilizarea werf pentru a adăuga cod din depozit va grăbi semnificativ construirea, deoarece werf clonează în esență depozitul o dată și apoi îl execută numai fetch daca este necesar. În plus, la adăugarea datelor din depozit, putem selecta doar directoarele necesare (în cazul nostru acesta este directorul docs), ceea ce va reduce semnificativ cantitatea de date adăugate.

Deoarece Jekyll este un instrument conceput pentru compilarea datelor statice și nu este necesar în imaginea finală, ar fi logic să compilați în artefact werf, și în imaginea finală importați doar rezultatul compilației.

Scriem werf.yaml

Deci, am decis că vom compila fiecare versiune într-un artefact werf separat. Totuși noi nu știm câte dintre aceste artefacte vor fi în timpul asamblarii, așa că nu putem scrie o configurație fixă ​​de construcție (strict vorbind, încă mai putem, dar nu va fi pe deplin eficientă).

werf vă permite să utilizați Go șabloane în fișierul dvs. de configurare (werf.yaml), iar acest lucru îl face posibil genera config din mers în funcție de datele externe (de ce aveți nevoie!). Datele externe în cazul nostru sunt informații despre versiuni și versiuni, pe baza cărora colectăm numărul necesar de artefacte și, ca urmare, obținem două imagini: werf-doc и werf-dev să ruleze pe diferite circuite.

Datele externe sunt transmise prin variabilele de mediu. Iată compoziția lor:

  • RELEASES — o linie cu o listă de versiuni și versiunea curentă corespunzătoare a werf, sub forma unei liste de valori separate prin spațiu în format <НОМЕР_РЕЛИЗА>%<НОМЕР_ВЕРСИИ>... Exemplu: 1.0%v1.0.4-beta.20
  • CHANNELS — o linie cu o listă de canale și versiunea curentă corespunzătoare a werf, sub forma unei liste de valori separate prin spațiu în format <КАНАЛ>%<НОМЕР_ВЕРСИИ>... Exemplu: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERSION — versiunea de lansare werf să fie afișată implicit pe site (nu este întotdeauna necesar să afișați documentația după cel mai mare număr de lansare). Exemplu: v1.0.4-beta.20
  • REVIEW_SHA — hash al comiterii de revizuire din care trebuie să construiți versiunea pentru bucla de testare.

Aceste variabile vor fi completate în pipeline-ul GitLab CI și cum este scris mai jos.

În primul rând, pentru comoditate, definim în werf.yaml Go variabilele șablon, atribuindu-le valori din variabilele de mediu:

{{ $_ := set . "WerfVersions" (cat (env "CHANNELS") (env "RELEASES") | splitList " ") }}
{{ $Root := . }}
{{ $_ := set . "WerfRootVersion" (env "ROOT_VERSION") }}
{{ $_ := set . "WerfReviewCommit" (env "REVIEW_SHA") }}

Descrierea artefactului pentru compilarea versiunii statice a site-ului este, în general, aceeași pentru toate cazurile de care avem nevoie (inclusiv generarea versiunii root, precum și a versiunii pentru circuitul de dezvoltare). Prin urmare, îl vom muta într-un bloc separat folosind funcția define - pentru reutilizare ulterioară include. Vom transmite șablonului următoarele argumente:

  • Version — versiunea generată (numele etichetei);
  • Channel — numele canalului de actualizare pentru care este generat artefactul;
  • Commit — commit hash, dacă artefactul este generat pentru un commit de revizuire;
  • context.

Descriere șablon artefact

{{- 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: "Install Dependencies"
    shell: bundle install
    args:
      executable: /bin/bash
      chdir: /app/docs
  beforeSetup:
{{- if .Commit }}
  - shell: echo "Review 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/ru_site/
  - file:
      dest: /app/docs/pages_ru/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/_ru_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/app/docs/_config_ru.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 }}

Numele artefactului trebuie să fie unic. Putem realiza acest lucru, de exemplu, adăugând numele canalului (valoarea variabilei .Channel) ca sufix la numele artefactului: artifact: doc-{{ .Channel }}. Dar trebuie să înțelegeți că atunci când importați din artefacte, va trebui să vă referiți la aceleași nume.

Când descrieți un artefact, se utilizează următoarea caracteristică werf: montare. Montajul indicând directorul de service build_dir vă permite să salvați memoria cache Jekyll între rulările pipeline, ceea ce accelerează semnificativ reasamblarea.

Este posibil să fi observat și utilizarea fișierului releases.yml este un fișier YAML cu date de lansare solicitate de la github.com (un artefact obținut la executarea unei conducte). Este necesar la compilarea site-ului, dar în contextul articolului este interesant pentru noi deoarece depinde de starea acestuia reasamblarea unui singur artefact — un artefact al versiunii rădăcină a site-ului (nu este necesar în alte artefacte).

Acest lucru este implementat folosind instrucțiunea condiționată if Go șabloane și modele {{ $Root.Files.Get "releases.yml" | sha256sum }} în scenă etape. Funcționează după cum urmează: la construirea unui artefact pentru versiunea rădăcină (variabilă .Channel este egal cu root) fișier hash releases.yml afectează semnătura întregii etape, deoarece face parte din numele sarcinii Ansible (parametru name). Astfel, la schimbare conţinut fişier releases.yml artefactul corespunzător va fi reasamblat.

De asemenea, acordați atenție lucrului cu un depozit extern. În imaginea unui artefact din depozit werf, doar directorul este adăugat /docs, iar în funcție de parametrii trecuți, datele etichetei necesare sau comiterii de revizuire sunt adăugate imediat.

Pentru a folosi șablonul de artefact pentru a genera o descriere a artefactului versiunilor transferate de canale și versiuni, organizăm o buclă pe variabilă .WerfVersions в werf.yaml:

{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ dict "Version" $VersionsDict._1 "Channel" $VersionsDict._0 "Root" $Root | include "doc_artifact" }}
---
{{ end -}}

Deoarece bucla va genera mai multe artefacte (sperăm că da), este necesar să se țină cont de separatorul dintre ele - secvența --- (Pentru mai multe informații despre sintaxa fișierului de configurare, consultați documentație). După cum am definit mai devreme, atunci când apelăm un șablon într-o buclă, transmitem parametrii versiunii, URL-ul și contextul rădăcină.

În mod similar, dar fără o buclă, numim șablonul artefact pentru „cazuri speciale”: pentru versiunea rădăcină, precum și versiunea din comiterea de revizuire:

{{ 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 }}

Vă rugăm să rețineți că artefactul pentru comiterea de revizuire va fi construit numai dacă variabila este setată .WerfReviewCommit.

Artefactele sunt gata - este timpul să începeți importul!

Imaginea finală, concepută pentru a rula pe Kubernetes, este un NGINX obișnuit cu un fișier de configurare a serverului adăugat nginx.conf și statică din artefacte. Pe lângă artefactul versiunii rădăcină a site-ului, trebuie să repetăm ​​bucla pe variabilă .WerfVersions pentru a importa artefacte ale versiunilor de canal și lansare + urmați regula de denumire a artefactelor pe care am adoptat-o ​​mai devreme. Deoarece fiecare artefact stochează versiuni ale site-ului pentru două limbi, le importăm în locurile oferite de configurație.

Descrierea imaginii finale werf-doc

image: werf-doc
from: nginx:stable-alpine
ansible:
  setup:
  - name: "Setup /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 -}}

Imaginea suplimentară, care, împreună cu cea principală, este lansată pe circuitul dev, conține doar două versiuni ale site-ului: versiunea din review commit și versiunea root a site-ului (există active generale și, dacă vă amintiți, , date de eliberare). Astfel, imaginea suplimentară va diferi de cea principală doar în secțiunea de import (și, bineînțeles, în nume):

image: 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 }}

După cum s-a menționat mai sus, artefactul pentru comiterea de revizuire va fi generat numai atunci când este rulată variabila de mediu setată REVIEW_SHA. Ar fi posibil să nu se genereze deloc imaginea werf-dev dacă nu există nicio variabilă de mediu REVIEW_SHA, dar pentru a curatenie prin politici Imaginile Docker în werf au funcționat pentru imaginea werf-dev, o vom lăsa să fie construită doar cu artefactul versiunii root (este deja construit oricum), pentru a simplifica structura conductei.

Asamblarea este gata! Să trecem la CI/CD și la nuanțe importante.

Pipeline în GitLab CI și caracteristici ale construirii dinamice

Când rulăm construcția, trebuie să setăm variabilele de mediu utilizate în werf.yaml. Acest lucru nu se aplică variabilei REVIEW_SHA, pe care o vom seta atunci când apelăm pipeline din hook-ul GitHub.

Vom genera datele externe necesare într-un script Bash generate_artifacts, care va genera două artefacte de conductă GitLab:

  • fișier releases.yml cu date de lansare,
  • fișier common_envs.sh, care conține variabilele de mediu care urmează să fie exportate.

Conținutul fișierului generate_artifacts veți găsi în nostru depozite cu exemple. Primirea datelor în sine nu este subiectul articolului, ci dosarul common_envs.sh este important pentru noi, pentru că munca lui werf depinde de asta. Un exemplu de conținut:

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'

Puteți utiliza rezultatul unui astfel de script, de exemplu, folosind funcția Bash source.

Acum vine partea distractivă. Pentru ca atât construirea, cât și implementarea aplicației să funcționeze corect, este necesar să se asigure că werf.yaml a fost aceeași cel putin într-o singură conductă. Dacă această condiție nu este îndeplinită, atunci semnăturile etapelor pe care werf le calculează în timpul asamblarii și, de exemplu, a desfășurării, vor fi diferite. Acest lucru va duce la o eroare de implementare, deoarece... imaginea necesară pentru desfășurare va lipsi.

Cu alte cuvinte, dacă în timpul asamblarii imaginii site-ului informațiile despre versiuni și versiuni sunt aceleași, iar în momentul implementării este lansată o nouă versiune și variabilele de mediu au valori diferite, atunci implementarea va eșua cu o eroare: la urma urmei, artefactul noii versiuni nu a fost încă construit.

Dacă generaţie werf.yaml depinde de datele externe (de exemplu, o listă de versiuni curente, ca în cazul nostru), atunci compoziția și valorile acestor date ar trebui înregistrate în conductă. Acest lucru este deosebit de important dacă parametrii externi se modifică destul de des.

O vom face primiți și înregistrați date externe în prima etapă a conductei în GitLab (Preconstruire) și transmiteți-le în continuare sub formă Artefact GitLab CI. Acest lucru vă va permite să rulați și să reporniți lucrări pipeline (construire, implementare, curățare) cu aceeași configurație în werf.yaml.

Conținutul scenei Preconstruire fişier .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 week

După ce ați capturat datele externe în artefact, puteți construi și implementa folosind etapele standard ale pipelinei GitLab CI: Build and Deploy. Lansăm conducta în sine folosind cârlige din depozitul werf GitHub (adică atunci când există modificări în depozitul GitHub). Datele pentru acestea pot fi găsite în proprietățile proiectului GitLab din secțiunea Setări CI/CD -> Declanșatoare pipelineși apoi creați Webhook-ul corespunzător în GitHub (Setări -> Webhooks).

Etapa de construire va arăta astfel:

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 va adăuga două artefacte de la stadiul la etapa de construire Preconstruire, deci exportăm variabile cu date de intrare pregătite folosind constructul source common_envs.sh. Începem etapa de construcție în toate cazurile, cu excepția lansării conductei conform unui program. Conform programului, vom rula o conductă pentru curățare - în acest caz nu este nevoie să efectuați asamblarea.

În etapa de implementare, vom descrie două sarcini - separat pentru implementare în circuitele de producție și de dezvoltare, folosind un șablon 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

Sarcinile diferă în esență doar prin a indica contextul clusterului în care werf ar trebui să efectueze implementarea (WERF_KUBE_CONTEXT) și setarea variabilelor de mediu buclei (environment.name и environment.url), care sunt apoi folosite în șabloanele de diagrame Helm. Nu vom furniza conținutul șabloanelor, deoarece... nu există nimic interesant acolo pentru subiectul în cauză, dar le puteți găsi în depozite pentru articol.

Efectul final

Deoarece versiunile werf sunt lansate destul de des, imagini noi vor fi create frecvent, iar Registrul Docker va crește constant. Prin urmare, este imperativ să configurați curățarea automată a imaginii pe baza politicilor. Este foarte ușor de făcut.

Pentru implementare veți avea nevoie de:

  • Adăugați un pas de curățare la .gitlab-ci.yml;
  • Adăugați execuția periodică a unei sarcini de curățare;
  • Configurați o variabilă de mediu cu un jeton de acces la scriere.

Adăugarea unei etape de curățare la .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

Am văzut deja aproape toate acestea puțin mai sus - doar pentru a le curăța, trebuie să vă conectați mai întâi la Docker Registry cu un token care are drepturi de ștergere a imaginilor din Docker Registry (tokenul de activitate GitLab CI emis automat nu au astfel de drepturi). Tokenul trebuie creat în prealabil în GitLab, iar valoarea acestuia trebuie specificată în variabila de mediu WERF_IMAGES_CLEANUP_PASSWORD proiect (Setări CI/CD -> Variabile).

Adăugarea unei sarcini de curățare cu programul necesar se face în CI/CD ->
orarele
.

Asta este: un proiect din Registrul Docker nu va mai crește constant din imagini neutilizate.

La sfârșitul părții practice, permiteți-mi să vă reamintesc că listările complete din articol sunt disponibile în merge:

Rezultat

  1. Am primit o structură de asamblare logică: un artefact per versiune.
  2. Ansamblul este universal și nu necesită modificări manuale atunci când sunt lansate versiuni noi de werf: documentația de pe site este actualizată automat.
  3. Două imagini sunt asamblate pentru diferite contururi.
  4. Funcționează rapid, pentru că Memorarea în cache este folosită cât mai mult posibil - atunci când este lansată o nouă versiune de werf sau este apelat un hook GitHub pentru o comitere de revizuire, numai artefactul corespunzător cu versiunea modificată este reconstruit.
  5. Nu trebuie să vă gândiți la ștergerea imaginilor neutilizate: curățarea conform politicilor werf va menține Registrul Docker în ordine.

Constatări

  • Utilizarea werf permite ansamblului să funcționeze rapid datorită stocării în cache atât a ansamblului în sine, cât și a stocării în cache atunci când lucrați cu depozite externe.
  • Lucrul cu depozite Git externe elimină nevoia de a clona întregul depozit de fiecare dată sau de a reinventa roata cu o logică de optimizare complicată. werf folosește un cache și face clonarea o singură dată, apoi folosește fetch și numai atunci când este necesar.
  • Abilitatea de a utiliza șabloanele Go în fișierul de configurare a construirii werf.yaml vă permite să descrieți un ansamblu al cărui rezultat depinde de date externe.
  • Utilizarea mount in werf accelerează semnificativ colectarea de artefacte - datorită memoriei cache, care este comună tuturor conductelor.
  • werf facilitează configurarea curățării, ceea ce este deosebit de important atunci când se construiește dinamic.

PS

Citește și pe blogul nostru:

Sursa: www.habr.com

Adauga un comentariu