Dynamisk sammansÀttning och distribution av Docker-avbildningar med werf med exemplet pÄ en versionerad dokumentationswebbplats

Vi har redan pratat om vĂ„rt GitOps-verktyg mer Ă€n en gĂ„ng. werf, och den hĂ€r gĂ„ngen vill vi dela med oss ​​av vĂ„r erfarenhet av att montera platsen med dokumentationen av sjĂ€lva projektet - werf.io (dess ryska version Ă€r en.werf.io). Detta Ă€r en vanlig statisk plats, men dess sammansĂ€ttning Ă€r intressant eftersom den Ă€r byggd med ett dynamiskt antal artefakter.

Dynamisk sammansÀttning och distribution av Docker-avbildningar med werf med exemplet pÄ en versionerad dokumentationswebbplats

GÄ in pÄ nyanserna i webbplatsstrukturen: generera en gemensam meny för alla versioner, sidor med information om utgÄvor, etc. - vi kommer inte. LÄt oss istÀllet fokusera pÄ problemen och funktionerna i dynamisk montering och lite pÄ de medföljande CI/CD-processerna.

Introduktion: hur sajten fungerar

Till att börja med lagras werf-dokumentation tillsammans med dess kod. Detta stÀller vissa utvecklingskrav som i allmÀnhet ligger utanför ramen för denna artikel, men Ätminstone kan man sÀga att:

  • Nya werf-funktioner bör inte slĂ€ppas utan uppdatering av dokumentationen och omvĂ€nt innebĂ€r alla Ă€ndringar i dokumentationen att en ny version av werf slĂ€pps;
  • Projektet har en ganska intensiv utveckling: nya versioner kan slĂ€ppas flera gĂ„nger om dagen;
  • Alla manuella Ă„tgĂ€rder för att distribuera en webbplats med en ny version av dokumentationen Ă€r Ă„tminstone trĂ„kiga;
  • Projektet har ett semantiskt synsĂ€tt versionshantering, med 5 stabilitetskanaler. Releaseprocessen involverar sekventiell passage av versioner genom kanaler för att öka stabiliteten: frĂ„n alfa till stenfast;
  • Webbplatsen har en rysksprĂ„kig version, som "lever och utvecklas" (dvs vars innehĂ„ll uppdateras) parallellt med huvudversionen (dvs engelsksprĂ„kig).

För att dölja allt detta "inre kök" för anvĂ€ndaren, erbjuda honom nĂ„got som "bara fungerar", gjorde vi separat werf installations- och uppdateringsverktyg - Är multiwerf. Du behöver bara ange releasenummer och stabilitetskanalen som du Ă€r redo att anvĂ€nda, sĂ„ kommer multiwerf att kontrollera om det finns en ny version pĂ„ kanalen och ladda ner den om det behövs.

I versionsvalmenyn pÄ webbplatsen finns de senaste versionerna av werf tillgÀngliga i varje kanal. Som standard, efter adress werf.io/documentation versionen av den mest stabila kanalen för den senaste utgÄvan öppnas - den indexeras ocksÄ av sökmotorer. Dokumentation för kanalen finns pÄ separata adresser (t.ex. werf.io/v1.0-beta/documentation för betaversion 1.0).

Sammanlagt har webbplatsen följande versioner tillgÀngliga:

  1. root (öppnas som standard),
  2. för varje aktiv uppdateringskanal för varje utgÄva (till exempel, werf.io/v1.0-beta).

För att generera en specifik version av en webbplats rÀcker det i allmÀnhet att kompilera den med hjÀlp av Jekyllgenom att köra i katalogen /docs werf repository motsvarande kommando (jekyll build), efter att ha bytt till Git-taggen för den nödvÀndiga versionen.

Det ÄterstÄr bara att tillÀgga:

  • sjĂ€lva verktyget (werf) anvĂ€nds för montering;
  • CI/CD-processer Ă€r byggda pĂ„ basis av GitLab CI;
  • och allt detta körs naturligtvis i Kubernetes.

uppgifter

LÄt oss nu formulera uppgifter som tar hÀnsyn till alla beskrivna detaljer:

  1. Efter att ha Àndrat werf-versionen pÄ valfri uppdateringskanal dokumentationen pÄ webbplatsen bör uppdateras automatiskt.
  2. För utveckling behöver man kunna ibland visa förhandsversioner av webbplatsen.

Webbplatsen mÄste kompileras om efter att ha Àndrat versionen pÄ valfri kanal frÄn motsvarande Git-taggar, men i processen att bygga bilden kommer vi att fÄ följande funktioner:

  • Eftersom listan över versioner pĂ„ kanaler Ă€ndras Ă€r det bara nödvĂ€ndigt att bygga om dokumentationen för kanaler dĂ€r versionen har Ă€ndrats. Att bygga om allt igen Ă€r trots allt inte sĂ€rskilt trevligt.
  • UppsĂ€ttningen av kanaler för releaser kan Ă€ndras. Vid nĂ„gon tidpunkt, till exempel, kanske det inte finns en version pĂ„ kanalerna som Ă€r mer stabil Ă€n 1.1-versionen med tidig Ă„tkomst, men med tiden kommer de att dyka upp - i det hĂ€r fallet, borde du inte Ă€ndra monteringen manuellt?

Det visar sig att montering beror pÄ att extern data Àndras.

genomförande

Att vÀlja ett tillvÀgagÄngssÀtt

Alternativt kan du köra varje version som krÀvs som en separat pod i Kubernetes. Det hÀr alternativet innebÀr ett större antal objekt i klustret, vilket kommer att vÀxa med ökningen av antalet stabila werfslÀpp. Och detta innebÀr i sin tur mer komplext underhÄll: varje version har sin egen HTTP-server och med en liten belastning. Detta medför naturligtvis ocksÄ större resurskostnader.

Vi tog samma vÀg samla alla nödvÀndiga versioner i en bild. Den kompilerade statistiken för alla versioner av webbplatsen finns i en container med NGINX, och trafik till motsvarande Deployment kommer via NGINX Ingress. En enkel struktur - en tillstÄndslös applikation - gör att du enkelt kan skala Deployment (beroende pÄ belastningen) med Kubernetes sjÀlv.

För att vara mer exakt samlar vi in ​​tvĂ„ bilder: en för produktionskretsen, den andra Ă€r en extra för utvecklingskretsen. TillĂ€ggsbilden anvĂ€nds (lanseras) endast pĂ„ dev-kretsen tillsammans med den huvudsakliga och innehĂ„ller versionen av webbplatsen frĂ„n gransknings-commit, och routing mellan dem utförs med hjĂ€lp av Ingress-resurser.

werf vs git klon och artefakter

Som redan nÀmnts, för att generera webbplatsstatik för en specifik version av dokumentationen, mÄste du bygga genom att byta till lÀmplig repository-tagg. Du kan ocksÄ göra detta genom att klona förvaret varje gÄng du bygger, vÀlja lÀmpliga taggar frÄn en lista. Detta Àr dock en ganska resurskrÀvande operation och krÀver dessutom att man skriver icke-triviala instruktioner... En annan allvarlig nackdel Àr att med detta tillvÀgagÄngssÀtt finns det inget sÀtt att cache nÄgot under montering.

HÀr kommer sjÀlva werfverktyget till vÄr hjÀlp och implementerar smart cachelagring och lÄter dig anvÀnda externa förrÄd. Att anvÀnda werf för att lÀgga till kod frÄn förvaret kommer att pÄskynda bygget avsevÀrt, eftersom werf klonar i princip förvaret en gÄng och körs sedan endast fetch om nödvÀndigt. Dessutom, nÀr vi lÀgger till data frÄn förvaret, kan vi bara vÀlja de nödvÀndiga katalogerna (i vÄrt fall Àr detta katalogen docs), vilket avsevÀrt kommer att minska mÀngden tillagd data.

