Docker պատկերների դինամիկ հավաքում և տեղակայում werf-ով, օգտագործելով տարբերակված փաստաթղթային կայքի օրինակը

Մենք արդեն մեկից ավելի անգամ խոսել ենք մեր GitOps գործիքի մասին վերֆ, և այս անգամ մենք կցանկանայինք կիսվել կայքէջի կառուցման փորձով՝ նախագծի փաստաթղթերի հետ միասին՝ werf.io (ռուսերեն տարբերակը ru.werf.ioՍա սովորական ստատիկ կայք է, բայց դրա հավաքումը հետաքրքիր է նրանով, որ այն կառուցված է դինամիկ թվով արտեֆակտների միջոցով։

Docker պատկերների դինամիկ հավաքում և տեղակայում werf-ով, օգտագործելով տարբերակված փաստաթղթային կայքի օրինակը

Մենք չենք խորանա կայքի կառուցվածքի նրբությունների մեջ՝ բոլոր տարբերակների համար ընդհանուր մենյուի ստեղծում, թողարկումների մասին տեղեկատվություն պարունակող էջ և այլն: Դրա փոխարեն մենք կկենտրոնանանք դինամիկ ասեմբլերի խնդիրների և առանձնահատկությունների վրա, ինչպես նաև մի փոքր կանդրադառնանք դրան ուղեկցող CI/CD գործընթացներին:

Ներածություն. Ինչպես է կայքը գործում

Սկսենք նրանից, որ werf-ի փաստաթղթերը պահվում են դրա կոդի հետ միասին։ Սա որոշակի պահանջներ է դնում մշակման վրա, որոնք, ընդհանուր առմամբ, դուրս են այս հոդվածի շրջանակներից, բայց առնվազն կարող ենք ասել, որ՝

  • Նոր werf ֆունկցիաները չպետք է թողարկվեն առանց փաստաթղթերը թարմացնելու, և, ընդհակառակը, փաստաթղթերում ցանկացած փոփոխություն ենթադրում է werf-ի նոր տարբերակի թողարկում։
  • Նախագիծը բավականին ինտենսիվ զարգացում ունի. նոր տարբերակները կարող են թողարկվել օրական մի քանի անգամ։
  • Կայքը փաստաթղթերի նոր տարբերակով տեղակայելու ցանկացած ձեռքով գործողություն առնվազն ձանձրալի է։
  • Նախագիծը կիրառում է իմաստաբանական մոտեցում տարբերակում, 5 կայունության ալիքներով։ Թողարկման գործընթացը ներառում է տարբերակների հաջորդական անցում ալիքներով՝ կայունության աճի կարգով՝ ալֆայից մինչև ժայռի պես ամուր։
  • Կայքն ունի ռուսալեզու տարբերակ, որը «ապրում և զարգանում է» (այսինքն՝ թարմացվում է) հիմնական (այսինքն՝ անգլերեն) տարբերակին զուգահեռ։

Այս ամբողջ «ներքին գործողությունները» օգտատիրոջից թաքցնելու համար, նրան առաջարկելով մի բան, որը «պարզապես աշխատում է», մենք ստեղծեցինք առանձին գործիք werf-ը տեղադրելու և թարմացնելու համար - Ից multiwerfԴուք պարզապես պետք է նշեք թողարկման համարը և կայունության ալիքը, որը պատրաստ եք օգտագործելու, և multiwerf-ը կստուգի, թե արդյոք ալիքում կա նոր տարբերակ և անհրաժեշտության դեպքում կներբեռնի այն։

Werf-ի վերջին տարբերակները հասանելի են կայքի տարբերակի ընտրության ցանկի յուրաքանչյուր ալիքում: Ըստ լռելյայնի՝ werf.io/փաստաթղթավորում բացվում է վերջին թողարկման ամենակայուն ալիքի տարբերակը՝ այն նաև ինդեքսավորվում է որոնողական համակարգերի կողմից: Ալիքի փաստաթղթերը հասանելի են առանձին հասցեներում (օրինակ՝ werf.io/v1.0-beta/փաստաթղթավորում բետա թողարկման 1.0-ի համար):

Ընդհանուր առմամբ, կայքում հասանելի են հետևյալ տարբերակները.

  1. root (բացվում է լռելյայնորեն),
  2. յուրաքանչյուր թողարկման յուրաքանչյուր ակտիվ թարմացման ալիքի համար (օրինակ՝ werf.io/v1.0-beta).

Կայքի որոշակի տարբերակ ստեղծելու համար, ընդհանուր առմամբ, բավարար է այն կոմպիլացնել՝ օգտագործելով Ջեկիլլ, աշխատում է գրացուցակում /docs werf պահեստի համապատասխան հրամանը (jekyll build), նախկինում անցնելով անհրաժեշտ տարբերակի Git թեգին։

Մնում է միայն ավելացնել, որ.

  • կոմունալ ծրագիրն ինքնին (werf) օգտագործվում է հավաքման համար։
  • CI/CD գործընթացները կառուցված են GitLab CI-ի հիման վրա։
  • և այս ամենը, իհարկե, աշխատում է Kubernetes-ում։

խնդիրները

Հիմա եկեք ձևակերպենք առաջադրանքներ, որոնք հաշվի են առնում նկարագրված բոլոր առանձնահատկությունները.

  1. Ցանկացած թարմացման ալիքում werf տարբերակը փոխելուց հետո կայքում առկա փաստաթղթերը պետք է ավտոմատ կերպով թարմացվեն.
  2. Զարգանալու համար երբեմն պետք է կարողանալ դիտել կայքի նախադիտումները.

Կայքը պետք է վերակազմավորվի համապատասխան Git թեգերից ցանկացած ալիքի տարբերակը փոխելուց հետո, բայց պատկերի հավաքման ընթացքում մենք կստանանք հետևյալ հնարավորությունները.

  • Քանի որ ալիքների տարբերակների ցանկը փոխվում է, անհրաժեշտ է միայն վերակառուցել այն ալիքների փաստաթղթերը, որոնց տարբերակը փոխվել է: Ի վերջո, ամեն ինչ զրոյից վերակառուցելը այդքան էլ լավ չէ:
  • Թողարկումների ալիքների հավաքածուն կարող է փոխվել: Օրինակ՝ որոշ պահի ալիքներում կարող է չլինել ավելի կայուն տարբերակ, քան վաղ մուտքի 1.1 թողարկումը, բայց դրանք կհայտնվեն ժամանակի ընթացքում. այս դեպքում դուք չեք կարող ձեռքով փոխել կառուցվածքը, այնպես չէ՞:

Ստացվում է, որ հավաքումը կախված է արտաքին տվյալների փոփոխությունից.

Իրականացման

Մոտեցման ընտրություն

Այլընտրանքորեն, դուք կարող եք Kubernetes-ում աշխատեցնել յուրաքանչյուր պահանջվող տարբերակը որպես առանձին պոդ: Այս տարբերակը ենթադրում է կլաստերում օբյեկտների ավելի մեծ քանակ, որը կաճի կայուն werf թողարկումների թվի աճի հետ մեկտեղ: Եվ սա, իր հերթին, ենթադրում է ավելի բարդ սպասարկում. յուրաքանչյուր տարբերակ ունի իր սեփական HTTP սերվերը՝ փոքր ծանրաբեռնվածությամբ: Իհարկե, սա նաև ենթադրում է ավելի մեծ ռեսուրսների ծախսեր:

Մենք նույն ճանապարհով գնացինք բոլոր անհրաժեշտ տարբերակների կառուցումները մեկ պատկերումԿայքի բոլոր տարբերակների կազմված ստատիկան գտնվում է NGINX-ի հետ մեկ կոնտեյների մեջ, և համապատասխան տեղակայման տրաֆիկը գալիս է NGINX Ingress-ի միջոցով: Պարզ կառուցվածքը՝ վիճակազուրկ ծրագիր, թույլ է տալիս հեշտությամբ մասշտաբավորել տեղակայումը (կախված բեռից)՝ օգտագործելով Kubernetes-ը:

Ավելի ճշգրիտ լինելու համար մենք կառուցում ենք երկու պատկեր՝ մեկը արտադրական սխեմայի համար, երկրորդը՝ լրացուցիչ՝ մշակողի սխեմայի համար։ Լրացուցիչ պատկերն օգտագործվում է (գործարկվում) միայն մշակողի սխեմայի վրա՝ հիմնականի հետ միասին, և պարունակում է կայքի տարբերակը վերանայման commit-ից, և դրանց միջև երթուղայնացումը կատարվում է Ingress ռեսուրսների միջոցով։

werf vs git կլոն և արտեֆակտներ

Ինչպես նշվեց, փաստաթղթերի որոշակի տարբերակի համար կայքի ստատիկա ստեղծելու համար անհրաժեշտ է կառուցել՝ անցնելով համապատասխան պահոցի թեգին։ Դուք կարող եք նաև դա անել՝ ամեն անգամ կառուցելիս կլոնավորելով պահոցը՝ ընտրելով համապատասխան թեգերը ցանկից։ Սակայն սա բավականին ռեսուրսատար գործողություն է և, բացի այդ, պահանջում է ոչ տրիվիալ հրահանգների գրում... Մեկ այլ լուրջ թերություն այն է, որ այս մոտեցմամբ կառուցման ընթացքում որևէ բան քեշավորելու միջոց չկա։

Այստեղ մեզ օգնության է հասնում werf ծրագիրը՝ իրականացնելով խելացի քեշավորում և թույլ է տալիս օգտագործել արտաքին պահոցներ. werf-ի օգտագործումը պահոցից կոդ ավելացնելու համար զգալիորեն կարագացնի կառուցման գործընթացը, քանի որ werf-ը, ըստ էության, մեկ անգամ կլոնավորում է պահոցը, ապա գործարկում։ միայն fetch անհրաժեշտության դեպքում։ Բացի այդ, պահոցից տվյալներ ավելացնելիս մենք կարող ենք ընտրել միայն անհրաժեշտ գրացուցակները (մեր դեպքում սա գրացուցակն է docs), ինչը զգալիորեն կնվազեցնի ավելացված տվյալների քանակը։

Քանի որ Jekyll-ը գործիք է, որը նախատեսված է ստատիկ ֆայլեր կազմելու համար և անհրաժեշտ չէ վերջնական պատկերում, տրամաբանական կլինի կազմվել արտեֆակտ werf, և վերջնական պատկերում ներմուծել միայն կոմպիլյացիայի արդյունքը.

Մենք գրում ենք werf.yaml

Այսպիսով, մենք որոշեցինք, որ յուրաքանչյուր տարբերակը կհավաքենք առանձին werf արտեֆակտում։ Այնուամենայնիվ, մենք Մենք չգիտենք, թե հավաքման ժամանակ քանի՞ արտեֆակտ կլինի, ուստի մենք չենք կարող գրել ֆիքսված կառուցման կոնֆիգուրացիա (խիստ ասած՝ կարող ենք, բայց դա շատ արդյունավետ չի լինի):

werf-ը թույլ է տալիս օգտագործել Go ձևանմուշներ ձեր կարգավորման ֆայլում (werf.yaml), և սա հնարավորություն է տալիս Ստեղծեք կոնֆիգուրացիա «արագ» կախված արտաքին տվյալներից (ինչ մեզ պետք է!): Մեր դեպքում արտաքին տվյալները տարբերակների և թողարկումների մասին տեղեկատվություն են, որոնց հիման վրա մենք հավաքում ենք անհրաժեշտ քանակությամբ արտեֆակտներ և արդյունքում ստանում ենք երկու պատկեր. werf-doc и werf-dev տարբեր շղթաների վրա մեկնարկելու համար։

Արտաքին տվյալները փոխանցվում են միջավայրի փոփոխականների միջոցով։ Ահա դրանց կազմը՝

  • RELEASES — տող՝ թողարկումների ցանկով և werf-ի համապատասխան ընթացիկ տարբերակով, որպես արժեքների ցանկ՝ բացատներով բաժանված ձևաչափով <НОМЕР_РЕЛИЗА>%<НОМЕР_ВЕРСИИ>. Օրինակ: 1.0%v1.0.4-beta.20
  • CHANNELS — տող՝ ալիքների ցանկով և werf-ի համապատասխան ընթացիկ տարբերակով, արժեքների բացատներով բաժանված ցանկի տեսքով՝ ձևաչափով <КАНАЛ>%<НОМЕР_ВЕРСИИ>. Օրինակ: 1.0-beta%v1.0.4-beta.20 1.0-alpha%v1.0.5-alpha.22
  • ROOT_VERSION — werf-ի թողարկման տարբերակը կայքում լռելյայնորեն ցուցադրելու համար (փաստաթղթերը միշտ չէ, որ անհրաժեշտ է ցուցադրել թողարկման ամենաբարձր համարով): Օրինակ՝ v1.0.4-beta.20
  • REVIEW_SHA — վերանայման կոմիտի հեշը, որից պետք է կառուցվի թեստային սխեմայի տարբերակը։

Այս փոփոխականները կտեղադրվեն GitLab CI խողովակաշարում, և թե ինչպես, ստորև նկարագրված է։

Նախևառաջ, հարմարության համար, եկեք սահմանենք werf.yaml Անցեք ձևանմուշի փոփոխականներին՝ նրանց շրջակա միջավայրի փոփոխականներից արժեքներ նշանակելով.

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

Կայքի ստատիկ տարբերակի կոմպիլյացիայի համար նախատեսված արտեֆակտի նկարագրությունը, ընդհանուր առմամբ, նույնն է մեզ անհրաժեշտ բոլոր դեպքերի համար (ներառյալ արմատային տարբերակի ստեղծումը, ինչպես նաև dev-contour-ի տարբերակը): Հետևաբար, մենք այն կտեղափոխենք առանձին բլոկ՝ օգտագործելով ֆունկցիան։ define — հետագա վերօգտագործման համար՝ օգնությամբ includeՄենք կփոխանցենք հետևյալ արգումենտները ձևանմուշին.

  • Version — ստեղծված տարբերակը (պիտակի անվանումը);
  • Channel — այն թարմացման ալիքի անվանումը, որի համար ստեղծվում է արտեֆակտը։
  • Commit — commit հեշ, եթե արտեֆակտը գեներացվում է review commit-ի համար։
  • համատեքստ

Արտեֆակտի ձևանմուշի նկարագրությունը

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

Արտեֆակտի անունը պետք է լինի եզակի։ Մենք կարող ենք դրան հասնել, օրինակ, ավելացնելով ալիքի անունը (փոփոխական արժեքը) .Channel) որպես արտեֆակտի անվանման վերջածանց՝ artifact: doc-{{ .Channel }}Բայց դուք պետք է հասկանաք, որ արտեֆակտներից ներմուծելիս պետք է հղում կատարեք նույն անուններին։

Արտեֆակտը նկարագրելիս օգտագործվում է հետևյալ werf հատկանիշը. մոնտաժ. Մոնտաժվում է նշված ծառայության գրացուցակով build_dir թույլ է տալիս պահպանել Jekyll քեշը խողովակաշարերի միջև ընկած ժամանակահատվածում, որը զգալիորեն արագացնում է վերամոնտաժը.

Դուք կարող եք նաև նկատել ֆայլի օգտագործումը releases.yml — YAML ֆայլ է, որից հարցված թողարկման տվյալներով։ Github.com (արտեֆակտ, որը ստացվել է խողովակաշարի գործարկման ժամանակ): Այն անհրաժեշտ է կայքի կազմման ժամանակ, բայց հոդվածի համատեքստում այն ​​մեզ համար հետաքրքիր է, քանի որ դրա վիճակը կախված է միայն մեկ արտեֆակտի վերամոնտաժում — կայքի արմատային տարբերակի արտեֆակտ (այն անհրաժեշտ չէ այլ արտեֆակտներում):

Սա իրականացվում է պայմանական օպերատորի միջոցով։ if Go ձևանմուշներ և կոնստրուկտներ {{ $Root.Files.Get "releases.yml" | sha256sum }} փուլում փուլերԱյն աշխատում է այսպես. արմատային տարբերակի համար արտեֆակտ կառուցելիս (փոփոխական .Channel հավասար է root) ֆայլի հեշ releases.yml ազդում է ամբողջ փուլի ստորագրության վրա, քանի որ այն Ansible առաջադրանքի անվանման բաղադրիչ է (պարամետր nameԱյսպիսով, փոփոխելիս պարունակություն ֆայլը releases.yml համապատասխան արտեֆակտը կվերահավաքվի։

Խնդրում ենք նաև ուշադրություն դարձնել արտաքին պահոցի հետ աշխատելուն։ Արտեֆակտի պատկերում werf պահոցներ, ավելացվում է միայն գրացուցակը /docs, և փոխանցված պարամետրերից կախված՝ անհրաժեշտ թեգի կամ վերանայման կոդի տվյալները անմիջապես ավելացվում են։

Արտեֆակտի ձևանմուշն օգտագործելու համար՝ փոխանցված ալիքի տարբերակների և թողարկումների արտեֆակտի նկարագրություն ստեղծելու համար, մենք ցիկլը կազմակերպում ենք փոփոխականի միջոցով։ .WerfVersions в werf.yaml:

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

Քանի որ ցիկլը կստեղծի մի քանի արտեֆակտներ (հուսով ենք՝ այո), անհրաժեշտ է հաշվի առնել դրանց միջև ընկած բաժանարարը՝ հաջորդականությունը։ --- (կարգավորման ֆայլի սինտաքսի վերաբերյալ լրացուցիչ տեղեկությունների համար տե՛ս փաստաթղթավորում)։ Ինչպես ավելի վաղ սահմանեցինք, ցիկլում շաբլոնը կանչելիս մենք փոխանցում ենք տարբերակի պարամետրերը, URL-ը և root համատեքստը։

Նմանապես, բայց առանց ցիկլի, մենք արտեֆակտի ձևանմուշը կանչում ենք «հատուկ դեպքերի» համար՝ root տարբերակի, ինչպես նաև 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 }}

Նկատի ունեցեք, որ review commit-ի արտեֆակտը կկառուցվի միայն այն դեպքում, եթե փոփոխականը սահմանված է։ .WerfReviewCommit.

Արտեֆակտները պատրաստ են՝ ժամանակն է սկսել ներմուծումը։

Kubernetes-ի վրա աշխատելու համար նախատեսված վերջնական պատկերը սովորական NGINX է, որին ավելացված է սերվերի կարգավորման ֆայլ։ nginx.conf և ստատիկան արտեֆակտներից։ Բացի կայքի արմատային տարբերակի արտեֆակտից, մենք պետք է կրկնենք ցիկլը փոփոխականով։ .WerfVersions ալիքի և թողարկման տարբերակների արտեֆակտներ ներմուծելու համար + հետևեք արտեֆակտների անվանակոչման կանոնին, որը մենք ընդունել ենք ավելի վաղ: Քանի որ յուրաքանչյուր արտեֆակտ պահպանում է կայքի տարբերակները երկու լեզուների համար, մենք դրանք ներմուծում ենք կարգավորման կողմից տրամադրված վայրեր:

Վերջնական պատկերի նկարագրությունը 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 -}}

Լրացուցիչ պատկերը, որը գործարկվում է մշակողի սխեմայի վրա հիմնականի հետ միասին, պարունակում է կայքի միայն երկու տարբերակ՝ վերանայման կոմիտից ստացված տարբերակը և կայքի root տարբերակը (այն պարունակում է ընդհանուր ակտիվներ և, եթե հիշում եք, թողարկման տվյալներ): Այսպիսով, լրացուցիչ պատկերը հիմնականից կտարբերվի միայն ներմուծման բաժնում (և, իհարկե, անվանումով):

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

Ինչպես նշվեց վերևում, review commit-ի համար արտեֆակտը կստեղծվի միայն set environment փոփոխականը գործարկելիս։ REVIEW_SHAՀնարավոր կլիներ ընդհանրապես չստեղծել werf-dev պատկերը, եթե միջավայրի փոփոխական չկա։ REVIEW_SHA, բայց որպեսզի մաքրում ըստ քաղաքականության Werf-ի Docker պատկերները աշխատեցին werf-dev պատկերի համար, մենք այն կթողնենք կառուցել միայն root տարբերակի արտեֆակտով (այն արդեն կառուցված է), որպեսզի պարզեցնենք խողովակաշարի կառուցվածքը։

Կառուցումը պատրաստ է։ Եկեք անցնենք CI/CD-ին և կարևոր նրբերանգներին։

GitLab CI-ում խողովակաշարի կառուցումը և դինամիկ կառուցման առանձնահատկությունները

Կառուցումը գործարկելիս մենք պետք է սահմանենք միջավայրի փոփոխականները, որոնք օգտագործվում են werf.yamlՍա չի վերաբերում REVIEW_SHA փոփոխականին, որը մենք կսահմանենք GitHub-ի կեռիկից խողովակաշարը կանչելիս։

Մենք անհրաժեշտ արտաքին տվյալների ձևավորումը կտեղափոխենք Bash սկրիպտի վրա։ generate_artifacts, որը կստեղծի GitLab խողովակաշարի երկու արտեֆակտ՝

  • ֆայլը releases.yml թողարկման տվյալների հետ,
  • ֆայլը common_envs.sh, որը պարունակում է արտահանման համար նախատեսված միջավայրի փոփոխականներ։

Ֆայլի բովանդակություն generate_artifacts դուք կգտնեք մեր մեջ պահեստարաններ՝ օրինակներովՀոդվածի թեման տվյալների հավաքագրումը չէ, այլ ֆայլը։ common_envs.sh կարևոր է մեզ համար, քանի որ werf-ի գործողությունը կախված է դրանից։ Դրա բովանդակության օրինակ՝

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'

Նման սկրիպտի արդյունքը կարող է օգտագործվել, օրինակ, Bash ֆունկցիայի միջոցով։ source.

Հիմա գալիս է ամենահետաքրքիր մասը։ Որպեսզի ծրագրի հավաքումը և տեղակայումը ճիշտ աշխատեն, անհրաժեշտ է համոզվել, որ werf.yaml էր նույնը գոնե մեկ խողովակաշարի ներսումԵթե ​​այս պայմանը չի բավարարվում, ապա werf-ի կողմից հավաքման և, օրինակ, տեղակայման ընթացքում հաշվարկվող փուլի ստորագրությունները տարբեր կլինեն։ Սա կհանգեցնի տեղակայման սխալի, քանի որ տեղակայման համար անհրաժեշտ պատկերը բացակայելու է։

Այլ կերպ ասած, եթե կայքի պատկերի հավաքման ժամանակ թողարկումների և տարբերակների մասին տեղեկատվությունը նույնն է, և տեղակայման պահին թողարկվում է նոր տարբերակ, և միջավայրի փոփոխականները ունեն տարբեր արժեքներ, ապա տեղակայումը կավարտվի սխալով. չէ՞ որ նոր տարբերակի արտեֆակտը դեռ չի հավաքվել։

Եթե ​​սերունդը werf.yaml կախված է արտաքին տվյալներից (օրինակ՝ ներկայիս տարբերակների ցանկից, ինչպես մեր դեպքում), ապա նման տվյալների կազմը և արժեքները պետք է գրանցվեն խողովակաշարի ներսում։ Սա հատկապես կարևոր է, եթե արտաքին պարամետրերը բավականին հաճախ են փոխվում։

Մենք կանենք արտաքին տվյալների ստացում և գրանցում GitLab-ում խողովակաշարի առաջին փուլում (Նախնական կառուցում) և դրանք հետագայում փոխանցել ձևով GitLab CI արտեֆակտներՍա թույլ կտա ձեզ գործարկել և վերագործարկել խողովակաշարի առաջադրանքները (կառուցում, տեղակայում, մաքրում) նույն կոնֆիգուրացիայով werf.yaml.

Բեմի բովանդակությունը Նախնական կառուցում ֆայլը .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

Արտեֆակտում արտաքին տվյալները ֆիքսելով՝ կարող եք կառուցել և տեղակայել՝ օգտագործելով GitLab CI խողովակաշարի ստանդարտ փուլերը՝ Կառուցել և տեղակայել: Մենք խողովակաշարը գործարկում ենք werf GitHub պահոցից կեռիկների միջոցով (այսինքն՝ երբ GitHub-ի պահոցում փոփոխություններ են լինում): Դրանց տվյալները կարելի է վերցնել GitLab նախագծի հատկություններից՝ բաժնում: CI/CD կարգավորումներ -> Խողովակաշարի ակտիվացուցիչներ, ապա ստեղծեք համապատասխան Webhook-ը GitHub-ում (Կարգավորումներ -> Վեբհուքեր).

Կառուցման փուլը կունենա հետևյալ տեսքը.

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-ը բեմից երկու արտեֆակտ կավելացնի կառուցման փուլին։ Նախնական կառուցում, ուստի մենք արտահանում ենք փոփոխականներ պատրաստված մուտքային տվյալներով՝ օգտագործելով կառուցվածքը source common_envs.shՄենք մեկնարկում ենք կառուցման փուլը բոլոր դեպքերում, բացառությամբ խողովակաշարի ժամանակացույցով մեկնարկի։ Ժամանակացույցով մենք կմեկնարկենք խողովակաշարը մաքրման համար. այս դեպքում կառուցման անհրաժեշտություն չկա։

Տեղակայման փուլում մենք կնկարագրենք երկու առաջադրանք՝ առանձին-առանձին արտադրական և մշակողական սխեմաներում տեղակայման համար՝ օգտագործելով 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

Առաջադրանքները էապես տարբերվում են միայն այն կլաստերի համատեքստի նշմամբ, որի մեջ werf-ը պետք է կատարի տեղակայումը (WERF_KUBE_CONTEXT), և կոնտուրային միջավայրի փոփոխականների սահմանումը (environment.name и environment.url), որոնք այնուհետև օգտագործվում են Հելմի դիագրամի ձևանմուշներում: Մենք չենք տրամադրի ձևանմուշների բովանդակությունը, քանի որ քննարկվող թեմայի համար հետաքրքիր ոչինչ չկա, բայց դուք կարող եք գտնել դրանք հոդվածի պահոցներ.

Վերջնական հպում

Քանի որ werf տարբերակները բավականին հաճախ են թողարկվում, նոր պատկերներ հաճախ կկառուցվեն, իսկ Docker Registry-ն անընդհատ կմեծանա։ Հետևաբար, անհրաժեշտ է կարգավորել պատկերների ավտոմատ մաքրումը՝ օգտագործելով քաղաքականություններ։ Դա շատ հեշտ է անել։

Իրականացման համար ձեզ անհրաժեշտ կլինի.

  • Ավելացրեք մաքրման քայլ .gitlab-ci.yml;
  • Ավելացրեք մաքրման առաջադրանքի պարբերական կատարումը։
  • Կարգավորեք միջավայրի փոփոխական՝ գրելու մուտքի տոկենով։

Ավելացրեք մաքրման փուլ .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

Մենք արդեն տեսել ենք այս գրեթե ամենը վերևում՝ միայն այն մաքրելու համար նախ պետք է մուտք գործել Docker Registry՝ օգտագործելով Docker Registry-ում պատկերներ ջնջելու իրավունք ունեցող տոկեն (GitLab CI առաջադրանքի ավտոմատ կերպով տրված տոկենը նման իրավունքներ չունի): Տոկենը պետք է նախապես ստեղծվի GitLab-ում, և դրա արժեքը պետք է նշված լինի միջավայրի փոփոխականում: WERF_IMAGES_CLEANUP_PASSWORD ծրագրի նախագիծը (CI/CD կարգավորումներ -> Փոփոխականներ).

Մաքրման առաջադրանքի ավելացումը պահանջվող ժամանակացույցով կատարվում է CI/CD ->
Ժանրեր
.

Այսքանը. ձեր Docker Registry նախագիծը այլևս անընդհատ չի աճի չօգտագործված պատկերներից։

Գործնական մասի ավարտին, կցանկանայի հիշեցնել, որ հոդվածի ամբողջական ցանկերը հասանելի են գնալ:

Արդյունք

  1. Մենք ստացանք տրամաբանական հավաքման կառուցվածք՝ մեկ արտեֆակտ յուրաքանչյուր տարբերակի համար։
  2. Հավաքածուն ունիվերսալ է և չի պահանջում ձեռքով փոփոխություններ werf-ի նոր տարբերակների թողարկման ժամանակ. կայքում առկա փաստաթղթերը թարմացվում են ավտոմատ կերպով։
  3. Երկու պատկերներ հավաքվում են տարբեր ուրվագծերի համար։
  4. Այն արագ է աշխատում, քանի որ քեշավորումն օգտագործվում է առավելագույն չափով. երբ թողարկվում է werf-ի նոր տարբերակ կամ GitHub hook-ը կանչվում է վերանայման կոմիտի համար, վերակառուցվում է միայն փոփոխված տարբերակով համապատասխան արտեֆակտը։
  5. Անհրաժեշտ չէ անհանգստանալ չօգտագործված պատկերները ջնջելու համար. werf քաղաքականության վրա հիմնված մաքրումը կպահպանի ձեր Docker գրանցամատյանը կոկիկ։

Արդյունքները

  • Werf-ի օգտագործումը թույլ է տալիս կառուցվածքին արագ աշխատել՝ ինչպես կառուցվածքի, այնպես էլ արտաքին պահոցների հետ աշխատելիս քեշավորման շնորհիվ։
  • Արտաքին Git պահոցների հետ աշխատելը վերացնում է պահոցը ամեն անգամ ամբողջությամբ կլոնավորելու կամ անիվը վերափոխելու անհրաժեշտությունը բարդ օպտիմալացման տրամաբանությամբ: werf-ը օգտագործում է քեշ և կլոնավորում է միայն մեկ անգամ, ապա օգտագործում է fetch և միայն անհրաժեշտության դեպքում։
  • Go ձևանմուշներ օգտագործելու հնարավորություն կառուցման կոնֆիգուրացիայի ֆայլում werf.yaml թույլ է տալիս նկարագրել մի ասամբլեա, որի արդյունքը կախված է արտաքին տվյալներից։
  • Werf-ում մոնտաժի օգտագործումը զգալիորեն արագացնում է արտեֆակտների հավաքագրումը՝ քեշի շնորհիվ, որը տարածված է բոլոր խողովակաշարերի համար։
  • werf-ը հեշտացնում է մաքրման կարգաբերումը, ինչը հատկապես կարևոր է դինամիկ կառուցվածքների համար։

PS

Կարդացեք նաև մեր բլոգում.

Source: www.habr.com

Գնեք հուսալի հոստինգ DDoS պաշտպանությամբ կայքերի, VPS VDS սերվերների համար 🔥 Գնեք հուսալի կայքերի հոսթինգ՝ DDoS պաշտպանությամբ, VPS VDS սերվերներով | ProHoster