Montimi dinamik dhe vendosja e imazheve Docker me werf duke përdorur shembullin e një siti dokumentacioni të versionuar

Ne kemi folur tashmë për mjetin tonë GitOps më shumë se një herë. werf, dhe këtë herë dëshirojmë të ndajmë përvojën tonë në montimin e faqes me dokumentacionin e vetë projektit - werf.io (versioni i tij rus është en.werf.io). Ky është një vend i zakonshëm statik, por montimi i tij është interesant në atë që është ndërtuar duke përdorur një numër dinamik objektesh.

Montimi dinamik dhe vendosja e imazheve Docker me werf duke përdorur shembullin e një siti dokumentacioni të versionuar

Shkoni në nuancat e strukturës së faqes: gjenerimi i një menuje të përbashkët për të gjitha versionet, faqet me informacione rreth publikimeve, etj. - ne nuk do të. Në vend të kësaj, le të përqendrohemi në çështjet dhe veçoritë e montimit dinamik dhe pak në proceset shoqëruese CI/CD.

Hyrje: si funksionon faqja

Për të filluar, dokumentacioni werf ruhet së bashku me kodin e tij. Kjo imponon disa kërkesa zhvillimi që në përgjithësi janë përtej qëllimit të këtij neni, por së paku mund të thuhet se:

  • Funksionet e reja werf nuk duhet të lëshohen pa përditësuar dokumentacionin dhe, anasjelltas, çdo ndryshim në dokumentacion nënkupton lëshimin e një versioni të ri të werf;
  • Projekti ka një zhvillim mjaft intensiv: versionet e reja mund të lëshohen disa herë në ditë;
  • Çdo operacion manual për të vendosur një faqe me një version të ri të dokumentacionit është të paktën i lodhshëm;
  • Projekti miraton një qasje semantike versionimi, me 5 kanale stabiliteti. Procesi i lëshimit përfshin kalimin e njëpasnjëshëm të versioneve nëpër kanale në mënyrë që të rritet qëndrueshmëria: nga alfa në shkëmb të ngurtë;
  • Sajti ka një version në gjuhën ruse, i cili "jeton dhe zhvillohet" (d.m.th., përmbajtja e të cilit përditësohet) paralelisht me versionin kryesor (d.m.th., në gjuhën angleze).

Për të fshehur gjithë këtë "kuzhinë të brendshme" nga përdoruesi, duke i ofruar atij diçka që "thjesht funksionon", ne bëmë vegël e veçantë e instalimit dhe përditësimit të werf - A multiwerf. Thjesht duhet të specifikoni numrin e lëshimit dhe kanalin e qëndrueshmërisë që jeni gati për të përdorur, dhe multiwerf do të kontrollojë nëse ka një version të ri në kanal dhe do ta shkarkojë nëse është e nevojshme.

Në menynë e përzgjedhjes së versioneve në faqen e internetit, versionet më të fundit të werf janë të disponueshme në çdo kanal. Si parazgjedhje, sipas adresës werf.io/documentation hapet versioni i kanalit më të qëndrueshëm për versionin më të fundit - ai gjithashtu indeksohet nga motorët e kërkimit. Dokumentacioni për kanalin është i disponueshëm në adresa të veçanta (për shembull, werf.io/v1.0-beta/documentation për lëshimin beta 1.0).

Në total, faqja ka në dispozicion versionet e mëposhtme:

  1. root (hapet si parazgjedhje),
  2. për çdo kanal të përditësimit aktiv të çdo versioni (për shembull, werf.io/v1.0-beta).

Për të gjeneruar një version specifik të një siti, në përgjithësi, mjafton ta përpiloni atë duke përdorur Jekyllduke ekzekutuar në drejtori /docs komanda përkatëse e depove werf (jekyll build), pasi të kaloni në etiketën Git të versionit të kërkuar.

Mbetet vetëm të shtojmë se:

  • vetë mjeti (werf) përdoret për montim;
  • Proceset CI/CD janë ndërtuar mbi bazën e GitLab CI;
  • dhe e gjithë kjo, natyrisht, funksionon në Kubernetes.

detyrat

Tani le të formulojmë detyra që marrin parasysh të gjitha specifikat e përshkruara:

  1. Pas ndryshimit të versionit werf në çdo kanal përditësimi dokumentacioni në sit duhet të përditësohet automatikisht.
  2. Për zhvillim ju duhet të jeni në gjendje ndonjëherë shikoni versionet paraprake të faqes.

Sajti duhet të ripërpilohet pas ndryshimit të versionit në çdo kanal nga etiketat përkatëse Git, por në procesin e ndërtimit të imazhit do të marrim veçoritë e mëposhtme:

  • Meqenëse lista e versioneve në kanale ndryshon, është e nevojshme vetëm rindërtimi i dokumentacionit për kanalet ku versioni ka ndryshuar. Në fund të fundit, rindërtimi i gjithçkaje përsëri nuk është shumë i këndshëm.
  • Grupi i kanaleve për publikimet mund të ndryshojë. Në një moment në kohë, për shembull, mund të mos ketë një version në kanale më të qëndrueshëm se lëshimi i hyrjes së hershme 1.1, por me kalimin e kohës ato do të shfaqen - në këtë rast, a nuk duhet ta ndryshoni montimin manualisht?

Ajo rezulton se montimi varet nga ndryshimi i të dhënave të jashtme.

Zbatimi

Zgjedhja e një qasjeje

Përndryshe, ju mund të ekzekutoni çdo version të kërkuar si një pod të veçantë në Kubernetes. Ky opsion nënkupton një numër më të madh objektesh në grup, i cili do të rritet me rritjen e numrit të lëshimeve të qëndrueshme të werfeve. Dhe kjo, nga ana tjetër, nënkupton mirëmbajtje më komplekse: çdo version ka serverin e vet HTTP, dhe me një ngarkesë të vogël. Natyrisht, kjo kërkon edhe kosto më të mëdha burimesh.

Ne morëm të njëjtën rrugë duke mbledhur të gjitha versionet e nevojshme në një imazh. Statikat e përpiluara të të gjitha versioneve të faqes janë të vendosura në një kontejner me NGINX, dhe trafiku në vendosjen përkatëse vjen përmes NGINX Ingress. Një strukturë e thjeshtë - një aplikacion pa shtetësi - ju lejon të shkallëzoni lehtësisht vendosjen (në varësi të ngarkesës) duke përdorur vetë Kubernetes.

Për të qenë më të saktë, ne po mbledhim dy imazhe: njëra për qarkun e prodhimit, e dyta është një shtesë për qarkun e devijimit. Imazhi shtesë përdoret (lançohet) vetëm në qarkun e devijimit së bashku me atë kryesor dhe përmban versionin e faqes nga komisioni i rishikimit, dhe rrugëtimi midis tyre kryhet duke përdorur burimet Ingress.

klon werf vs git dhe artefakte

Siç është përmendur tashmë, për të gjeneruar statikë të faqes për një version specifik të dokumentacionit, duhet të ndërtoni duke kaluar në etiketën e duhur të depove. Ju gjithashtu mund ta bëni këtë duke klonuar depon çdo herë që ndërtoni, duke zgjedhur etiketat e duhura nga një listë. Megjithatë, ky është një operacion mjaft intensiv i burimeve dhe, për më tepër, kërkon shkrimin e udhëzimeve jo të parëndësishme... Një tjetër disavantazh serioz është se me këtë qasje nuk ka asnjë mënyrë për të ruajtur diçka në memorie gjatë montimit.

Këtu na vjen në ndihmë vetë shoqëria werf, duke zbatuar memorie inteligjente dhe ju lejon të përdorni depot e jashtme. Përdorimi i werf për të shtuar kodin nga depoja do të përshpejtojë ndjeshëm ndërtimin, sepse werf në thelb klonon depon një herë dhe më pas ekzekuton vetëm fetch nëse është e nevojshme. Përveç kësaj, kur shtojmë të dhëna nga depoja, ne mund të zgjedhim vetëm drejtoritë e nevojshme (në rastin tonë kjo është drejtoria docs), gjë që do të zvogëlojë ndjeshëm sasinë e të dhënave të shtuara.

Meqenëse Jekyll është një mjet i krijuar për përpilimin e të dhënave statike dhe nuk nevojitet në imazhin përfundimtar, do të ishte logjike të përpilohej në artefakt werf, dhe në imazhin përfundimtar importoni vetëm rezultatin e përpilimit.

Shkruajmë werf.yaml

Pra, vendosëm që të përpilonim secilin version në një objekt të veçantë werf. Megjithatë ne ne nuk e dimë se sa nga këto artefakte do të ketë gjatë montimit, kështu që ne nuk mund të shkruajmë një konfigurim fiks ndërtimi (duke thënë rreptësisht, ne ende mundemi, por nuk do të jetë plotësisht efektiv).

werf ju lejon të përdorni Shkoni shabllonet në skedarin tuaj të konfigurimit (werf.yaml), dhe kjo e bën të mundur gjenerojnë konfigurimin në fluturim në varësi të të dhënave të jashtme (çfarë ju nevojitet!). Të dhënat e jashtme në rastin tonë janë informacione rreth versioneve dhe lëshimeve, në bazë të të cilave ne mbledhim numrin e kërkuar të objekteve dhe si rezultat marrim dy imazhe: werf-doc и werf-dev për të punuar në qarqe të ndryshme.

Të dhënat e jashtme kalohen përmes variablave të mjedisit. Këtu është përbërja e tyre:

  • RELEASES - një rresht me një listë të lëshimeve dhe versionin aktual përkatës të werf, në formën e një liste vlerash të ndarë me hapësirë ​​në format <НОМЕР_РЕЛИЗА>%<НОМЕР_ВЕРСИИ>. Shembull: 1.0%v1.0.4-beta.20
  • CHANNELS - një rresht me një listë kanalesh dhe versionin aktual përkatës të werf, në formën e një liste vlerash të ndarë me hapësirë ​​në format <КАНАЛ>%<НОМЕР_ВЕРСИИ>. Shembull: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERSION — Versioni i lëshimit werf të shfaqet si parazgjedhje në sajt (nuk është gjithmonë e nevojshme të shfaqet dokumentacioni me numrin më të lartë të lëshimit). Shembull: v1.0.4-beta.20
  • REVIEW_SHA — hash i komisionit të rishikimit nga i cili duhet të ndërtoni versionin për ciklin e testimit.

Këto variabla do të plotësohen në tubacionin e GitLab CI, dhe si shkruhet saktësisht më poshtë.

Para së gjithash, për lehtësi, ne përcaktojmë në werf.yaml Shkoni variablat e shabllonit, duke u caktuar atyre vlera nga variablat e mjedisit:

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

Përshkrimi i artefaktit për përpilimin e versionit statik të faqes është përgjithësisht i njëjtë për të gjitha rastet që na duhen (përfshirë gjenerimin e versionit rrënjë, si dhe versionin për qarkun e devijimit). Prandaj, ne do ta zhvendosim atë në një bllok të veçantë duke përdorur funksionin define - për ripërdorim të mëvonshëm include. Ne do të kalojmë argumentet e mëposhtme në shabllon:

  • Version — versioni i gjeneruar (emri i etiketës);
  • Channel — emri i kanalit të përditësimit për të cilin është krijuar objekti;
  • Commit — kryeni hash, nëse artifakti është krijuar për një kryerje rishikimi;
  • kontekst.

Përshkrimi i shabllonit të objektit

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

Emri i objektit duhet të jetë unik. Këtë mund ta arrijmë, për shembull, duke shtuar emrin e kanalit (vlera e ndryshores .Channel) si prapashtesë e emrit të objektit: artifact: doc-{{ .Channel }}. Por duhet të kuptoni se kur importoni nga objekte, do t'ju duhet t'i referoheni të njëjtëve emra.

Kur përshkruani një objekt, përdoret tipari i mëposhtëm werf: montimi. Montimi që tregon drejtorinë e shërbimit build_dir ju lejon të ruani cache-in e Jekyll midis drejtimeve të tubacionit, i cili përshpejton ndjeshëm rimontimin.

Ju gjithashtu mund të keni vënë re përdorimin e skedarit releases.yml është një skedar YAML me të dhënat e lëshimit të kërkuara nga github.com (një objekt i marrë gjatë ekzekutimit të një tubacioni). Është e nevojshme gjatë përpilimit të faqes, por në kontekstin e artikullit është interesante për ne sepse varet nga gjendja e saj rimontimi i vetëm një objekti — një objekt i versionit rrënjësor të faqes (nuk nevojitet në objekte të tjera).

Kjo zbatohet duke përdorur deklaratën e kushtëzuar if Shkoni shabllonet dhe dizajnet {{ $Root.Files.Get "releases.yml" | sha256sum }} në skenë fazat. Ai funksionon si më poshtë: kur ndërtoni një objekt për versionin rrënjë (ndryshore .Channel është e barabartë me root) hash i skedarit releases.yml ndikon në nënshkrimin e të gjithë fazës, pasi është pjesë e emrit të detyrës Ansible (parametri name). Kështu, kur ndryshoni përmbajtjen dosje releases.yml do të rimontohet objekti përkatës.

Ju lutemi kushtojini vëmendje edhe punës me një depo të jashtme. Në imazhin e një objekti nga depo werf, shtohet vetëm drejtoria /docs, dhe në varësi të parametrave të kaluar, të dhënat e etiketës së kërkuar ose të komisionit të rishikimit shtohen menjëherë.

Për të përdorur shabllonin e objektit për të gjeneruar një përshkrim të artefaktit të versioneve të transferuara të kanaleve dhe publikimeve, ne organizojmë një lak në variablin .WerfVersions в werf.yaml:

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

Sepse lak do të gjenerojë disa objekte (shpresojmë kështu), është e nevojshme të merret parasysh ndarësi midis tyre - sekuenca --- (Për më shumë informacion mbi sintaksën e skedarit të konfigurimit, shihni dokumentacionin). Siç është përcaktuar më herët, kur thërrasim një shabllon në një lak, ne kalojmë parametrat e versionit, URL-në dhe kontekstin rrënjë.

Në mënyrë të ngjashme, por pa një lak, ne e quajmë shabllonin e objektit për "raste të veçanta": për versionin rrënjë, si dhe versionin nga kryerja e rishikimit:

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

Ju lutemi vini re se objekti për kryerjen e rishikimit do të ndërtohet vetëm nëse ndryshorja është vendosur .WerfReviewCommit.

Artifaktet janë gati - është koha për të filluar importimin!

Imazhi përfundimtar, i krijuar për të ekzekutuar në Kubernetes, është një NGINX i rregullt me ​​një skedar konfigurimi të serverit të shtuar nginx.conf dhe statike nga artefaktet. Përveç artefaktit të versionit rrënjësor të faqes, duhet të përsërisim ciklin në variabël .WerfVersions për të importuar artefakte të versioneve të kanalit dhe lëshimit + ndiqni rregullin e emërtimit të objektit që kemi miratuar më parë. Meqenëse çdo objekt ruan versionet e sajtit për dy gjuhë, ne i importojmë ato në vendet e ofruara nga konfigurimi.

Përshkrimi i imazhit përfundimtar 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 -}}

Imazhi shtesë, i cili, së bashku me atë kryesor, lëshohet në qarkun e devijimit, përmban vetëm dy versione të faqes: versionin nga kryerja e rishikimit dhe versioni rrënjësor i faqes (ka asete të përgjithshme dhe, nëse ju kujtohet , lëshimi i të dhënave). Kështu, imazhi shtesë do të ndryshojë nga ai kryesor vetëm në seksionin e importit (dhe, natyrisht, në emër):

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

Siç u përmend më lart, artifakti për kryerjen e rishikimit do të gjenerohet vetëm kur të ekzekutohet ndryshorja e mjedisit të caktuar REVIEW_SHA. Do të ishte e mundur të mos gjenerohej fare imazhi werf-dev nëse nuk ka ndryshore mjedisore REVIEW_SHA, por në mënyrë që të pastrimi sipas politikave Imazhet e dokerit në werf funksionuan për imazhin werf-dev, do ta lëmë të ndërtohet vetëm me artifaktin e versionit rrënjë (gjithsesi është ndërtuar tashmë), për të thjeshtuar strukturën e tubacionit.

Asambleja është gati! Le të kalojmë te CI/CD dhe nuancat e rëndësishme.

Pipeline në GitLab CI dhe veçoritë e ndërtimit dinamik

Kur ekzekutojmë ndërtimin, duhet të vendosim variablat e mjedisit të përdorura në werf.yaml. Kjo nuk vlen për variablin REVIEW_SHA, të cilin do ta vendosim kur thërrasim tubacionin nga grepa GitHub.

Ne do të gjenerojmë të dhënat e nevojshme të jashtme në një skript Bash generate_artifacts, i cili do të gjenerojë dy artefakte të tubacionit GitLab:

  • файл releases.yml me të dhënat e lëshimit,
  • файл common_envs.sh, që përmban variablat e mjedisit që do të eksportohen.

Përmbajtja e skedarit generate_artifacts ju do të gjeni në tonë depo me shembuj. Marrja e të dhënave në vetvete nuk është objekti i artikullit, por skedari common_envs.sh është e rëndësishme për ne, sepse prej saj varet puna e werfit. Një shembull i përmbajtjes së tij:

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'

Ju mund të përdorni daljen e një skripti të tillë, për shembull, duke përdorur funksionin Bash source.

Tani vjen pjesa argëtuese. Në mënyrë që ndërtimi dhe vendosja e aplikacionit të funksionojnë si duhet, është e nevojshme të sigurohet që werf.yaml был e njëjta të paktën brenda një tubacioni. Nëse ky kusht nuk plotësohet, atëherë nënshkrimet e fazave që llogariten gjatë montimit dhe, për shembull, vendosjes, do të jenë të ndryshme. Kjo do të çojë në një gabim vendosjeje, sepse... imazhi i kërkuar për vendosjen do të mungojë.

Me fjalë të tjera, nëse gjatë montimit të imazhit të faqes, informacioni rreth lëshimeve dhe versioneve është i njëjtë, dhe në momentin e vendosjes lëshohet një version i ri dhe variablat e mjedisit kanë vlera të ndryshme, atëherë vendosja do të dështojë me një gabim: në fund të fundit, artefakti i versionit të ri nuk është ndërtuar ende.

Nëse brezi werf.yaml varet nga të dhënat e jashtme (për shembull, një listë e versioneve aktuale, si në rastin tonë), atëherë përbërja dhe vlerat e të dhënave të tilla duhet të regjistrohen brenda tubacionit. Kjo është veçanërisht e rëndësishme nëse parametrat e jashtëm ndryshojnë mjaft shpesh.

Ne do të marrin dhe regjistrojnë të dhëna të jashtme në fazën e parë të tubacionit në GitLab (Parandërtimi) dhe i transmetoni ato më tej në formë Artifakt GitLab CI. Kjo do t'ju lejojë të ekzekutoni dhe rinisni punët e tubacionit (ndërtimi, vendosja, pastrimi) me të njëjtin konfigurim në werf.yaml.

Përmbajtja e skenës Parandërtimi dosje .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

Pasi të keni kapur të dhënat e jashtme në artefakt, mund të ndërtoni dhe vendosni duke përdorur fazat standarde të tubacionit GitLab CI: Build dhe Deploy. Ne e nisim vetë tubacionin duke përdorur grepa nga depoja e werf GitHub (d.m.th., kur ka ndryshime në depon e GitHub). Të dhënat për ta mund të gjenden në vetitë e projektit GitLab në seksion Cilësimet CI/CD -> Aktivizuesit e tubacionit, dhe më pas krijoni Webhook-un përkatës në GitHub (Cilësimet -> Webhooks).

Faza e ndërtimit do të duket kështu:

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 do të shtojë dy artefakte nga skena në fazën e ndërtimit Parandërtimi, kështu që ne eksportojmë variabla me të dhëna hyrëse të përgatitura duke përdorur konstruktin source common_envs.sh. Ne fillojmë fazën e ndërtimit në të gjitha rastet, përveç nisjes së tubacionit sipas një plani. Sipas orarit, ne do të drejtojmë një tubacion për pastrim - në këtë rast nuk ka nevojë të kryhet montimi.

Në fazën e vendosjes, ne do të përshkruajmë dy detyra - veçmas për vendosjen në qarqet e prodhimit dhe devijimit, duke përdorur një shabllon 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

Detyrat në thelb ndryshojnë vetëm në përcaktimin e kontekstit të grupit në të cilin werf duhet të kryejë vendosjen (WERF_KUBE_CONTEXT), dhe vendosja e variablave të mjedisit të ciklit (environment.name и environment.url), të cilat përdoren më pas në shabllonet e diagramit Helm. Ne nuk do të ofrojmë përmbajtjen e shablloneve, sepse... nuk ka asgjë interesante për temën në fjalë, por mund t'i gjeni në depo për artikullin.

Prekja e fundit

Meqenëse versionet werf lëshohen mjaft shpesh, imazhet e reja do të ndërtohen shpesh dhe Regjistri Docker do të rritet vazhdimisht. Prandaj, është e domosdoshme të konfiguroni pastrimin automatik të imazhit bazuar në politika. Është shumë e lehtë për t'u bërë.

Për të zbatuar do t'ju duhet:

  • Shtoni një hap pastrimi në .gitlab-ci.yml;
  • Shto ekzekutimin periodik të një detyre pastrimi;
  • Vendosni një variabël mjedisi me një shenjë hyrjeje shkrimi.

Shtimi i një faze pastrimi në .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

Ne kemi parë tashmë pothuajse të gjitha këto pak më lart - vetëm për ta pastruar atë, së pari duhet të identifikoheni në Regjistrin Docker me një shenjë që ka të drejtën për të fshirë imazhet në Regjistrin Docker (tokeni i detyrave GitLab CI i lëshuar automatikisht nuk ka të drejta të tilla). Shenja duhet të krijohet paraprakisht në GitLab dhe vlera e tij duhet të specifikohet në variablin e mjedisit WERF_IMAGES_CLEANUP_PASSWORD projekti (Cilësimet CI/CD -> Variablat).

Shtimi i një detyre pastrimi me orarin e kërkuar është bërë në CI/CD ->
oraret
.

Kjo është e gjitha: një projekt në Regjistrin Docker nuk do të rritet vazhdimisht nga imazhet e papërdorura.

Në fund të pjesës praktike, më lejoni t'ju kujtoj se listat e plota nga artikulli janë në dispozicion në git:

Result

  1. Ne morëm një strukturë logjike të montimit: një objekt për version.
  2. Asambleja është universale dhe nuk kërkon ndryshime manuale kur lëshohen versionet e reja të werf: dokumentacioni në faqen e internetit përditësohet automatikisht.
  3. Dy imazhe janë mbledhur për konture të ndryshme.
  4. Ajo funksionon shpejt, sepse Memoria e memories përdoret sa më shumë që të jetë e mundur - kur lëshohet një version i ri i werf ose thirret një grep GitHub për kryerjen e rishikimit, vetëm objekti përkatës me versionin e ndryshuar rindërtohet.
  5. Nuk ka nevojë të mendoni për fshirjen e imazheve të papërdorura: pastrimi sipas politikave të werf do ta mbajë në rregull Regjistrin Docker.

Gjetjet

  • Përdorimi i werf lejon asamblenë të funksionojë shpejt për shkak të ruajtjes në memorie të vetë asamblesë dhe ruajtjes në memorie kur punoni me depo të jashtme.
  • Puna me depo të jashtme Git eliminon nevojën për të klonuar të gjithë depo çdo herë ose për të rishpikur rrotën me logjikën e ndërlikuar të optimizimit. werf përdor një cache dhe bën klonimin vetëm një herë, dhe më pas përdor fetch dhe vetëm kur është e nevojshme.
  • Aftësia për të përdorur shabllonet Go në skedarin e konfigurimit të ndërtimit werf.yaml ju lejon të përshkruani një asamble, rezultati i të cilit varet nga të dhënat e jashtme.
  • Përdorimi i montimit në werf përshpejton ndjeshëm mbledhjen e objekteve - për shkak të cache-it, i cili është i zakonshëm për të gjitha tubacionet.
  • werf e bën të lehtë konfigurimin e pastrimit, gjë që është veçanërisht e rëndësishme kur ndërtohet në mënyrë dinamike.

PS

Lexoni edhe në blogun tonë:

Burimi: www.habr.com

Shto një koment