Eftersom Jekyll Àr ett verktyg designat för att kompilera statisk data och inte behövs i den slutliga bilden, skulle det vara logiskt att kompilera i werf artefakt, och in i den slutliga bilden importera endast kompileringsresultatet.

Vi skriver werf.yaml

SÄ vi bestÀmde att vi skulle kompilera varje version i en separat werfartefakt. Men vi vi vet inte hur mÄnga av dessa artefakter det kommer att finnas under monteringen, sÄ vi kan inte skriva en fast byggkonfiguration (strÀngt taget kan vi fortfarande, men det kommer inte att vara helt effektivt).

werf lÄter dig anvÀnda GÄ mallar i din konfigurationsfil (werf.yaml), och detta gör det möjligt generera konfiguration i farten beroende pÄ extern data (vad du behöver!). Extern data i vÄrt fall Àr information om versioner och utgÄvor, pÄ grundval av vilken vi samlar in det erforderliga antalet artefakter och som ett resultat fÄr vi tvÄ bilder: werf-doc О werf-dev att köra pÄ olika kretsar.

Extern data skickas genom miljövariabler. HÀr Àr deras sammansÀttning:

  • RELEASES — en rad med en lista över utgĂ„vor och motsvarande aktuella version av werf, i form av en mellanslagsseparerad vĂ€rdelista i formatet <НОМЕР_РЕЛИЗА>%<НОМЕР_ВЕРСИИ>. Exempel: 1.0%v1.0.4-beta.20
  • CHANNELS — en rad med en lista över kanaler och motsvarande aktuella version av werf, i form av en mellanslagsseparerad vĂ€rdelista i formatet <КАНАЛ>%<НОМЕР_ВЕРСИИ>. Exempel: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERSION — werf version som ska visas som standard pĂ„ webbplatsen (det Ă€r inte alltid nödvĂ€ndigt att visa dokumentation med det högsta releasenumret). Exempel: v1.0.4-beta.20
  • REVIEW_SHA — hash för granskningsĂ„tagandet frĂ„n vilket du behöver bygga versionen för testslingan.

Dessa variabler kommer att fyllas i i GitLab CI-pipeline, och hur exakt skrivs nedan.

Först av allt, för bekvÀmlighets skull, definierar vi in werf.yaml GÄ till mallvariabler, tilldela dem vÀrden frÄn miljövariabler:

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

Beskrivningen av artefakten för att kompilera den statiska versionen av webbplatsen Àr i allmÀnhet densamma för alla fall vi behöver (inklusive generering av rotversionen, sÄvÀl som versionen för dev-kretsen). DÀrför kommer vi att flytta det till ett separat block med hjÀlp av funktionen define - för efterföljande ÄteranvÀndning include. Vi skickar följande argument till mallen:

  • Version — genererad version (taggnamn);
  • Channel — Namnet pĂ„ uppdateringskanalen för vilken artefakten genereras.
  • Commit — commit hash, om artefakten genereras för en gransknings commit;
  • sammanhang.

Beskrivning av artefaktmall

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

Artefaktens namn mÄste vara unikt. Vi kan till exempel uppnÄ detta genom att lÀgga till kanalnamnet (variabelns vÀrde .Channel) som ett suffix till namnet pÄ artefakten: artifact: doc-{{ .Channel }}. Men du mÄste förstÄ att nÀr du importerar frÄn artefakter mÄste du referera till samma namn.

NÀr man beskriver en artefakt anvÀnds följande werf-funktion: montering. Montering som indikerar servicekatalogen build_dir lÄter dig spara Jekyll-cachen mellan pipelinekörningar, vilket pÄskyndar Ätermonteringen avsevÀrt.

Du kanske ocksĂ„ har mĂ€rkt anvĂ€ndningen av filen releases.yml Ă€r en YAML-fil med utgivningsdata som begĂ€rts frĂ„n github.com (en artefakt som erhĂ„lls vid exekvering av en pipeline). Det behövs nĂ€r man sammanstĂ€ller webbplatsen, men i samband med artikeln Ă€r det intressant för oss eftersom det beror pĂ„ dess tillstĂ„nd Ă„termontering av endast en artefakt — en artefakt av webbplatsens rotversion (den behövs inte i andra artefakter).

Detta implementeras med hjÀlp av det villkorade uttalandet if GÄ till mallar och mönster {{ $Root.Files.Get "releases.yml" | sha256sum }} i scenen etapper. Det fungerar enligt följande: nÀr man bygger en artefakt för rotversionen (variabel .Channel Àr lika med root) filhash releases.yml pÄverkar signaturen för hela scenen, eftersom den Àr en del av namnet pÄ Ansible-uppgiften (parameter name). AlltsÄ nÀr man byter innehÄll fil releases.yml motsvarande artefakt kommer att Ätermonteras.

Var ocksÄ uppmÀrksam pÄ att arbeta med ett externt arkiv. I bilden av en artefakt frÄn werf förvaret, endast katalogen lÀggs till /docs, och beroende pÄ de angivna parametrarna, lÀggs data för den nödvÀndiga taggen eller granskningsbekrÀftelsen till omedelbart.

För att anvĂ€nda artefaktmallen för att generera en beskrivning av artefakten för de överförda versionerna av kanaler och releaser, organiserar vi en loop pĂ„ variabeln .WerfVersions ĐČ werf.yaml:

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

DÀrför att slingan kommer att generera flera artefakter (vi hoppas det), det Àr nödvÀndigt att ta hÀnsyn till separatorn mellan dem - sekvensen --- (För mer information om konfigurationsfilsyntax, se dokumentation). Som definierats tidigare, nÀr vi anropar en mall i en loop, skickar vi versionsparametrarna, URL och rotkontext.

PÄ liknande sÀtt, men utan en loop, kallar vi artefaktmallen för "speciella fall": för rotversionen, sÄvÀl som versionen frÄn granskningen 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 }}

Observera att artefakten för granskningsÄtagandet endast kommer att byggas om variabeln Àr instÀlld .WerfReviewCommit.

Artefakterna Àr klara - det Àr dags att börja importera!

Den slutliga bilden, designad för att köras pÄ Kubernetes, Àr en vanlig NGINX med en serverkonfigurationsfil tillagd nginx.conf och statisk frÄn artefakter. Förutom artefakten av rotversionen av webbplatsen mÄste vi upprepa slingan pÄ variabeln .WerfVersions för att importera artefakter av kanal- och releaseversioner + följ artefaktnamnsregeln som vi antog tidigare. Eftersom varje artefakt lagrar versioner av webbplatsen för tvÄ sprÄk, importerar vi dem till de platser som tillhandahÄlls av konfigurationen.

Beskrivning av den slutliga bilden 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 -}}

TillÀggsbilden, som, tillsammans med den huvudsakliga, lanseras pÄ dev-kretsen, innehÄller bara tvÄ versioner av webbplatsen: versionen frÄn gransknings-commit och rotversionen av webbplatsen (det finns allmÀnna tillgÄngar och, om du kommer ihÄg , slÀpp data). SÄledes kommer den extra bilden att skilja sig frÄn den huvudsakliga endast i importsektionen (och, naturligtvis, i namnet):

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

Som nÀmnts ovan kommer artefakten för granskningsbekrÀftelsen att genereras endast nÀr den instÀllda miljövariabeln körs REVIEW_SHA. Det skulle vara möjligt att inte generera werf-dev-bilden alls om det inte finns nÄgon miljövariabel REVIEW_SHA, men för att stÀdning enligt policyer Docker-bilder i werf fungerade för werf-dev-bilden, vi kommer att lÄta den byggas endast med artefakten för rotversionen (den Àr redan byggd i alla fall), för att förenkla pipelinestrukturen.

Monteringen Àr klar! LÄt oss gÄ vidare till CI/CD och viktiga nyanser.

Pipeline i GitLab CI och funktioner för dynamiskt bygge

NÀr vi kör bygget mÄste vi stÀlla in de miljövariabler som anvÀnds i werf.yaml. Detta gÀller inte för variabeln REVIEW_SHA, som vi stÀller in nÀr vi anropar pipeline frÄn GitHub-kroken.

Vi kommer att generera nödvÀndig extern data i ett Bash-skript generate_artifacts, som kommer att generera tvÄ GitLab pipeline-artefakter:

  • фаĐčĐ» releases.yml med releasedata,
  • фаĐčĐ» common_envs.sh, som innehĂ„ller de miljövariabler som ska exporteras.

Filens innehÄll generate_artifacts hittar du i vÄr arkiv med exempel. Att ta emot sjÀlva data Àr inte föremÄlet för artikeln, utan filen common_envs.sh Àr viktigt för oss, eftersom werfs arbete beror pÄ det. Ett exempel pÄ dess innehÄll:

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'

Du kan anvÀnda utdata frÄn ett sÄdant skript, till exempel genom att anvÀnda Bash-funktionen source.

Nu kommer den roliga delen. För att bÄde konstruktionen och driftsÀttningen av applikationen ska fungera korrekt Àr det nödvÀndigt att sÀkerstÀlla det werf.yaml det var det samma Ätminstone inom en pipeline. Om detta villkor inte Àr uppfyllt, kommer signaturerna för de steg som werf berÀknar under montering och till exempel driftsÀttning att vara annorlunda. Detta kommer att leda till ett distributionsfel, eftersom... bilden som krÀvs för distribution kommer att saknas.

Med andra ord, om informationen om utgÄvor och versioner Àr densamma under monteringen av webbplatsbilden, och vid tidpunkten för implementeringen slÀpps en ny version och miljövariablerna har olika vÀrden, kommer distributionen att misslyckas med ett fel: trots allt har artefakten av den nya versionen Ànnu inte byggts.

Om generation werf.yaml beror pÄ externa data (till exempel en lista över aktuella versioner, som i vÄrt fall), dÄ bör sammansÀttningen och vÀrdena för sÄdana data registreras i pipelinen. Detta Àr sÀrskilt viktigt om externa parametrar Àndras ganska ofta.

Vi kommer ta emot och spela in extern data i det första steget av pipelinen i GitLab (Förbyggd) och överför dem vidare i formulÀret GitLab CI-artefakt. Detta gör att du kan köra och starta om pipeline-jobb (bygga, distribuera, stÀda) med samma konfiguration i werf.yaml.

Scenens innehÄll Förbyggd fil .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

Efter att ha fÄngat externa data i artefakten, kan du bygga och distribuera med hjÀlp av standard GitLab CI pipeline-steg: Bygg och distribuera. Vi lanserar sjÀlva pipelinen med hjÀlp av krokar frÄn werf GitHub-förvaret (dvs nÀr det finns Àndringar i GitHub-förvaret). Data för dem kan hittas i GitLab-projektets egenskaper i avsnittet CI/CD-instÀllningar -> Pipeline-utlösare, och skapa sedan motsvarande Webhook i GitHub (InstÀllningar -> Webhooks).

Byggstadiet kommer att se ut sÄ hÀr:

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 kommer att lÀgga till tvÄ artefakter frÄn scenen till byggstadiet Förbyggd, sÄ vi exporterar variabler med förberedda indata med hjÀlp av konstruktionen source common_envs.sh. Vi pÄbörjar byggskedet i alla fall, förutom att lansera pipelinen enligt ett schema. Enligt schemat kommer vi att köra en pipeline för rengöring - i det hÀr fallet behöver vi inte utföra montering.

I distributionsstadiet kommer vi att beskriva tvÄ uppgifter - separat för distribution till produktions- och dev-kretsar, med hjÀlp av en YAML-mall:

.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

Uppgifterna skiljer sig i huvudsak endast genom att ange i vilket klusterkontext werf ska utföra distributionen (WERF_KUBE_CONTEXT), och stÀller in loopmiljövariablerna (environment.name О environment.url), som sedan anvÀnds i Helm-diagrammallar. Vi kommer inte att tillhandahÄlla innehÄllet i mallarna, eftersom... det finns inget intressant dÀr för Àmnet i frÄga, men du kan hitta dem i arkiv för artikeln.

Slutlig touch

Eftersom werf-versioner slÀpps ganska ofta, kommer nya bilder att byggas ofta, och Docker Registry kommer stÀndigt att vÀxa. DÀrför Àr det absolut nödvÀndigt att konfigurera automatisk bildrensning baserat pÄ policyer. Det Àr vÀldigt lÀtt att göra.

För att implementera behöver du:

  • LĂ€gg till ett rengöringssteg till .gitlab-ci.yml;
  • LĂ€gg till periodisk utförande av en rengöringsuppgift;
  • StĂ€ll in en miljövariabel med en skrivĂ„tkomsttoken.

LÀgga till ett rengöringssteg till .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

Vi har redan sett nÀstan allt detta lite högre - bara för att rengöra det mÄste du först logga in pÄ Docker Registry med en token som har rÀttigheter att ta bort bilder i Docker Registry (den automatiskt utfÀrdade GitLab CI-uppgiftstoken gör det inte har sÄdana rÀttigheter). Token mÄste skapas i GitLab i förvÀg och dess vÀrde mÄste anges i miljövariabeln WERF_IMAGES_CLEANUP_PASSWORD projektet (CI/CD-instÀllningar -> Variabler).

LÀgga till en stÀduppgift med önskat schema görs i CI/CD ->
Scheman
.

Det Àr allt: ett projekt i Docker Registry kommer inte lÀngre att stÀndigt vÀxa frÄn oanvÀnda bilder.

I slutet av den praktiska delen, lÄt mig pÄminna dig om att fullstÀndiga listor frÄn artikeln finns tillgÀngliga i gÄ:

Resultat

  1. Vi fick en logisk monteringsstruktur: en artefakt per version.
  2. Monteringen Àr universell och krÀver inga manuella Àndringar nÀr nya versioner av werf slÀpps: dokumentationen pÄ webbplatsen uppdateras automatiskt.
  3. TvÄ bilder Àr sammansatta för olika konturer.
  4. Det fungerar snabbt, eftersom Caching anvÀnds sÄ mycket som möjligt - nÀr en ny version av werf slÀpps eller en GitHub-hook anropas för en granskning, byggs endast motsvarande artefakt med den Àndrade versionen om.
  5. Du behöver inte tÀnka pÄ att ta bort oanvÀnda bilder: rengöring enligt werf-policyer kommer att hÄlla ordning pÄ Docker-registret.

Resultat

  • Genom att anvĂ€nda werf kan sammansĂ€ttningen fungera snabbt pĂ„ grund av cachning av bĂ„de sjĂ€lva sammansĂ€ttningen och cachning nĂ€r man arbetar med externa repositories.
  • Att arbeta med externa Git-förrĂ„d eliminerar behovet av att klona hela förvaret varje gĂ„ng eller Ă„teruppfinna hjulet med knepig optimeringslogik. werf anvĂ€nder en cache och gör kloningen bara en gĂ„ng och anvĂ€nder sedan fetch och endast nĂ€r det behövs.
  • Möjlighet att anvĂ€nda Go-mallar i byggkonfigurationsfilen werf.yaml lĂ„ter dig beskriva en sammansĂ€ttning vars resultat beror pĂ„ externa data.
  • Att anvĂ€nda mount in werf snabbar upp insamlingen av artefakter avsevĂ€rt - pĂ„ grund av cachen, som Ă€r gemensam för alla pipelines.
  • werf gör det enkelt att konfigurera rengöring, vilket Ă€r sĂ€rskilt viktigt nĂ€r man bygger dynamiskt.

PS

LÀs Àven pÄ vÄr blogg:

KĂ€lla: will.com

Köp pĂ„litlig hosting för webbplatser med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster