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

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

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

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

Ներածություն. ինչպես է աշխատում կայքը

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

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

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

Կայքի տարբերակների ընտրության ընտրացանկում, werf-ի վերջին տարբերակները հասանելի են յուրաքանչյուր ալիքում: Լռելյայն, ըստ հասցեի werf.io/documentation Բացվում է վերջին թողարկման ամենակայուն ալիքի տարբերակը, այն նաև ինդեքսավորվում է որոնման համակարգերի կողմից: Ալիքի համար փաստաթղթերը հասանելի են առանձին հասցեներով (օրինակ՝ werf.io/v1.0-beta/documentation 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-ը:

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

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

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

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

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

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

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

werf-ը թույլ է տալիս օգտագործել Գնալ կաղապարներ ձեր կազմաձևման ֆայլում (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") }}

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

  • Version - գեներացված տարբերակ (պիտակի անունը);
  • Channel — թարմացման ալիքի անվանումը, որի համար ստեղծվել է արտեֆակտը.
  • 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 Գնացեք կաղապարներ և ձևավորումներ {{ $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-ը և արմատային համատեքստը:

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

Խնդրում ենք նկատի ունենալ, որ վերանայման հանձնառության արտեֆակտը կստեղծվի միայն այն դեպքում, եթե փոփոխականը սահմանված է .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 -}}

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

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_SHA. Հնարավոր կլիներ ընդհանրապես չգեներացնել werf-dev պատկերը, եթե շրջակա միջավայրի փոփոխական չկա REVIEW_SHA, բայց որպեսզի մաքրում ըստ քաղաքականության Դոկերի պատկերները werf-ում աշխատել են werf-dev պատկերի համար, մենք այն կթողնենք միայն արմատային տարբերակի արտեֆակտով (այն ամեն դեպքում արդեն կառուցված է), խողովակաշարի կառուցվածքը պարզեցնելու համար։

Ժողովը պատրաստ է! Անցնենք CI/CD-ին և կարևոր նրբերանգներին:

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

Build-ը գործարկելիս մենք պետք է սահմանենք միջավայրի փոփոխականները, որոնք օգտագործվում են 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 խողովակաշարի ստանդարտ փուլերը՝ Build և Deploy: Մենք գործարկում ենք խողովակաշարն ինքնին` օգտագործելով կեռիկներ 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), որոնք այնուհետև օգտագործվում են Helm աղյուսակի ձևանմուշներում: Մենք չենք տրամադրի կաղապարների բովանդակությունը, քանի որ... խնդրո առարկա թեմայի համար այնտեղ հետաքրքիր բան չկա, բայց դուք կարող եք գտնել դրանք հոդվածների համար նախատեսված պահեստներ.

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

Քանի որ 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 կեռիկը կանչվում է վերանայման հանձնման համար, վերակառուցվում է միայն փոփոխված տարբերակով համապատասխան արտեֆակտը:
  5. Կարիք չկա մտածել չօգտագործված պատկերները ջնջելու մասին. «Werf»-ի կանոնների համաձայն մաքրումը կպահի Docker Registry-ը:

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

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

PS

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

Source: www.habr.com

Добавить комментарий