3-way merge në werf: deponim në Kubernetes me Helm «në steroide»

Ndodhi ajo që ne (dhe jo vetëm ne) prisnim prej një kohe të gjatë: werf, utilitarja jonë Open Source për ndërtimin e aplikacioneve dhe shpërndarjen e tyre në Kubernetes, tani mbështet aplikimin e ndryshimeve përmes patch-eve 3-way-merge! Përveç kësaj, është bërë e mundur adoptimi i burimeve ekzistuese K8s në lëshimet Helm pa rinovimin e këtyre burimeve.

3-way merge në werf: deponim në Kubernetes me Helm «në steroide»

NĂ«se e themi shkurt, vendosim WERF_THREE_WAY_MERGE=enabled — marrim deponim «si nĂ« kubectl apply», i pajtueshĂ«m me instalimet ekzistuese nĂ« Helm 2 dhe ndoshta edhe mĂ« shumĂ«.

Por le të fillojmë me teorinë: çfarë janë patch-et 3-way-merge, si arritën njerëzit në qasjen e gjenerimit të tyre dhe pse janë të rëndësishme në proceset CI/CD me infrastrukturën e bazuar në Kubernetes? Pas kësaj - do të shohim se çfarë paraqet 3-way-merge në werf, cilat modet përdoren si parazgjedhje dhe si të menaxhohen ato.

ÇfarĂ« Ă«shtĂ« patch 3-way-merge?

Kështu, fillojmë me detyrën e nxjerrjes së burimeve të përshkruara në manifestet YAML, në Kubernetes.

Për të punuar me burimet, API i Kubernetes ofron operacionet themelore: create, patch, replace dhe delete. Supozohet se me to duhet të ndërtohet një nxjerrje e vazhdueshme e burimeve në klaster. Si?

Komandat imperativ kubectl

Qasja e parĂ« pĂ«r menaxhimin e objekteve nĂ« Kubernetes — pĂ«rdorimi i komandave imperativ kubectl pĂ«r tĂ« krijuar, ndryshuar dhe fshirĂ« kĂ«to objekte. Thjesht thĂ«nĂ«:

  • nĂ«pĂ«rmjet komandĂ«s. kubectl run mund tĂ« nisĂ« njĂ« Deployment ose Job:
    kubectl run --generator=deployment/apps.v1 EMRI_I_DEPLOYMENTIT --image=IMAZHI
  • nĂ«pĂ«rmjet komandĂ«s. kubectl scale — ndryshoni numrin e replikave:
    kubectl scale --replicas=3 deployment/mysql
  • etj.

Kjo qasje mund të duket e lehtë në shikim të parë. Megjithatë, ka probleme:

  1. ËshtĂ« e vĂ«shtirĂ« tĂ« automatizohet.
  2. Si të pasqyrohet konfigurimi në Git? Si të bëhet rishikimi i ndryshimeve që ndodhin me klasterin?
  3. Si të sigurohet riprodhueshmëria e konfigurimit gjatë rinisjes?
  4. 


ËshtĂ« e qartĂ« se kjo qasje nuk pĂ«rputhet mirĂ« me ruajtjen e sĂ« njĂ«jtĂ«s pĂ«rkrah kodit tĂ« aplikacionit dhe infrastrukturĂ«s si kod (IaC; ose madje GitOps si njĂ« variant mĂ« modern, qĂ« po fiton popullaritet nĂ« ekosistemin Kubernetes). Prandaj, kĂ«to komanda nuk patĂ«n zhvillim tĂ« mĂ«tejshĂ«m nĂ« kubectl.

Operacionet create, get, replace dhe delete

Me krijimin e parë gjerësisht është e thjeshtë: dërgojmë manifestin në operacionin në kube api dhe burimi është krijuar. Paraqitja YAML e manifestit mund të ruhet në Git, dhe për krijim mund të përdoret komanda create kubectl create -f manifest.yaml fshirja.

D po ashtu është e thjeshtë: vendosim të njëjtin manifest.yaml manifest.yaml nga Git në ekip kubectl delete -f manifest.yaml.

Operación ndërrim lejon zëvendësimin e plotë të konfiguracionit të burimit me një të ri, pa krijuar përsëri burimin. Kjo do të thotë se para se të bëni ndryshime në burim, është logjike të kërkoni versionin aktual përmes veprimit merr, ta ndryshoni atë dhe ta përditësoni përmes veprimit ndërrim. Në kube apiserver është e integruar ndërprerja optimiste dhe, nëse objekti është ndryshuar pas veprimit merr veprimi ndërrim nuk do të kalojë.

