Dynamická zostava a nasadenie Docker obrazov s werf na príklade webovej stránky s verzionovanou dokumentáciou

Už sme viackrát hovorili o našom nástroji GitOps werf, a tentoraz by sme sa radi podelili o skúsenosti so zostavovaním webu s dokumentáciou samotného projektu — werf.io (jeho slovenská verzia — sk.werf.io). Je to bežná statická stránka, avšak jej zostava je zaujímavá tým, že je postavená s využitím dynamického počtu artefaktov.

Dynamická zostava a nasadenie Docker obrazov s werf na príklade webovej stránky s verzionovanou dokumentáciou

Neponárame sa do nuáns štruktúry stránky: generovanie spoločného menu pre všetky verzie, stránky s informáciami o verziách atď. — nebudeme. Namiesto toho sa zameriame na otázky a špecifiká dynamickej zostavy a trochu na sprievodné procesy CI/CD.

Úvod: ako funguje stránka

Začíname tým, že dokumentácia k werfu sa uchováva spolu s jeho kódom. To kladie určité požiadavky na vývoj, ktoré v zásade presahujú rámec tohto článku, ale aspoň môžeme povedať, že:

  • Nové funkcie werfu by nemali byť uvedené bez aktualizácie dokumentácie a naopak, akékoľvek zmeny v dokumentácii predpokladajú vydanie novej verzie werfu;
  • Projekt má dosť intenzívny vývoj: nové verzie môžu vychádzať niekoľkokrát za deň;
  • Akékoľvek manuálne operácie pri nasadzovaní webu s novou verziou dokumentácie sú aspoň únavné;
  • V projekte je prijatý prístup semantického verziovania, s 5 kanálmi stability. Proces vydávania predpokladá postupné prechádzanie verzií cez kanály v poradí zvyšovania stability: od alpha po rock-solid;
  • Stránka má slovenskú verziu, ktorá „žije a vyvíja sa“ (t.j. obsah, ktorý sa aktualizuje) paralelne s hlavným (t.j. anglickým) variantom.

Aby sme skryli pred používateľom celú túto „vnútornú kuchyňu“, a ponúkli mu to, čo „jednoducho funguje“, vytvorili sme samostatný nástroj na inštaláciu a aktualizáciu werfu — sú multiwerf. Stačí zadať číslo vydania a kanál stability, ktorý ste pripravení použiť, a multiwerf skontroluje, či je na kanáli nová verzia, a v prípade potreby ju stiahne.

V menu výberu verzií na stránke sú dostupné posledné verzie werfu v každom kanáli. Predvolene, na adrese werf.io/documentation sa otvorí verzia najstabilnejšieho kanála pre posledné vydanie — tá sa indexuje vyhľadávačmi. Dokumentácia pre kanál je dostupná na samostatných adresách (napríklad, werf.io/v1.0-beta/documentation pre beta-vydanie 1.0).

Celkovo sú na stránke dostupné nasledujúce verzie:

  1. root (otvára sa predvolene),
  2. pre každý aktívny kanál aktualizácií každého vydania (napríklad, werf.io/v1.0-beta).

Na vygenerovanie konkrétnej verzie webu je vo všeobecnosti potrebné vykonať jej kompiláciu pomocou Jekyll,, spustením v adresári /docs repozítora werf príslušný príkaz (jekyll build), predtým sa prepnúť na Git-tag požadovanej verzie.

Stačí dodať, že:

  • na zostavenie sa používa samotný nástroj (werf);
  • CI/CD procesy sú postavené na báze GitLab CI;
  • a to všetko samozrejme funguje v Kubernetes.

Úlohy

Teraz formulujme úlohy, ktoré zohľadňujú celú opísanú špecifiku:

  1. Po zmene verzie werf na akomkoľvek kanáli aktualizácií, dokumentácia na stránke by sa mala automaticky aktualizovať..
  2. Pre vývoj je potrebné mať príležitosť niekedy prehliadať predbežné verzie webu..

Rekompiláciu webu je potrebné vykonávať po zmene verzie na akomkoľvek kanáli z príslušných Git-tagov, ale počas procesu zostavenia obrazu získame nasledujúce špecifiká:

  • Keďže zoznam verzií na kanáloch sa mení, je potrebné prekompilovať iba dokumentáciu pre kanály, kde sa zmenila verzia. Veď prekompilovať všetko znova nie je veľmi elegantné.
  • Sám súbor kanálov pre vydania sa môže meniť. V určitom časovom okamihu, napríklad, môže na kanáloch chýbať verzia stabilnejšia ako vydanie early-access 1.1, ale časom sa objavia — nemennit v tomto prípade zostavenie ručne?

Z toho vyplýva, že zostavenie závisí od sa meniacej vonkajších údajov..

Implementácia

Výber prístupu

Ako variantu, môžeme spustiť každú potrebnú verziu ako samostatný pod v Kubernetes. Taký variant predpokladá väčší počet objektov v klastri, ktorý bude rásť s počtom stabilných vydaní werf. A to zase predpokladá zložitejšiu údržbu: na každú verziu vzniká vlastný HTTP server, pričom s malou záťažou. Samozrejme, to so sebou nesie aj väčšie výdavky na zdroje.

My sme sa vydali cestou zostavenia všetkých potrebných verzií v jednom obraze.Skompilovaná statika všetkých verzií webu sa nachádza v kontajneri s NGINX, a prenos na príslušný Deployment prichádza cez NGINX Ingress. Jednoduchá štruktúra — stateless aplikácia — umožňuje jednoducho škálovať Deployment (v závislosti od záťaže) pomocou samotného Kubernetes.

Ak chceme byť presní, zhromažďujeme dva obrazy: jeden pre produkčné prostredie a druhý, dodatočný, pre vývojové prostredie. Dodatočný obraz sa používa (spúšťa) iba v prostredí dev spolu s hlavným a obsahuje verziu webovej stránky z review commit-u, pričom smerovanie medzi nimi sa vykonáva pomocou zdrojov Ingress.

werf vs git clone a artefakty

Ako už bolo spomenuté, na generovanie statických stránok pre konkrétnu verziu dokumentácie je potrebné vykonať zostavenie, pričom sa prepína na príslušný tag v repozitári. Môžeme to robiť aj klonovaním repozitára zakaždým pri zostavení a výberom príslušných tagov zo zoznamu. Avšak, táto operácia je dosť náročná na zdroje a tiež si vyžaduje napísanie netriviálnych pokynov... Ďalším vážnym mínusom je, že pri takomto prístupe nie je možnosť niečo cache-ovať počas zostavovania.

Tu nám na pomoc prichádza samotný nástroj werf, ktorý implementuje inteligentné cacheovanie a umožňuje používať externé repozitáre. Použitie werf na pridanie kódu z repozitára značným spôsobom urýchli zostavovanie, keďže werf v podstate raz klonuje repozitár a potom vykonáva iba fetch podľa potreby. Okrem toho, pri pridávaní údajov z repozitára môžeme vybrať iba potrebné adresáre (v našom prípade je to adresár docs), čo značne zníži objem pridávaných údajov.

Keďže Jekyll je nástroj určený na kompiláciu statiky a nie je potrebný v konečnom obraze, bolo by logické vykonať kompiláciu v artefakte werf, a do konečného obrazu importovať iba výsledok kompilácie.

Napíšeme werf.yaml

Takže sme sa rozhodli, že budeme kompilovať každú verziu v samostatnom artefakte werf. Avšak, nevieme, koľko týchto artefaktov bude pri zostavení, preto nemôžeme napísať pevne stanovenú konfiguráciu zostavovania (prísne povedané, stále môžeme, ale nebude to veľmi efektívne).

werf umožňuje používať Go šablóny vo svojom konfiguračnom súbore (werf.yaml), a to dáva možnosť generovať konfiguráciu „za behu“ na základe externých údajov (to, čo potrebujeme!). Externými údajmi v našom prípade sú informácie o verziách a vydaniach, na základe ktorých zostavujeme potrebné množstvo artefaktov a dostávame v konečnom dôsledku dva obrazy: werf-doc a werf-dev pre spúšťanie na rôznych kontúroch.

Externé údaje sú prenášané prostredníctvom premenných prostredia. Tu je ich zloženie:

  • VERZIE — reťazec so zoznamom verzií a ich aktuálnou verziou werf vo forme zoznamu oddeleného medzerami v formáte %. Príklad: 1.0%v1.0.4-beta.20
  • KANÁLY — reťazec so zoznamom kanálov a ich aktuálnou verziou werf vo forme zoznamu oddeleného medzerami v formáte %. Príklad: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERZIA — verzia pre releasing werf, ktorá bude zobrazená predvolene na stránke (nie vždy je potrebné zobrazovať dokumentáciu pre najvyššie číslo verzie). Príklad: v1.0.4-beta.20
  • REVIEW_SHA — hash review-commit, z ktorého je potrebné zostaviť verziu pre testovací obvod.

Tieto premenné budú naplnené v pipeline GitLab CI, a ako presne — je napísané nižšie.

Najprv, pre pohodlie, určme v werf.yaml premenné Go šablón, priradiac im hodnoty z premenných prostredia:

{{ $_ := set . "WerfVersions" (cat (env "KANÁLY") (env "VERZIE") | splitList " ") }}
{{ $Root := . }}
{{ $_ := set . "WerfRootVersion" (env "ROOT_VERZIA") }}
{{ $_ := set . "WerfReviewCommit" (env "REVIEW_SHA") }}

Popis artefaktu na zostavenie statiky verzie stránky je vo všeobecnosti rovnaký pre všetky potrebné prípady (vrátane generácie koreňovej verzie, ako aj verzie pre dev-obvod). Preto ho presunieme do samostatného bloku pomocou funkcie define — na následné opätovné použitie s pomocou include. Šablóne budeme odovzdávať nasledujúce argumenty:

  • Verzia — generovanú verziu (názov tagu);
  • Channel — názov kanála aktualizácií, pre ktorý je generovaný artefakt;
  • Commit — hash commitu, ak je artefakt generovaný pre review-commit;
  • kontext.

Popis šablóny artefaktu

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

Názov artefaktu musí byť unikátny. Môžeme to dosiahnuť, napríklad, pridaním názvu kanála (hodnota premennej .Channel) ako prídavku názvu artefaktu: artifact: doc-{{ .Channel }}. Ale je potrebné chápať, že pri importe z artefaktov bude potrebné odkazovať na rovnaké mená.

Pri popise artefaktu sa používa taká možnosť werf, ako montovanie. Montovanie s uvedením pomocného adresára build_dir umožňuje uchovávať medzipamäť Jekyll medzi spusteniami pipeline, čo výrazne urýchľuje opätovné zostavenie.

Tiež ste si mohli všimnúť používanie súboru releases.yml — je to YAML súbor s údajmi o vydaniach, ktorý sa žiada z github.com (artefakt, ktorý sa získava pri vykonávaní pipeline). Je potrebný pri kompilácii stránky, ale v kontexte článku nás zaujíma tým, že od jeho stavu závisí opätovné zostavenie iba jedného artefaktu — artefaktu stránky koreňovej verzie (v iných artefaktoch nie je potrebný).

Toto je realizované pomocou podmienečného operátora ak Go šablón a konštrukcie {{ $Root.Files.Get "releases.yml" | sha256sum }} v etape stádia. Funguje to nasledovne: pri zostavovaní artefaktu pre hlavnú verziu (premenná .Channel rovná root) hash súboru releases.yml ovplyvňuje podpis celého stupňa, pretože je súčasťou názvu úlohy Ansible (parameter name). Týmto spôsobom, pri zmene obsahu súboru releases.yml sa vyžaduje, aby bol príslušný artefakt znovu zostavený.

Všimnite si tiež prácu s externým repozitárom. Do obrazu artefaktu z repozitára werf, sa pridáva iba adresár /docs, pričom v závislosti od odovzdaných parametrov sa okamžite pridávajú dáta potrebného tagu alebo review-commit.

Ak chcete použiť šablónu artefaktu na generovanie popisu artefaktu odovzdaných verzií kanálov a vydaní, zorganizujeme cyklus po premennej .WerfVersions v werf.yaml:

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

Keďže cyklus vygeneruje niekoľko artefaktov (na to dúfame), je potrebné zohľadniť oddeľovač medzi nimi — sekvencia --- (podrobnejšie o syntaxi konfiguračného súboru pozri v dokumenácie). Ako sme sa už skôr dohodli, pri volaní šablóny v cykle odovzdávame parametre verzie, URL a hlavnú kontext.

Podobne, ale už bez cyklu, voláme šablónu artefaktu pre «špeciálne prípady»: pre hlavnú verziu, ako aj verziu z 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 }}

Všimnite si, že artefakt pre review-commit bude zostavený iba v prípade, ak je nastavená premenná .WerfReviewCommit.

Artefakty sú pripravené — je čas zaoberať sa importom!

Koncový obraz, určený na spustenie v Kubernetes, predstavuje bežný NGINX, do ktorého bol pridaný konfiguračný súbor servera nginx.conf a statika z artefaktov. Okrem artefaktu hlavnej verzie webovej stránky musíme zopakovať cyklus po premennej .WerfVersions na import artefaktov verzií kanálov a vydaní + dodržať pravidlo pomenovania artefaktov, ktoré sme si predtým stanovili. Keďže každý artefakt uchováva verzie stránky pre dva jazyky, importujeme ich na miesta, ktoré sú predpokladané konfiguráciou.

