We hebben al verschillende keren gesproken over onze GitOps-tool , en dit keer willen we onze ervaring delen met het bouwen van de website met de documentatie van het project zelf — (de Nederlandstalige versie — ). Het is een gewone statische website, maar de opbouw is interessant omdat deze gebruikmaakt van een dynamisch aantal artefacten.

We zullen niet ingaan op de nuances van de structuur van de website: zoals het genereren van een algemeen menu voor alle versies, pagina's met informatie over releases, enz. In plaats daarvan richten we ons op de vragen en bijzonderheden van de dynamische assemblage en een beetje op aanverwante CI/CD-processen.
Inleiding: hoe de website is opgebouwd
Laten we beginnen met het feit dat de documentatie over werf samen met de code wordt opgeslagen. Dit stelt bepaalde eisen aan de ontwikkeling die in het algemeen buiten het bestek van dit artikel vallen, maar we kunnen in ieder geval zeggen dat:
- Nieuwe functies van werf mogen niet worden vrijgegeven zonder een update van de documentatie en omgekeerd impliceren wijzigingen in de documentatie het uitkomen van een nieuwe versie van werf;
- Het project kent een vrij intensieve ontwikkeling: nieuwe versies kunnen meerdere keren per dag worden uitgebracht;
- Handmatige operaties voor het deployen van de website met een nieuwe versie van de documentatie zijn in ieder geval vermoeiend;
- In het project is een semantische benadering aangenomen , met 5 stabiliteitskanalen. Het releaseproces houdt een opeenvolgende doorgang van versies door de kanalen in, in volgorde van toenemende stabiliteit: van alpha tot rock-solid;
- De website heeft een Nederlandstalige versie die "leeft en zich ontwikkelt" (d.w.z. waarvan de inhoud wordt bijgewerkt) parallel aan de hoofdzakelijke (d.w.z. Engelstalige) versie.
Om de gebruiker al deze "interne keuken" te verbergen en hem datgene te bieden dat "gewoon werkt", hebben we gemaakt een apart installatie- en update-instrument voor werf is . Het is voldoende om het versienummer en het stabiliteitskanaal op te geven dat je bereid bent te gebruiken, en multiwerf controleert of er een nieuwe versie op het kanaal beschikbaar is en downloadt deze indien nodig.
In het keuzemenu voor versies op de website zijn de laatste versies van werf in elk kanaal beschikbaar. Standaard, op het adres er opent een versie van het meest stabiele kanaal voor de laatste release — deze wordt ook geïndexeerd door zoekmachines. Documentatie voor het kanaal is beschikbaar op aparte adressen (bijvoorbeeld, voor de beta-release 1.0).
Kortom, de website heeft de volgende versies beschikbaar:
- de hoofdversie (opent standaard),
- voor elk actief updatekanaal van elke release (bijvoorbeeld, ).
Om een specifieke versie van de website te genereren, is het in het algemeen voldoende om de compilatie uit te voeren met behulp van , door de juiste opdracht in de map /docs van de werf-repository uit te voeren (jekyll build), voorafgaand aan het schakelen naar de Git-tag van de benodigde versie.
Het enige dat nog toegevoegd moet worden, is dat:
- de utility zelf wordt gebruikt voor de build (werf);
- CI/CD-processen zijn gebouwd op basis van GitLab CI;
- en dit alles werkt natuurlijk binnen Kubernetes.
Taken
Laten we nu de taken formuleren, rekening houdend met alle beschreven specifics:
- Na het wijzigen van de versie van werf op een van de updatekanalen moet de documentatie op de website automatisch worden bijgewerkt..
- Voor de ontwikkeling moet het soms mogelijk zijn om voorlopige versies van de website te bekijken..
De website moet opnieuw worden gecompileerd na het wijzigen van de versie op een van de kanalen van de respectieve Git-tags, maar in het proces van het bouwen van de afbeelding krijgen we de volgende kenmerken:
- Aangezien de lijst met versies op de kanalen verandert, moeten we alleen de documentatie opnieuw opbouwen voor de kanalen waar de versie is gewijzigd. Het is immers niet netjes om alles opnieuw op te bouwen.
- De set kanalen voor releases kan veranderen. Op een bepaald moment kan er bijvoorbeeld geen versie zijn op de kanalen die stabieler zijn dan de early-access release 1.1, maar na verloop van tijd zullen ze verschijnen — we kunnen de build in dat geval toch niet handmatig wijzigen?
Het blijkt dat de build hangt af van veranderende externe gegevens..
Implementatie
Kies aanpak.
Als optie kunnen we elke benodigde versie als een aparte pod in Kubernetes draaien. Deze optie impliceert een groter aantal objecten in de cluster, dat zal toenemen met het aantal stabiele versies van werf. Dit met zich mee brengt ook complexere onderhoud: voor elke versie komt er een eigen HTTP-server bij, met een kleine belasting. Natuurlijk betekent dit ook hogere resource-kosten.
Wij hebben gekozen voor het bouwen van alle benodigde versies in één afbeelding.. De gecompileerde statica van alle versies van de website bevindt zich in een container met NGINX, en het verkeer naar de bijbehorende Deployment komt via NGINX Ingress. De eenvoudige structuur — een stateless applicatie — maakt het gemakkelijk om de Deployment te schalen (afhankelijk van de belasting) met de middelen van Kubernetes zelf.
Om preciezer te zijn, bouwen we twee afbeeldingen: één voor de productie-omgeving, de tweede is aanvullend, voor de dev-omgeving. De aanvullende afbeelding wordt (uitgevoerd) alleen op de dev-omgeving samen met de belangrijkste en bevat de versie van de website van de review-commit, terwijl de routering tussen hen wordt uitgevoerd met behulp van Ingress-resources.
werf vs git clone en artefacten
Zoals eerder vermeld, om de statica van de website voor een specifieke versie van de documentatie te genereren, moet je een build uitvoeren door over te schakelen naar de overeenkomstige tag van de repository. Het zou ook mogelijk zijn om dit te doen door de repository elke keer te klonen tijdens de build, waarbij je de overeenkomstige tags uit de lijst kiest. Dit is echter een vrij resource-intensieve handeling en vereist bovendien het schrijven van niet-triviale instructies... Een ander groot minpunt is dat er bij deze aanpak geen mogelijkheid is om iets te cachen tijdens de build.
Hier komt de werf-tool ons helpen, die slim cachen en het mogelijk maakt om te gebruiken. Het gebruik van werf om code uit de repository toe te voegen, versnelt de build aanzienlijk, omdat werf in wezen de repository één keer kloont en vervolgens van fetch indien nodig uitvoert. Bovendien, bij het toevoegen van gegevens uit de repository kunnen we alleen de benodigde mappen selecteren (in ons geval is dat de map docs), wat de omvang van de toegevoegde gegevens aanzienlijk vermindert.
Aangezien Jekyll een tool is die is bedoeld voor het compileren van statica en niet nodig is in de uiteindelijke afbeelding, zou het logisch zijn om de compilatie uit te voeren in , en in de uiteindelijke afbeelding slechts het resultaat van de compilatie te importeren..
We schrijven werf.yaml
Dus hebben we besloten dat we elke versie zullen compileren in een apart werf-artefact. Echter, we weten niet hoeveel van deze artefacten er zullen zijn tijdens de build, dus kunnen we geen vaste build-configuratie schrijven (strikt genomen kunnen we dat wel, maar het zou niet zo efficiënt zijn).
werf maakt het mogelijk om te gebruiken in zijn configuratiebestand (werf.yaml), wat de mogelijkheid biedt om de config 'on-the-fly' te genereren afhankelijk van externe gegevens (wat nodig is!). Externe gegevens zijn in ons geval de informatie over versies en releases, waarop we het benodigde aantal artefacten baseren en uiteindelijk twee afbeeldingen verkrijgen: werf-doc en werf-dev om te draaien op verschillende omgevingen.
Externe gegevens worden doorgegeven via omgevingsvariabelen. Dit is hun samenstelling:
-
RELEASES— een string met een lijst van releases en de bijbehorende actuele versie van werf, in de vorm van een spatiegescheiden lijst van waarden in het formaat%. Voorbeeld:1.0%v1.0.4-beta.20 -
CHANNELS— een string met een lijst van kanalen en de bijbehorende actuele versie van werf, in de vorm van een spatiegescheiden lijst van waarden in het formaat%. Voorbeeld:1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22 -
ROOT_VERSION— de versie van de werf-release die standaard op de website weergegeven moet worden (het is niet altijd nodig om documentatie voor het hoogste release-nummer weer te geven). Voorbeeld:v1.0.4-beta.20 -
REVIEW_SHA— de hash van de review-commit, waarvan de versie voor de testomgeving moet worden opgebouwd.
Deze variabelen worden ingevuld in de GitLab CI-pipeline, en hoe precies, wordt hieronder beschreven.
Als eerste, voor het gemak, definiëren we in werf.yaml Go-template-variabelen, waarbij we ze waarden toewijzen uit omgevingsvariabelen:
{{ $_ := set . "WerfVersions" (cat (env "CHANNELS") (env "RELEASES") | splitList " ") }}
{{ $Root := . }}
{{ $_ := set . "WerfRootVersion" (env "ROOT_VERSION") }}
{{ $_ := set . "WerfReviewCommit" (env "REVIEW_SHA") }} De beschrijving van het artefact voor het compileren van de statische versie van de website is in grote lijnen hetzelfde voor alle noodzakelijke gevallen (inclusief de generatie van de rootversie, en versie voor de dev-omgeving). Daarom brengen we het in een aparte block met behulp van de functie define — voor toekomstige hergebruik met behulp van include. We zullen de volgende argumenten aan de template doorgeven:
-
Versie— de te genereren versie (de tagnaam); -
Channel— de naam van het updatekanaal waarvoor het artefact wordt gegenereerd; -
Commit— de hash van de commit, als het artefact wordt gegenereerd voor een review-commit; - de context.
De beschrijving van de artefact-template
{{- 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/nl_site/
- file:
dest: /app/docs/pages_nl/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/_nl_site/{{ if .BaseURL }} --baseurl /{{ .BaseURL }}{{ end }} --config /app/docs/_config.yml,/app/docs/_config_nl.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 }} De naam van het artifact moet uniek zijn. Dit kunnen we bereiken door bijvoorbeeld de naam van het kanaal (de waarde van de variabele .Channel) als suffix aan de naam van het artifact toe te voegen: artifact: doc-{{ .Channel }}. Maar het is belangrijk om te begrijpen dat we bij het importeren van artifacts naar dezelfde namen moeten verwijzen.
Bij de beschrijving van het artifact wordt de mogelijkheid van werf gebruikt, genaamd . Mounting met de opgegeven service directory build_dir maakt het mogelijk om de Jekyll-cache tussen pipeline-runs te behouden, wat de herbouw aanzienlijk versnelt..
Je hebt ook mogelijk het gebruik van het bestand releases.yml opgemerkt — dit is een YAML-bestand met gegevens over releases, dat wordt opgevraagd vanaf (artifact verkregen tijdens het uitvoeren van de pipeline). Het is nodig bij het compileren van de site, maar in de context van dit artikel is het interessant omdat de status ervan afhankelijk is van de herbouw van slechts één artifact — het artifact van de hoofddomeinversie (het is niet nodig in andere artifacts).
Dit is geïmplementeerd met behulp van de conditionele operator als Go-templates en de constructie {{ $Root.Files.Get "releases.yml" | sha256sum }} in de fase . Het werkt als volgt: bij het samenstellen van het artifact voor de rootversie (variabele .Channel gelijk aan root) beïnvloedt de hash van het bestand releases.yml de handtekening van de hele fase, omdat het een onderdeel is van de naam van de Ansible-taak (parameter naam). Dus bij wijziging van de inhoud bestand releases.yml zal het bijbehorende artifact opnieuw worden opgebouwd.
Let ook op het werken met een externe repository. In het artifact van de afbeelding uit , wordt alleen de map toegevoegd /docs, waarbij afhankelijk van de doorgegeven parameters gegevens van de noodzakelijke tag of review-commit direct worden toegevoegd.
Om de sjabloon van het artifact te gebruiken voor het genereren van de beschrijving van de artifacts van de doorgegeven versies van kanalen en releases, organiseren we een lus over de variabele .WerfVersions in werf.yaml:
{{ range .WerfVersions -}}
{{ $VersionsDict := splitn "%" 2 . -}}
{{ dict "Version" $VersionsDict._1 "Channel" $VersionsDict._0 "Root" $Root | include "doc_artifact" }}
---
{{ end -}} Aangezien de lus meerdere artifacts zal genereren (dat hopen we), moet rekening worden gehouden met de scheidingsteken tussen hen — een reeks --- (zie voor meer informatie over de syntaxis van het configuratiebestand ). Zoals eerder vastgesteld, geven we bij het aanroepen van het sjabloon in de lus parameters voor versie, URL en rootcontext door.
Op een vergelijkbare manier, maar zonder lus, roepen we het sjabloon van het artifact aan voor 'bijzondere gevallen': voor de rootversie, evenals de versie uit de 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 }} Let op dat het artifact voor de review-commit alleen zal worden opgebouwd als de variabele .WerfReviewCommit.
Artifacts zijn klaar — het is tijd om met de import aan de slag te gaan!
Het eindbeeld, bedoeld voor uitvoering in Kubernetes, is een gewone NGINX, waarvoor een serverconfiguratiebestand is toegevoegd nginx.conf en statische bestanden uit artifacts. Naast het artifact van de rootversie van de site moeten we de lus herhalen over de variabele .WerfVersions voor het importeren van de artifacts van de versies van kanalen en releases + het respecteren van de eerder vastgestelde naamgevingsregels voor artifacts. Aangezien elk artifact de versies van de site voor twee talen opslaat, importeren we ze naar de plaatsen die zijn voorzien in de configuratie.
Beschrijving van het eindbeeld 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/nl_site/assets
import:
- artifact: doc-root
add: /app/_main_site
to: /app/main_site
before: setup
- artifact: doc-root
add: /app/_nl_site
to: /app/nl_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/_nl_site
to: /app/nl_site/v{{ $Channel }}
before: setup
{{ end -}}Het extra beeld dat samen met de hoofdversie op de dev-contour draait, bevat slechts twee versies van de site: de versie van de review-commit en de basisversie van de site (daar zijn gemeenschappelijke assets en, als je je herinnert, gegevens over de releases). Dus het extra beeld zal alleen verschillen van de hoofdversie in de importsectie (en natuurlijk de naam):
image: werf-dev
...
import:
- artifact: doc-root
add: /app/_main_site
to: /app/main_site
before: setup
- artifact: doc-root
add: /app/_nl_site
to: /app/nl_site
before: setup
{{- if .WerfReviewCommit }}
- artifact: doc-review
add: /app/_main_site
to: /app/main_site/review
before: setup
- artifact: doc-review
add: /app/_nl_site
to: /app/nl_site/review
before: setup
{{- end }} Zoals eerder opgemerkt, zal het artifact voor de review-commit alleen worden gegenereerd wanneer de omgevingsvariabele is ingesteld. REVIEW_SHA. Het zou zelfs mogelijk zijn om helemaal geen werf-dev beeld te genereren als er geen omgevingsvariabele is. REVIEW_SHA, maar om ervoor te zorgen dat Docker-images in werf functioneert voor het werf-dev beeld, laten we het alleen bouwen met het artifact van de basisversie (het is immers al gebouwd), ter vereenvoudiging van de pipeline-structuur.
De build is klaar! Laten we doorgaan naar CI/CD en belangrijke nuances.
Pipeline in GitLab CI en kenmerken van dynamische builds
Bij het starten van de build moeten we omgevingsvariabelen instellen die worden gebruikt in werf.yaml. Dit is niet van toepassing op de variabele REVIEW_SHA, die we zullen instellen bij het aanroepen van de pipeline vanuit de GitHub-hook.
De benodigde externe gegevens verplaatsen we naar een Bash-script generate_artifacts, dat twee artifacts van de GitLab-pipeline zal genereren:
- bestand
releases.ymlmet gegevens over de releases, - bestand
common_envs.sh, dat omgevingsvariabelen voor export bevat.
De inhoud van het bestand generate_artifacts je vindt in onze . Het verkrijgen van de gegevens is niet het onderwerp van het artikel, maar het bestand common_envs.sh is belangrijk voor ons, omdat de werking van werf ervan afhangt. Een voorbeeld van de inhoud:
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' Het uitvoer van zo'n script kan bijvoorbeeld met behulp van een Bash-functie worden gebruikt. source.
Maar nu het interessante deel. Om zowel de bouw als de implementatie van de applicatie correct te laten werken, moet ervoor worden gezorgd dat werf.yaml was dezelfde minimaal binnen één pipeline. Als aan deze voorwaarde niet wordt voldaan, zullen de signaturen van de fasen die werf berekent tijdens de bouw en bijvoorbeeld de implementatie, verschillend zijn. Dit zal leiden tot een implementatiefout, omdat het vereiste beeld voor de implementatie zal ontbreken.
Met andere woorden, als tijdens de bouw van het websitebeeld de informatie over releases en versies hetzelfde is, maar op het moment van implementatie een nieuwe versie uitkomt en de omgevingsvariabelen andere waarden hebben, zal de implementatie eindigen met een fout: het artefact van de nieuwe versie is immers nog niet gebouwd.
Als de generatie werf.yaml afhangt van externe gegevens (zoals een lijst van actuele versies, zoals in ons geval), dan moeten de samenstelling en waarden van dergelijke gegevens binnen de pipeline worden vastgelegd. Dit is vooral belangrijk als externe parameters vrij vaak veranderen.
We zullen externe gegevens ophalen en vastleggen in de eerste fase van de pipeline in GitLab (Prebuild) en ze vervolgens doorgeven als GitLab CI-artifact. Dit maakt het mogelijk om de taken van de pipeline (bouw, implementatie, opruiming) met dezelfde configuratie uit te voeren en opnieuw te starten in werf.yaml.
De inhoud van de fase Prebuild bestand .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 weekDoor externe gegevens in het artefact vast te leggen, is het mogelijk om de bouw en implementatie uit te voeren met behulp van de standaard fasen van de GitLab CI-pipeline: Build en Deploy. We starten de pipeline via hooks vanuit de GitHub-repository werf (d.w.z. bij wijzigingen in de repository op GitHub). Gegevens hiervoor kunnen worden gehaald uit de projectinstellingen in GitLab in de sectie CI / CD-instellingen -> Pipeline-triggers, en vervolgens maken we de bijbehorende Webhook in GitHub (Instellingen -> Webhooks).
De bouwfase zal er als volgt uitzien:
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 zal twee artefacten uit de fase aan de bouwfase toevoegen Prebuild, dus we exporteren variabelen met de voorbereide invoergegevens met behulp van de constructie source common_envs.sh. We starten de buildfase in alle gevallen, behalve bij het plannen van de pipeline. Voor het plannen hebben we een pipeline die voor schoonmaak zorgt - hierin hoeft geen build te worden uitgevoerd.
In de deployfase zullen we twee taken beschrijven - apart voor de deploy naar de production- en dev-omgevingen, met gebruik van een YAML-sjabloon:
.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 naar Productie:
<<: *base_deploy
variables:
WERF_KUBE_CONTEXT: prod
environment:
name: production
url: werf.io
only:
refs:
- master
except:
variables:
- $REVIEW_SHA
refs:
- schedules
Deploy naar Test:
<<: *base_deploy
variables:
WERF_KUBE_CONTEXT: dev
environment:
name: test
url: werf.test.flant.com
except:
refs:
- schedules
only:
variables:
- $REVIEW_SHA De taken verschillen in wezen alleen in de specificatie van de clustercontext waarin werf de deploy moet uitvoeren (WERF_KUBE_CONTEXT), en in het instellen van omgevingsvariabelen voor de omgeving (environment.name en environment.url), die vervolgens worden gebruikt in de Helm-chart sjablonen. We zullen de inhoud van de sjablonen hier niet geven, omdat er niets interessants voor het besproken onderwerp in staat, maar je kunt ze vinden in de .
Laatste details
Aangezien versies van werf regelmatig uitkomen, zullen er vaak nieuwe beelden worden gemaakt en zal de Docker Registry continu groeien. Daarom is het absoluut noodzakelijk om automatische schoonmaak van beelden op basis van beleid in te stellen. Dit is heel eenvoudig te doen.
Voor de implementatie is nodig:
- Een schoonmaakfase toevoegen aan
.gitlab-ci.yml; - Een periodieke taak voor schoonmaak instellen;
- Een omgevingsvariabele met een toegangstoken voor schrijven instellen.
We voegen een schoonmaakfase toe aan .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
Bijna alles hebben we al eerder gezien - alleen voor de schoonmaak moet je je vooraf authentiseren bij de Docker Registry met een token dat de rechten heeft om beelden in de Docker Registry te verwijderen (de automatisch uitgegeven token van GitLab CI heeft deze rechten niet). Het token moet van tevoren in GitLab worden aangemaakt en zijn waarde moet worden opgegeven in de omgevingsvariabele WERF_IMAGES_CLEANUP_PASSWORD van het project (CI/CD-instellingen -> Variabelen).
Het toevoegen van een schoonmaaktaak met de benodigde planning wordt gedaan in CI/CD ->
Schemas.
Alles: het project in Docker Registry zal niet langer blijven groeien door ongebruikte afbeeldingen.
Als afsluiting van het praktische deel herinner ik eraan dat de volledige lijsten uit het artikel beschikbaar zijn in :
- ;
- .
Resultaat
- We hebben een logische buildstructuur gekregen: één artifact per versie.
- De build is universeel en vereist geen handmatige wijzigingen bij het uitkomen van nieuwe versies van werf: de documentatie op de website wordt automatisch bijgewerkt.
- Er worden twee afbeeldingen opgebouwd voor verschillende omgevingen.
- Het werkt snel omdat maximaal gebruik wordt gemaakt van caching — bij het uitkomen van een nieuwe versie van werf of het aanroepen van de GitHub-hook voor een review-commit, wordt alleen het overeenkomstige artifact met de gewijzigde versie opnieuw opgebouwd.
- Je hoeft niet na te denken over het verwijderen van ongebruikte afbeeldingen: het opruimen volgens de werf-beleidsregels houdt de ordening in de Docker Registry.
Conclusies
- Het gebruik van werf stelt de build in staat om snel te werken dankzij caching, zowel van de build zelf als bij het werken met externe repositories.
- Werken met externe Git-repositories voorkomt de noodzaak om de repository telkens volledig te klonen of een ingewikkelde optimalisatie-logica te bedenken. werf gebruikt caching en kloont alleen één keer, en gebruikt daarna
fetchen alleen indien nodig. - De mogelijkheid om Go-sjablonen in het buildconfiguratiebestand te gebruiken
werf.yamlmaakt het mogelijk om een build te beschrijven waarvan het resultaat afhankelijk is van externe gegevens. - Het gebruik van mounting in werf versnelt de opbouw van artifacts aanzienlijk — door het gebruik van cache die gemeenschappelijk is voor alle pipelines.
- werf maakt het eenvoudig om opschoning in te stellen, wat vooral relevant is bij dynamische builds.
P.S.
Lees ook op onze blog:
- «»;
- «»;
- «»;
- «».
Bron: habr.com