PĂ«r tĂ« ruajtur konfigurimin nĂ« Git dhe pĂ«r ta pĂ«rditĂ«suar me anĂ« tĂ« ndĂ«rrimit, duhet tĂ« bĂ«ni veprimin merr, tĂ« bashkoni konfigurimin nga Git me atĂ« qĂ« kemi marrĂ«, dhe tĂ« kryeni ndĂ«rrim. Si standard, kubectl lejon vetĂ«m pĂ«rdorimin e komandĂ«s kubectl replace -f manifest.yamlindex manifest.yaml — njĂ« manifest i pĂ«rgatitur plotĂ«sisht (nĂ« rastin tonĂ« — i bashkuar) qĂ« duhet tĂ« vendoset. KĂ«shtu, pĂ«rdoruesi duhet tĂ« realizojĂ« bashkimin e manifeve, dhe kjo Ă«shtĂ« njĂ« çështje jo triviale


Po ashtu, Ă«shtĂ« e rĂ«ndĂ«sishme tĂ« theksohet se megjithatĂ« manifest.yaml nĂ«se ruhet nĂ« Git, nuk mund tĂ« dimĂ« paraprakisht nĂ«se duhet tĂ« krijohet objekti ose ta pĂ«rditĂ«sojmĂ« — kjo duhet ta bĂ«jĂ« softi i pĂ«rdoruesit.

Pra, në përfundim: mund të ndërtojmë një shpërndarje të vazhdueshme vetëm me anë të krijimit, ndërrimit dhe fshirjes, duke siguruar ruajtjen e konfiguracionit të infrastrukturës në Git së bashku me kodin dhe një CI/CD të përshtatshëm?

Në thelb, mundemi
 Për këtë do të kërkohet të realizohet veprimi i bashkimit të manifeve dhe një lloj mbështetjeje që:

  • verifikon nĂ«se objekti Ă«shtĂ« nĂ« klaster,
  • krijon burimin fillestar,
  • e pĂ«rditĂ«son ose e fshin.

Kur pĂ«rditĂ«sohet, duhet pasur parasysh se burimi mund tĂ« ketĂ« ndryshuar qĂ« nga hera e fundit merr dhe tĂ« trajtojĂ« automatikisht rastin e ndĂ«rprerjes optimiste — tĂ« bĂ«jĂ« pĂ«rpjekje tĂ« pĂ«rsĂ«ritura pĂ«r pĂ«rditĂ«simin.

Megjithatë, pse të shpikim biçikletën, kur kube-apiserver ofron një mënyrë tjetër për të përditësuar burimet: veprimin patch, i cili heq një pjesë të problemeve të përshkruara nga përdoruesi?

Patch

Ja erdhëm te patch-at.

Patch-at janë mënyra kryesore për të aplikuar ndryshime në objektet ekzistuese në Kubernetes. Veprimi patch punon në atë mënyrë që:

  • pĂ«rdoruesi i kube-apiserver kĂ«rkon tĂ« dĂ«rgojĂ« njĂ« patch nĂ« format JSON dhe tĂ« specifikojĂ« objektin,
  • dhe apiserver do ta kuptojĂ« vetĂ« gjendjen aktuale tĂ« objektit dhe do ta sjellĂ« atĂ« nĂ« formĂ«n e kĂ«rkuar.

Ndërprerja optimiste në këtë rast nuk është e nevojshme. Kjo operacion është më deklarative në krahasim me ndërrimin, ndonëse fillimisht mund të duket ndryshe.

Kështu:

  • me anĂ« tĂ« veprimit create ne krijojmĂ« objektin sipas manifestit nga Git’i,
  • nĂ«pĂ«rmjet fshij — e fshimĂ«, nĂ«se objekti nuk Ă«shtĂ« mĂ« i nevojshĂ«m,
  • nĂ«pĂ«rmjet patch — ne pĂ«rdorim objektin, duke e sjellĂ« atĂ« nĂ« formĂ«n e pĂ«rshkruar nĂ« Git.

Megjithatë, për ta bërë këtë, është e nevojshme të krijohet patch-i i duhur!

Si funksionojnë patch-et në Helm 2: 2-way-merge

Në instalimin e parë të lëshimit, Helm kryen operacionin create për burimet e chart-it.

Duke përditësuar lëshimin e Helm, për secilën burim:

  • llogarit patch-in midis versionit tĂ« burimit nga chart-i i kaluar dhe versionit aktual tĂ« chart-it,
  • e aplikon kĂ«tĂ« patch.

Këtë patch do ta quajmë 2-way-merge patch, sepse në krijimin e tij përfshihen 2 manifestime:

  • manifesti i burimit nga lĂ«shimi i kaluar,
  • manifesti i burimit nga burimi aktual.

Kur fshijmë, operacioni fshij në kube apiserver thirret për burimet që janë shpallur në lëshimin e kaluar, por nuk janë shpallur në atë aktual.

Qasja me 2-way-merge patch ka një problem: ajo çon në disankronizimin e gjendjes reale të burimit në klaster dhe manifestin në Git..

Ilustrimi i problemit me një shembull

  • NĂ« Git, nĂ« chart ruhet njĂ« manifest, ku fusha image nĂ« Deployment ka vlerĂ«n ubuntu:18.04.
  • PĂ«rdoruesi pĂ«rmes kubectl edit ka ndryshuar vlerĂ«n e kĂ«saj fushe nĂ« ubuntu:19.04.
  • Kur ripĂ«rditĂ«sohet chart-i i Helm nuk gjeneron patch, sepse fusha image nĂ« versionin e kaluar tĂ« lĂ«shimit dhe nĂ« chart-in aktual janĂ« tĂ« njĂ«jta.
  • Pas ripĂ«rditĂ«simit image mbetet ubuntu:19.04, ndonĂ«se nĂ« chart shkruhet ubuntu:18.04.

Kemi marrë disankronizim dhe humbëm deklarativitetin.

ÇfarĂ« Ă«shtĂ« njĂ« burim i sinkronizuar?

Në përgjithësi, përputhje të plotë e manifestit të burimit në klasterin në funksion dhe manifestit nga Git nuk mund të arrihet. Sepse në manifestin real mund të ketë annotime/etiketa shërbimi, konteinerë të shtuar dhe të tjerë të dhëna që përfshihen dhe hiqen nga burimi dinamkisht nga disa kontrolerë. Ne nuk mund dhe nuk duam t'i mbajmë këto të dhëna në Git. Megjithatë, ne duam që gjatë lëshimit fushat që ne i kemi caktuar qartë në Git të pranoni vlerat përkatëse.

Kështu rezulton një rregull i përgjithshëm për burimin e sinkronizuar: gjatë lëshimit të burimit mund të ndryshohen ose fshihen vetëm ato fusha që janë qartë të shkruara në manifestin nga Git (ose janë shkruar në versionin e kaluar dhe tani janë fshirë).

3-way-merge patch

Ideja kryesore 3-way-merge patch: gjenerojmë patch midis versionit më të fundit të aplikuar të manifestit nga Git dhe versionit të synuar të manifestit nga Git duke marrë parasysh versionin aktual të manifestit nga klasteri në funksion. Patch-i përfundimtar duhet të përputhet me rregullin e burimit të sinkronizuar:

  • Fushat e reja, tĂ« shtuara nĂ« versionin e synuar, shtohen me anĂ« tĂ« njĂ« patchi;
  • Fushat ekzistuese nĂ« versionin mĂ« tĂ« fundit tĂ« aplikuar dhe qĂ« nuk ekzistojnĂ« nĂ« atĂ« tĂ« synuar — zerohet me anĂ« tĂ« njĂ« patchi;
  • Fushat nĂ« versionin aktual tĂ« objektit, tĂ« cilat ndryshojnĂ« nga versioni i synuar i manifestit, — pĂ«rditĂ«sohen me anĂ« tĂ« njĂ« patchi.

Kështu krijohen patch-et kubectl apply:

  • Versioni mĂ« i fundit i aplikuar i manifestit ruhet nĂ« annotimin e vetĂ« objektit,
  • i synuari — merret nga skedari YAML i caktuar,
  • aktuali — nga klasteri nĂ« punĂ«.

Tani që e kuptuam teorinë, le të flasim për atë që kemi bërë në werf.

Aplikimi i ndryshimeve në werf

Më parë werf, si dhe Helm 2, përdorte patch-e me 2-way-merge.

Repair patch

PĂ«r tĂ« kaluar nĂ« llojin e ri tĂ« patch-eve — 3-way-merge, hapi i parĂ« ishte tĂ« prezantonim tĂ« ashtuquajturat repair-patch-e.

Gjatë deploy-it përdoret patch-i standard 2-way-merge, por werf gjeneron gjithashtu një patch të tillë, i cili do të sinkronizonte gjendjen aktuale të burimeve me atë që shkruhet në Git (krijohet një patch i tillë duke përdorur të njëjtat rregulla për burimet e sinkronizuara, të përshkruara më sipër).

Në rastin e një rrethane të sinkronizimit, në fund të deploy-it, përdoruesi merr një WARNIM me mesazhin përkatës dhe patch-in që duhet të aplikojë, për ta sjellë burimin në një pamje të sinkronizuar. Gjithashtu ky patch regjistrohet në një annotim të veçantë werf.io/repair-patch. Supozohet se përdoruesi në mënyrë manuale vetë do ta aplikojë këtë patch: werf nuk do ta aplikojë atë për parim.

Gjenerimi i repair-patch-eve është një masë përkohore, e cila lejon të testojmë në praktikë krijimin e patch-eve sipas parimit 3-way-merge, por të mos aplikojmë automatikisht këto patch-e. Tani për tani, ky modalitet pune është aktivizuar si parazgjedhje.

Patch 3-way-merge vetëm për lëshimet e reja

Duke filluar nga 1 dhjetori 2019, versionet beta dhe alpha të werf fillojnë si parazgjedhje të përdorin patch-e të plota 3-way-merge për aplikimin e ndryshimeve vetëm për lëshimet e reja Helm, të shpërndara përmes werf. Të gjitha lëshimet ekzistuese do të vazhdojnë të përdorin qasjen 2-way-merge + repair-patch-e.

Ky modalitet pune mund të aktivizohet në mënyrë eksplicite me konfigurimin WERF_THREE_WAY_MERGE_MODE=onlyNewReleases tani.

ShĂ«nim: karakteristika u shfaq nĂ« werf pĂ«r disa lĂ«shime: nĂ« kanal alfa ajo u bĂ« funksionale me versionin v1.0.5-alpha.19, ndĂ«rsa nĂ« kanal beta — me v1.0.4-beta.20.

patch 3-way-merge për të gjitha lëshimet

Deri më 15 Dhjetor 2019, versionet beta dhe alpha të werf do të përdorin automatikisht patch-e 3-way-merge për të aplikuar ndryshime për të gjitha versionet.

Ky modalitet pune mund të aktivizohet në mënyrë eksplicite me konfigurimin WERF_THREE_WAY_MERGE_MODE=enabled tani.

Si të veprohet me autoskalimin e burimeve?

Në Kubernetes, ekzistojnë 2 lloje të autoskalimit: HPA (horizontal) dhe VPA (vertikal).

Horizontalja automatikisht zgjidh numrin e replikave, ndërsa vertikalja - numrin e burimeve. Si numri i replikave, ashtu edhe kërkesat për burime specifikohen në manifestin e burimeve (shih spec.replicas ose spec.containers[].resources.limits.cpu, spec.containers[].resources.limits.memory dhe të tjera).

Problemi: nëse përdoruesi konfiguron burimin në chart në mënyrë që të përfshijë vlera të caktuara për burimet ose replikat dhe për këtë burim aktivizohen autoskalera, atëherë gjatë çdo depolimi werf do të rikthejë këto vlera në atë që është regjistruar në manifestin e chartit.

Ka dy zgjidhje për këtë problem. E para, më e mira është të flitet për heqjen e qartë të vlerave të autoskalueshme në manifestin e chartit. Nëse kjo mundësi për ndonjë arsye nuk është e përshtatshme (p.sh., sepse në chart është e përshtatshme të caktohen kufizime fillestare të burimeve dhe numri i replikave), atëherë werf ofron këto aneksime:

  • werf.io/set-replicas-only-on-creation=true
  • werf.io/set-resources-only-on-creation=true

Me një aneksim të tillë, werf nuk do të rikthejë vlerat përkatëse gjatë çdo depolimi, por do t'i vendosë ato vetëm gjatë krijimit fillestar të burimit.

Për më shumë, shih në dokumentacionin e projektit për HPA dhe VPA.

Ndalo përdorimin e patch-it me 3-way-merge

Përdoruesi për momentin mund të ndalojë përdorimin e patch-eve të reja në werf përmes variablës së mjedisit WERF_THREE_WAY_MERGE_MODE=disabled. Megjithatë, duke filluar nga 1 Mars 2020 ky ndalim do të ndalojë së funksionuari dhe do të jetë e mundur vetëm përdorimi i patch-eve 3-way-merge.

Adoptoni burimet në werf

Nisja e metodës së aplikimit të ndryshimeve me patch-e 3-way-merge na lejoi të realizonim menjëherë një karakteristikë si adoptimi i burimeve ekzistuese në klaster në Helm-release.

Helm 2 ka një problem: nuk mund të shtohet në manifestet e chart-it një burim që tashmë ekziston në klaster, pa e ri-krijuar atë nga e para (shih #6031, #3275). Ne i mësuam werf të pranojë burimet ekzistuese në release. Për këtë, është e nevojshme të vendosni në versionin aktual të burimit nga klasteri i punës një aneksim (p.sh., nëpërmjet kubectl edit):

"werf.io/allow-adoption-by-release": RELEASE_NAME

Tani duhet të përshkruhet në chart dhe me radhën tjetër që do të deplojohet ndihmësia me emrin e duhur, burimi ekzistues do të pranohet në këtë ndihmë dhe do të mbetet nën menaxhimin e saj. Më shumë se kaq, gjatë procesit të pranimit të burimit në ndihmë, werf do ta çojë gjendjen aktuale të burimit nga klasteri aktiv në gjendjen e përshkruar në chart, duke përdorur të njëjtat patch-e 3-way-merge dhe rregullin e burimit të sinkronizuar.

Shënim: konfigurimi WERF_THREE_WAY_MERGE_MODE nuk ndikon në pranimin e burimeve - në rastin e pranimit gjithmonë përdoret patch-i 3-way-merge.

Detajet - në dokumentacionin.

Konkluzionet dhe planet e ardhshme

Shpresoj se pas këtij artikulli është bërë më e qartë se çfarë janë patch-e 3-way-merge dhe pse kemi arritur kështu. Nga një pikëpamje praktike për zhvillimin e projektit werf, realizimi i tyre ishte një hap tjetër në përmirësimin e depolimit të ngjashëm me Helm. Tani mund të harrojmë problemet me sinkronizimin e konfiguracionit që shpesh shfaqeshin gjatë përdorimit të Helm 2. Me këtë, është shtuar një funksionalitet i ri i dobishëm për pranimin e burimeve Kubernetes që janë shkarkuar tashmë në Helm-në.

Në depolimin e ngjashëm me Helm, ende ka disa probleme dhe vështirësi, si përdorimi i template-eve Go, dhe ne do të vazhdojmë t'i zgjidhim ato.

Informacionin mbi metodat e përditësimit të burimeve dhe pranimin e tyre mund ta gjeni gjithashtu në këtë faqe dokumentacioni.

Helm 3

Një vërejtje e veçantë i takon në daljen të një versioni të ri të madh Helm - v3, - i cili gjithashtu përdor patch-e 3-way-merge dhe heq Tillerin. Versioni i ri i Helm kërkon migrazione instalime ekzistuese për t'i konvertuar ato në formatin e ri të ruajtjes së ndihmave.

Werf nga ana e tij deri tani ka hequr dorë nga përdorimi i Tiller, është kaluar në 3-way-merge dhe ka shtuar shumë të tjera, duke mbetur kështu i përputhshëm me instalimet ekzistuese në Helm 2 (nuk ka nevojë të kryhen skriptet e migrimit). Pra, për sa kohë që werf nuk është kalim në Helm 3, përdoruesit e werf nuk humbasin avantazhet kryesore të Helm 3 përpara Helm 2 (ato janë gjithashtu të pranishme në werf).

Megjithatë, kalimi i werf në bazën e kodit të Helm 3 është i pashmangshëm dhe do të ndodhë në të ardhmen e afërt. Pritet që kjo të jetë werf 1.1 ose werf 1.2 (në këtë moment, versioni kryesor i werf është 1.0; më shumë për strukturën e versionimit të werf shih. këtu). Gjatë kësaj kohe, Helm 3 do të ketë kohë për të stabilizuar.

P.S.

Lexoni gjithashtu në blogun tonë:

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster