Dynamisch bouwen en implementeren van Docker-images met werf op het voorbeeld van een documentatiesite met versiebeheer

We hebben het al meer dan eens gehad over onze GitOps-tool werf, en deze keer willen we de ervaring delen van het bouwen van een site met de documentatie van het project zelf - werf.io (de Russische versie is nl.werf.io). Dit is een normale statische site, maar de opbouw ervan is interessant omdat deze is gebouwd met behulp van een dynamisch aantal artefacten.

Dynamisch bouwen en implementeren van Docker-images met werf op het voorbeeld van een documentatiesite met versiebeheer

Ga in op de nuances van de sitestructuur: het genereren van een gemeenschappelijk menu voor alle versies, pagina's met informatie over releases, enz. - we zullen niet. Laten we ons in plaats daarvan concentreren op de problemen en bijzonderheden van dynamische assemblage en een beetje op de gerelateerde CI/CD-processen.

Inleiding: hoe de site werkt

Laten we beginnen met het feit dat werfdocumentatie samen met de code wordt opgeslagen. Dit legt bepaalde ontwikkelingsvereisten op die over het algemeen buiten het bestek van dit artikel vallen, maar er kan op zijn minst worden gezegd dat:

  • Nieuwe werf-functies mogen niet worden vrijgegeven zonder de documentatie bij te werken en, omgekeerd, alle wijzigingen in de documentatie impliceren een nieuwe versie van werf;
  • Het project kent een vrij intensieve ontwikkeling: er kunnen meerdere keren per dag nieuwe versies uitkomen;
  • Alle handmatige bewerkingen om een ​​site te implementeren met een nieuwe versie van de documentatie zijn op zijn minst vervelend;
  • Het project hanteerde de benadering van semantiek versiebeheer, met 5 kanalen van stabiliteit. Het vrijgaveproces omvat de sequentiële doorgang van versies door de kanalen in volgorde van toenemende stabiliteit: van alfa tot rotsvast;
  • De site heeft een Russischtalige versie die "leeft en zich ontwikkelt" (d.w.z. waarvan de inhoud wordt bijgewerkt) parallel aan de hoofdversie (d.w.z. de Engelstalige).

Om al deze "innerlijke keuken" voor de gebruiker te verbergen en hem iets aan te bieden dat "gewoon werkt", hebben we dat gedaan aparte werf installatie en update tool - Is multiwerf. U hoeft alleen het releasenummer en het stabiliteitskanaal dat u wilt gebruiken op te geven, en multiwerf zal controleren of er een nieuwe versie op het kanaal staat en deze indien nodig downloaden.

De nieuwste versies van werf in elk kanaal zijn beschikbaar in het versiekeuzemenu op de site. Standaard op werf.io/documentatie de versie van het meest stabiele kanaal voor de nieuwste release wordt geopend - het wordt ook geïndexeerd door zoekmachines. Documentatie voor het kanaal is beschikbaar op aparte adressen (bijvoorbeeld werf.io/v1.0-beta/documentatie voor bètaversie 1.0).

In totaal heeft de site de volgende versies beschikbaar:

  1. root (opent standaard),
  2. voor elk actief updatekanaal van elke release (bijvoorbeeld werf.io/v1.0-bèta).

Om een ​​specifieke versie van de site te genereren, is het in het algemeen voldoende om deze te compileren met behulp van Jekylldoor in de directory te lopen /docs werf-repository met het bijbehorende commando (jekyll build), na het overschakelen naar de Git-tag van de vereiste versie.

Het blijft alleen om toe te voegen dat:

  • de nutsvoorziening zelf (werf) wordt gebruikt voor montage;
  • CI/CD-processen zijn gebouwd bovenop GitLab CI;
  • en dit alles werkt natuurlijk in Kubernetes.

taken

Nu formuleren we taken die rekening houden met alle beschreven bijzonderheden:

  1. Na het wijzigen van de werf-versie op een updatekanaal documentatie op de site moet automatisch worden bijgewerkt.
  2. Voor ontwikkeling moet je soms kunnen sitevoorbeelden bekijken.

De hercompilatie van de site moet worden uitgevoerd na het wijzigen van de versie op elk kanaal van de overeenkomstige Git-tags, maar tijdens het bouwen van de afbeelding krijgen we de volgende functies:

  • Aangezien de lijst met versies op de kanalen verandert, is het alleen nodig om de documentatie opnieuw op te bouwen voor de kanalen waarvan de versie is gewijzigd. Alles opnieuw opbouwen is immers niet erg mooi.
  • De reeks kanalen voor releases kan veranderen. Op een bepaald moment is er bijvoorbeeld misschien geen versie op de kanalen die stabieler is dan de release met vroege toegang 1.1, maar na verloop van tijd zullen ze verschijnen - verander in dit geval de montage niet met de hand?

Het blijkt dat montage is afhankelijk van veranderende externe gegevens.

uitvoering

Keuze van aanpak

U kunt ook elke vereiste versie uitvoeren als een afzonderlijke pod in Kubernetes. Deze optie impliceert een groter aantal objecten in het cluster, dat zal groeien met een toename van het aantal stabiele releases van werf. En dit impliceert op zijn beurt meer complex onderhoud: elke versie heeft zijn eigen HTTP-server en met een kleine belasting. Dit brengt natuurlijk ook hogere resourcekosten met zich mee.

We gingen onderweg montage van alle benodigde versies in één afbeelding. De gecompileerde statistieken van alle versies van de site bevinden zich in een container met NGINX en het verkeer naar de bijbehorende Deployment komt via NGINX Ingress. Een eenvoudige structuur - een stateless applicatie - maakt het eenvoudig om Deployment (afhankelijk van de belasting) te schalen met behulp van Kubernetes zelf.

Om preciezer te zijn, we bouwen twee afbeeldingen: een voor het productiecircuit, de tweede is een extra voor het ontwikkelcircuit. De extra afbeelding wordt alleen gebruikt (gelanceerd) op de ontwikkellus samen met de hoofdafbeelding en bevat de versie van de site van de beoordelingstoewijzing, en routering tussen deze wordt uitgevoerd met behulp van Ingress-bronnen.

werf versus git kloon en artefacten

Zoals eerder vermeld, moet u, om sitestatistieken voor een specifieke versie van de documentatie te genereren, bouwen door over te schakelen naar de juiste repository-tag. U kunt dit ook doen door de repository elke keer dat u bouwt te klonen en de juiste tags uit de lijst te kiezen. Dit is echter een nogal resource-intensieve operatie en vereist bovendien het schrijven van niet-triviale instructies ... Een ander ernstig nadeel is dat er met deze aanpak geen manier is om iets in de cache op te slaan tijdens de montage.

Hier komt het werfhulpprogramma zelf te hulp, uitvoerend slim cachen en u in staat stellen om te gebruiken externe opslagplaatsen. Het gebruik van werf om code uit de repository toe te voegen, zal het bouwen enorm versnellen, omdat werf kloont de repository in wezen één keer en doet dat dan alleen fetch indien nodig. Bovendien kunnen we bij het toevoegen van gegevens uit de repository alleen de benodigde mappen selecteren (in ons geval is dit de map docs), wat de hoeveelheid toegevoegde gegevens aanzienlijk zal verminderen.

Aangezien Jekyll een hulpmiddel is voor het samenstellen van statica en niet nodig is in de uiteindelijke afbeelding, zou het logisch zijn om te compileren naar werf artefact, en in de uiteindelijke afbeelding importeer alleen het compilatieresultaat.

We schrijven werf.yaml

Daarom hebben we besloten dat we elke versie in een apart werfartefact zullen compileren. Echter, wij we weten niet hoeveel van deze artefacten er tijdens de montage zullen zijn, dus we kunnen geen vaste buildconfiguratie schrijven (strikt genomen kunnen we dat wel, maar het zal niet erg efficiënt zijn).

werf kunt u gebruiken Ga patronen in je configuratiebestand (werf.yaml), wat het mogelijk maakt genereer config on the fly afhankelijk van externe data (wat je nodig hebt!). Externe gegevens zijn in ons geval informatie over versies en releases, op basis waarvan we het vereiste aantal artefacten verzamelen en als resultaat twee afbeeldingen krijgen: werf-doc и werf-dev om op verschillende circuits te rijden.

Externe gegevens worden doorgegeven via omgevingsvariabelen. Hier is hun samenstelling:

  • RELEASES - een string met een lijst met releases en de bijbehorende huidige versie van werf, als een lijst gescheiden door een spatie met waarden in het formaat <НОМЕР_РЕЛИЗА>%<НОМЕР_ВЕРСИИ>. Voorbeeld: 1.0%v1.0.4-beta.20
  • CHANNELS - een regel met een lijst met kanalen en de bijbehorende huidige versie van werf, in de vorm van een lijst gescheiden door een spatie met waarden in het formaat <КАНАЛ>%<НОМЕР_ВЕРСИИ>. Voorbeeld: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERSION — versie van de werf-release die standaard op de site moet worden weergegeven (het is niet altijd nodig om documentatie op het hoogste releasenummer weer te geven). Voorbeeld: v1.0.4-beta.20
  • REVIEW_SHA — hash van de review commit, van waaruit je een versie moet bouwen voor de testlus.

Deze variabelen worden ingevuld in de GitLab CI-pijplijn, en hoe precies staat hieronder beschreven.

Allereerst definiëren we voor het gemak in werf.yaml Ga naar sjabloonvariabelen door ze waarden toe te wijzen 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 site is over het algemeen hetzelfde voor alle gevallen die we nodig hebben (inclusief het genereren van de rootversie, evenals de versie voor het dev-circuit). Daarom zullen we het naar een apart blok brengen met behulp van de functie define - voor later hergebruik include. We zullen de volgende argumenten doorgeven aan de sjabloon:

  • Version — gegenereerde versie (tagnaam);
  • Channel — de naam van het updatekanaal waarvoor het artefact wordt gegenereerd;
  • Commit — commit hash, als het artefact is gegenereerd voor een review commit;
  • context.

Beschrijving van artefactsjabloon

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

De artefactnaam moet uniek zijn. Dit kunnen we bijvoorbeeld bereiken door de naam van het kanaal toe te voegen (de waarde van de variabele .Channel) als achtervoegsel van een artefactnaam: artifact: doc-{{ .Channel }}. Maar u moet begrijpen dat u bij het importeren van artefacten naar dezelfde namen moet verwijzen.

Bij het beschrijven van een artefact wordt deze werf-functie gebruikt, zoals montage. Montage met servicemap build_dir stelt u in staat om de Jekyll-cache op te slaan tussen pijplijnuitvoeringen, welke versnelt de montage aanzienlijk.

U hebt misschien ook het gebruik van het bestand opgemerkt releases.yml is een YAML-bestand met opgevraagde vrijgavegegevens github.com (artefact verkregen door het uitvoeren van de pijplijn). Het is nodig bij het samenstellen van de site, maar in de context van het artikel is het voor ons interessant omdat het afhangt van de staat het herbouwen van slechts één artefact - een artefact van de site van de rootversie (het is niet nodig in andere artefacten).

Dit wordt geïmplementeerd met behulp van de voorwaardelijke operator if Ga patronen en ontwerpen {{ $Root.Files.Get "releases.yml" | sha256sum }} in stadium stadia. Het werkt als volgt: bij het bouwen van een artefact voor de rootversie (variabel .Channel is gelijk aan root) bestandshash releases.yml beïnvloedt de ondertekening van het hele werkgebied, aangezien het deel uitmaakt van de naam van de Ansible-taak (parameter name). Dus bij het wisselen inhoud het dossier releases.yml het bijbehorende artefact wordt herbouwd.

Besteed ook aandacht aan het werken met een externe repository. In de afbeelding van een artefact uit werf opslagplaats, wordt alleen de directory toegevoegd /docs, en afhankelijk van de doorgegeven parameters worden de gegevens van de direct noodzakelijke tag of review commit toegevoegd.

Om de artefactsjabloon te gebruiken om een ​​artefactbeschrijving van de ingediende versies van kanalen en releases te genereren, organiseren we een lus over de variabele .WerfVersions в werf.yaml:

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

Omdat de lus zal verschillende artefacten genereren (we hopen van wel), je moet rekening houden met het scheidingsteken ertussen - de reeks --- (Voor meer informatie over de syntaxis van het configuratiebestand, zie documentatie). Zoals eerder gedefinieerd, geven we bij het aanroepen van de sjabloon in een lus versieparameters, URL en contextroot door.

Op dezelfde manier, maar zonder een cyclus, noemen we het artefact-sjabloon voor "speciale gevallen": voor de rootversie, evenals de versie van 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 }}

Merk op dat het artefact voor de review commit alleen wordt gebouwd als de variabele is ingesteld .WerfReviewCommit.

Artefacten zijn klaar - het is tijd om te beginnen met importeren!

De uiteindelijke image die bedoeld is om op Kubernetes te draaien, is een reguliere NGINX waaraan een serverconfiguratiebestand is toegevoegd. nginx.conf en statisch door artefacten. Naast het artefact van de rootversie van de site, moeten we de lus over de variabele herhalen .WerfVersions om artefacten van kanaal- en vrijgaveversies te importeren + volg de regel voor naamgeving van artefacten die we eerder hebben aangenomen. Aangezien elk artefact versies van de site voor twee talen opslaat, importeren we ze naar de plaatsen die door de configuratie worden geboden.

Beschrijving van de uiteindelijke werf-doc afbeelding

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

De extra afbeelding, die samen met de hoofdafbeelding op het dev-circuit draait, bevat slechts twee versies van de site: de versie van de review commit en de root-versie van de site (er zijn gemeenschappelijke activa en, als je het je herinnert, gegevens op releases). De extra afbeelding zal dus alleen verschillen van de hoofdafbeelding in de importsectie (en natuurlijk in de naam):

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

Zoals hierboven opgemerkt, wordt het artefact voor de beoordelingscommit alleen gegenereerd als de omgevingsvariabele is ingesteld om te worden uitgevoerd REVIEW_SHA. Het zou mogelijk zijn om de werf-dev-afbeelding helemaal niet te genereren als er geen omgevingsvariabele is REVIEW_SHA, maar om schoonmaak volgens beleid Docker-images in werf werkten voor de werf-dev-image, we laten het alleen bouwen met het artefact van de rootversie (het is toch al gebouwd), om de pijplijnstructuur te vereenvoudigen.

Montage is klaar! Laten we verder gaan met CI / CD en belangrijke nuances.

Pijplijn in GitLab CI en kenmerken van dynamische assemblage

Bij het uitvoeren van de build moeten we de 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 pijplijn vanaf de GitHub-hook.

We zullen de vorming van de benodigde externe gegevens overbrengen naar het Bash-script generate_artifacts, die twee GitLab-pijplijnartefacten zal genereren:

  • файл releases.yml met vrijgavegegevens
  • файл common_envs.shEen met de te exporteren omgevingsvariabelen.

Bestand inhoud generate_artifacts vindt u in onze archieven met voorbeelden. Het verkrijgen van de gegevens zelf is niet het onderwerp van het artikel, maar het bestand common_envs.sh belangrijk voor ons, omdat werf hangt ervan af. 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'

De output van zo'n script kun je bijvoorbeeld gebruiken met de Bash-functie source.

En nu het meest interessante. Om ervoor te zorgen dat zowel de build als de implementatie van de applicatie correct werken, moet u ervoor zorgen dat werf.yaml был hetzelfde minst binnen één pijplijn. Als aan deze voorwaarde niet wordt voldaan, dan zullen de stage signatures die werf berekent tijdens het bouwen en bijvoorbeeld deployment anders zijn. Dit zal resulteren in een implementatiefout, zoals de afbeelding die nodig is voor implementatie zal ontbreken.

Met andere woorden, als tijdens het bouwen van de site-image informatie over releases en versies hetzelfde is, en op het moment van implementatie wordt een nieuwe versie uitgebracht en de omgevingsvariabelen hebben verschillende waarden, dan zal de implementatie mislukken met een foutmelding: na allemaal, het artefact van de nieuwe versie is nog niet gebouwd.

Als generatie werf.yaml afhankelijk is van externe gegevens (bijvoorbeeld een lijst met huidige versies, zoals in ons geval), dan moeten de samenstelling en waarden van dergelijke gegevens binnen de pijplijn worden vastgelegd. Dit is vooral belangrijk als de externe parameters vrij vaak veranderen.

Wij zullen externe gegevens ontvangen en herstellen in de eerste fase van de pijplijn in GitLab (voorbouw) en geef ze verder door in het formulier GitLab CI-artefact. Hiermee kunt u pijplijntaken (bouwen, implementeren, opschonen) starten en opnieuw starten met dezelfde configuratie in werf.yaml.

Stage inhoud voorbouw het dossier .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

Met vaste externe gegevens in een artefact kunt u bouwen en implementeren met behulp van de standaardfasen van de GitLab CI-pijplijn: Build and Deploy. We lanceren de pijplijn zelf door hooks vanuit de werf GitHub-repository (dat wil zeggen, wanneer er wijzigingen worden aangebracht in de GitHub-repository). De gegevens daarvoor kunnen worden gevonden in de eigenschappen van het GitLab-project in de sectie CI / CD-instellingen -> Pipeline-triggersen maak vervolgens de bijbehorende webhook in GitHub (Instellingen -> Webhooks).

De opbouwfase ziet er als volgt uit:

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 voegt twee artefacten toe van de fase naar de bouwfase voorbouw, dus we exporteren voorbereide invoervariabelen met het construct source common_envs.sh. We beginnen in alle gevallen met de bouwfase, behalve bij de geplande lancering van de pijplijn. Volgens het schema zullen we een schoonmaakpijplijn laten lopen - in dit geval hoeft u niet te bouwen.

In de implementatiefase beschrijven we twee taken - afzonderlijk voor implementatie naar productie- en ontwikkelcircuits, met behulp 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 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

De taken verschillen in wezen alleen door de clustercontext te specificeren waarin werf moet worden geïmplementeerd (WERF_KUBE_CONTEXT), en het instellen van de omgevingsvariabelen van het pad (environment.name и environment.url), die vervolgens worden gebruikt in Helm-diagramsjablonen. We zullen de inhoud van de sjablonen niet geven, omdat er is niets interessants voor het onderwerp in kwestie, maar je kunt ze wel vinden in opslagplaatsen voor het artikel.

Laatste greep

Aangezien werf-versies vrij vaak worden uitgebracht, zullen er regelmatig nieuwe afbeeldingen worden gebouwd en zal de Docker Registry voortdurend groeien. Daarom is het absoluut noodzakelijk om het automatisch opschonen van afbeeldingen te configureren volgens het beleid. Het is heel gemakkelijk om dit te doen.

Implementatie vereist:

  • Voeg een reinigingsstap toe aan .gitlab-ci.yml;
  • Periodieke uitvoering van opschoningstaken toevoegen;
  • Stel een omgevingsvariabele in met een schrijftoegangstoken.

Een opschoonstap toevoegen .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

We hebben dit bijna allemaal al een beetje hoger gezien - alleen voor het opschonen moet je eerst inloggen bij de Docker Registry met een token dat rechten heeft om afbeeldingen in de Docker Registry te verwijderen (het automatisch uitgegeven GitLab CI-taaktoken heeft niet zo'n rechten). Het token moet vooraf in GitLab worden ingevoerd en de waarde ervan moet worden opgegeven in de omgevingsvariabele WERF_IMAGES_CLEANUP_PASSWORD project (CI/CD-instellingen -> Variabelen).

Het toevoegen van een schoonmaaktaak met het gewenste schema is gedaan in CI/CD ->
Schema's
.

Alles: het project in de Docker Registry zal niet langer constant groeien uit ongebruikte afbeeldingen.

Aan het einde van het praktische gedeelte wil ik u eraan herinneren dat de volledige vermeldingen van het artikel beschikbaar zijn in Git:

Resultaat

  1. We hebben een logische bouwstructuur: één artefact per versie.
  2. De montage is universeel en vereist geen handmatige wijzigingen wanneer nieuwe versies van werf worden uitgebracht: de documentatie op de site wordt automatisch bijgewerkt.
  3. Er worden twee afbeeldingen samengesteld voor verschillende contouren.
  4. Werkt snel, omdat caching wordt maximaal gebruikt — wanneer een nieuwe versie van werf wordt uitgebracht of een GitHub-hook wordt aangeroepen voor een review-commit — wordt alleen het overeenkomstige artefact met de gewijzigde versie opnieuw opgebouwd.
  5. U hoeft niet na te denken over het verwijderen van ongebruikte afbeeldingen: opschonen door werfbeleid houdt het Docker-register op orde.

Bevindingen

  • Door werf te gebruiken, kan de assemblage snel werken door zowel de assemblage zelf als caching te cachen bij het werken met externe repositories.
  • Door met externe Git-repositories te werken, hoeft u de repository niet elke keer volledig te klonen of het wiel opnieuw uit te vinden met lastige optimalisatielogica. werf gebruikt de cache en doet de kloon slechts één keer en gebruikt dan fetch en alleen wanneer nodig.
  • Mogelijkheid om Go-templates te gebruiken in het configuratiebestand van de build werf.yaml stelt u in staat een samenstelling te beschrijven waarvan het resultaat afhankelijk is van externe gegevens.
  • Het gebruik van mount in werf versnelt het verzamelen van artefacten aanzienlijk - vanwege de cache, die gemeenschappelijk is voor alle pijplijnen.
  • werf maakt het gemakkelijk om opschoning aan te passen, wat vooral geldt voor dynamische builds.

PS

Lees ook op onze blog:

Bron: www.habr.com

Voeg een reactie