Popis konečného obrazu werf-doc

obraz: werf-doc
z: nginx:stable-alpine
ansible:
  setup:
  - name: "Nastavenie 
/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 -}}

Doplnkový obraz, ktorý sa spolu s hlavným spúšťa na dev-kontúre, obsahuje iba dve verzie webu: verziu z revidovacieho commit-a a hlavnú verziu webu (tam sú spoločné assety a, ak si pamätáte, údaje o vydaniach). Takže, doplnkový obraz sa od hlavného líši iba sekciou importu (no a, samozrejme, menom):

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

Ako už bolo spomenuté vyššie, artefakt pre revidovací commit sa bude generovať iba pri spustení nastavenej premennej prostredia. REVIEW_SHA. Bolo by možné vôbec negenerovať obraz werf-dev, ak nie je premenná prostredia. REVIEW_SHA, ale na to, aby čistenie podľa politík Docker-obrazov v werf fungovalo pre obraz werf-dev, zostaneme pri jeho zostavení iba s artefaktom hlavnej verzie (už bol zostavený), aby sa zjednodušila štruktúra pipeline.

Zostavenie je hotové! Prechádzame na CI/CD a dôležité nuansy.

Pipeline v GitLab CI a vlastnosti dynamického zostavenia.

Pri spustení zostavenia je potrebné nastaviť premenné prostredia, ktoré sa používajú v werf.yaml. To sa netýka premennej REVIEW_SHA, ktorú nastavíme pri vyvolávaní pipeline z GitHub webhooku.

Vytvorenie potrebných externých údajov presunieme do Bash skriptu generate_artifacts, ktorý bude generovať dva artefakty pre pipeline GitLab:

  • súbor releases.yml s údajmi o vydaniach,
  • súbor common_envs.sh, obsahujúci premenné prostredia na export.

Obsah súboru generate_artifacts nájdete v našom repozítári s príkladmi. Samotné získavanie údajov nie je predmetom článku, ale súbor common_envs.sh je dôležitý, pretože od neho závisí fungovanie werf. Príklad jeho obsahu:

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'

Výstup takéhoto skriptu je možné použiť napríklad pomocou Bash funkcie. source.

A teraz to najzaujímavejšie. Aby fungovala správne aj zostava, aj nasadenie aplikácie, je potrebné zabezpečiť, aby werf.yaml bol rovnakým minimálne v rámci jedného pipeline. Ak sa táto podmienka nesplní, podpisy fáz, ktoré werf počíta pri zostavovaní a napríklad nasadení, budú rôzne. To spôsobí chybu pri nasadení, pretože potrebný obraz pre nasadenie bude chýbať.

Inými slovami, ak počas zostavovania obrazu stránky sú informácie o vydaniach a verziách jedny, a v okamihu nasadenia vyjde nová verzia a premenne prostredia budú mať iné hodnoty, nasadenie sa skončí chybou: veď artefakt novej verzie ešte nebol zostavený.

Ak generácia werf.yaml závisí od externých údajov (napríklad zoznamu aktuálnych verzií, ako v našom prípade), potom zloženie a hodnoty takýchto údajov by sa mali stabilizovať v rámci pipeline. To je obzvlášť dôležité, ak sa externé parametre pomerne často menia.

Budeme zhromažďovať a stabilizovať externé údaje v prvej fáze pipeline v GitLab (Prebuild) a predávať ich ďalej vo forme artefaktu GitLab CI. To umožní spúšťať a znovu spúšťať úlohy pipeline (zostavenie, nasadenie, údržba) s rovnakou konfiguráciou v werf.yaml.

Obsah fázy Prebuild súboru .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

Zafixovaním externých údajov v artefakte je možné vykonávať zostavenie a nasadenie pomocou štandardných fáz pipeline GitLab CI: Build a Deploy. Samotný pipeline spúšťame pomocou hookov z GitHub úložiska werf (t.j. pri zmenách v úložisku na GitHub). Údaje pre ne môžeme získať v vlastnostiach projektu GitLab v sekcii CI / CD Settings -> Pipeline triggers, a potom vytvoríme v GitHub zodpovedajúci Webhook (Settings -> Webhooks).

Fáza zostavenia bude vyzerať nasledovne:

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 pridá do fázy zostavenia dva artefakty z fázy Prebuild, takže exportujeme premenne s pripravenými vstupnými údajmi pomocou konštrukcie source common_envs.sh. Spúšťame fázu zberu vo všetkých prípadoch, okrem spustenia pipeline podľa rozpisu. Podľa rozpisu sa spustí pipeline na čistenie — v tomto prípade nie je potrebné vykonávať zber.

Vo fáze nasadzovania opíšeme dve úlohy — samostatne pre nasadenie na production a dev kontúry, pomocou YAML šablóny:

.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

Nasadenie na produkciu:
  <<: *base_deploy
  variables:
    WERF_KUBE_CONTEXT: prod
  environment:
    name: production
    url: werf.io
  only:
    refs:
      - master
  except:
    variables:
      - $REVIEW_SHA
    refs:
      - schedules

Nasadenie na test:
  <<: *base_deploy
  variables:
    WERF_KUBE_CONTEXT: dev
  environment:
    name: test
    url: werf.test.flant.com
  except:
    refs:
      - schedules
  only:
    variables:
      - $REVIEW_SHA

Úlohy sa líšia iba označením kontextu klastra, do ktorého by mal werf vykonávať nasadenie (WERF_KUBE_CONTEXT), a nastavením premenných prostredia kontúry (environment.name a environment.url), ktoré sa potom používajú v šablónach Helm diagramu. Obsah šablón nebudeme uvádzať, pretože tam nie je nič zaujímavé pre prerokovávanú tému, ale môžete ich nájsť v repozitári k článku.

Finálny dotyk

Keďže verzie werf vychádzajú pomerne často, budú sa často vytvárať nové obrazy a Docker Registry — neustále rásť. Preto je potrebné nastaviť automatické čistenie obrazov podľa politík. Urobiť to je veľmi jednoduché.

Na realizáciu bude potrebné:

  • Pridať fázu čistenia do .gitlab-ci.yml;
  • Pridať periodické vykonávanie úlohy čistenia;
  • Nastaviť premennú prostredia s prístupovým tokenom na zápis.

Pridávame fázu čistenia do .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

Takmer všetko sme už videli trochu vyššie — len pre čistenie je potrebné najprv sa autorizovať v Docker Registry s tokenom, ktorý má práva na odstránenie obrazov v Docker Registry (automatiky vydávaný token úlohy GitLab CI takéto práva nemá). Token je potrebné získať v GitLabe vopred a uviesť jeho hodnotu v premennej prostredia WERF_IMAGES_CLEANUP_PASSWORD projektu (CI/CD nastavenia -> Premenné).

Pridanie úlohy čistenia s potrebným rozpisom sa vykonáva v CI/CD ->
Harmonogramy
.

Všetko: projekt v Docker Registry už nebude neustále rásť kvôli nepoužívaným obrazom.

Na záver praktickej časti pripomeniem, že plné výpisy z článku sú dostupné na Git:

Výsledok

  1. Dostali sme logickú štruktúru zostavenia: jeden artefakt na jednu verziu.
  2. Zostavenie je univerzálne a nevyžaduje manuálne zmeny pri vydávaní nových verzií werf: dokumentácia na stránke sa automaticky aktualizuje.
  3. Zostavené sú dva obrazy pre rôzne kontúry.
  4. Pracuje rýchlo, pretože maximálne využíva caching — pri vydaní novej verzie werf alebo pri aktivácii GitHub hook pre review commit — prebieha prebuild iba zodpovedajúceho artefaktu so zmenenou verziou.
  5. Nie je potrebné myslieť na odstránenie nepoužívaných obrazov: čistenie podľa politík werf udrží poriadok v Docker Registry.

Zhrnutie

  • Používanie werf umožňuje, aby zostavenie pracovalo rýchlo vďaka cache samotnej zostavy aj cache pri práci s externými repozitármi.
  • Práca s externými Git repozitármi eliminuje potrebu každom plne klonovať repozitár alebo vymýšľať koleso s komplikovanou logikou optimalizácie. werf používa cache a robí klonovanie iba raz, a potom používa fetch a len podľa potreby.
  • Možnosť používania Go šablón v konfiguračnom súbore zostavenia werf.yaml umožňuje opísať zostavenie, ktorého výsledok závisí od externých údajov.
  • Použitie montovania v werf značne urýchľuje zostavenie artefaktov — vďaka cache, ktorá je spoločná pre všetky pipeline.
  • werf umožňuje ľahko nastaviť čistenie, čo je obzvlášť aktuálne pri dynamickom zostavení.

P.S.

Prečítajte si tiež na našom blogu:

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster