Spojimi 3-way në werf: instalim në Kubernetes me Helm "në steroidë"

Ishte një ngjarje që ne (dhe jo vetëm ne) e prisnim prej kohësh: werf, mjeti ynë Open Source për ndërtimin e aplikacioneve dhe dorëzimin 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ë helm-release pa ri-krijimin e këtyre burimeve.

Spojimi 3-way në werf: instalim në Kubernetes me Helm "në steroidë"

NĂ«se ta themi shumĂ« shkurt, ne vendosim WERF_THREE_WAY_MERGE=enabled — marrim njĂ« deploy «si nĂ« kubectl aplikoni», i cili Ă«shtĂ« i pĂ«rshtatshĂ«m me instalimet ekzistuese nĂ« Helm 2 dhe madje pak mĂ« shumĂ«.

Por le të fillojmë me teorinë: çfarë janë patch-et 3-way-merge, si erdhën njerëzit në këtë qasje dhe pse janë të rëndësishme në proceset CI/CD me infrastrukturë bazuar në Kubernetes? Pas kësaj, do të shohim se çfarë përfaqëson 3-way-merge në werf, cilat moda përdoren si parazgjedhje dhe si t'i menaxhojmë ato.

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

Pra, le të fillojmë me detyrën e nisjes së burimeve, të përshkruara në manifestet YAML, në Kubernetes.

Për të punuar me burimet, Kubernetes API ofron operacionet kryesore: create, patch, replace dhe delete. Supozohet që me to duhet të ndërtohet një deploy i përshtatshëm i burimeve në klaster. Si?

Komandat imperativë kubectl

Afrohet metoda e parĂ« pĂ«r menaxhimin e objekteve nĂ« Kubernetes — pĂ«rdorimi i komandave imperativĂ« kubectl pĂ«r krijimin, ndryshimin dhe fshirjen e kĂ«tyre objekteve. NĂ« terma tĂ« thjeshtĂ«:

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

Ky qasje mund të duket e përshtatshme në shikim të parë. Megjithatë, ka probleme:

  1. ËshtĂ« e vĂ«shtirĂ« pĂ«r ta automatizuar.
  2. Si për të reflektuar konfiguracionin në Git? Si të bëjmë review të ndryshimeve që ndodhin me klasterin?
  3. Si të sigurojmë riprodhueshmëria konfigurimin në rishkaktim?
  4. 


ËshtĂ« e qartĂ« se ky qasje i pĂ«rshtatet dobĂ«t ruajtjes sĂ« sĂ« bashku me kodin e aplikacionit dhe infrastrukturĂ«s si kod (IaC; ose edhe GitOps si njĂ« variant mĂ« modern, qĂ« po fiton popullaritet nĂ« ekosistemin Kubernetes). Prandaj, zhvillimi i mĂ«tejshĂ«m i kĂ«tyre komandave nĂ« kubectl nuk mori prioritet.

Operacionet create, get, replace dhe delete

Me krijimin nĂ« fillim Ă«shtĂ« shumĂ« e thjeshtĂ«: ne dĂ«rgojmĂ« manifestin nĂ« operacionin krijo nĂ« kube API dhe burimi Ă«shtĂ« krijuar. PĂ«rfaqĂ«simi YAML i manifestit mund tĂ« ruhet nĂ« Git, dhe pĂ«r tĂ« krijuar — pĂ«rdorim komandĂ«n kubectl create -f manifest.yaml.

Me fshirja po ashtu është e thjeshtë: ne mund të përdorim të njëjtin manifest.yaml nga Git në komandën kubectl delete -f manifest.yaml.

Operacioni zëvendëso lejon plotësisht të zëvendësojmë konfiguracionin e burimit me një të re, pa e rikrijuar burimin. Kjo do të thotë se para se të bëjmë një ndryshim në burim, është logjike të kërkojmë versionin aktual me operacionin merr, ta ndryshojmë atë dhe ta azhurnojmë me operacionin zëvendëso. Në kube apiserver është ndërtuar optimistic locking dhe, nëse objekti ka ndryshuar pas operacionit, atëherë operacioni merr nuk do të kalojë. zëvendëso nuk nuk kalon.

PĂ«r tĂ« ruajtur konfiguracionin nĂ« Git dhe pĂ«r ta azhurnuar me zĂ«vendĂ«sim, duhet tĂ« kryejmĂ« operacionin merr, tĂ« bashkojmĂ« konfigurimin nga Git me atĂ« qĂ« kemi marrĂ«, dhe tĂ« ekzekutojmĂ« zĂ«vendĂ«so. NĂ« mĂ«nyrĂ« tĂ« natyrshme, kubectl vetĂ«m lejon pĂ«rdorimin e komandĂ«s kubectl replace -f manifest.yaml, ku manifest.yaml — tashmĂ« njĂ« manifest i plotĂ«sisht i pĂ«rgatitur (nĂ« rastin tonĂ« — i bashkuar) qĂ« kĂ«rkohet tĂ« vendoset. KĂ«shtu, pĂ«rdoruesi duhet tĂ« zgjidhĂ« bashkimin e manifestĂ«ve, njĂ« detyrĂ« qĂ« nuk Ă«shtĂ« e thjeshtë 

Po ashtu, duhet tĂ« theksohet se ndonĂ«se manifest.yaml ruhet nĂ« Git, ne nuk mund ta dimĂ« paraprakisht nĂ«se duhet tĂ« krijojmĂ« objektin apo ta azhurnojmĂ« atĂ« — kjo duhet tĂ« bĂ«het nga softi i pĂ«rdoruesit.

Në përmbledhje: a mund të ndërtojmë një deploy të vazhdueshëm vetëm me ndihmën e create, replace dhe delete, duke siguruar ruajtjen e konfiguracionit të infrastrukturës në Git së bashku me kodin dhe një CI/CD të përshtatshëm?

Në parim, po
 Për këtë do të kërkojë implementimin e operacionit të bashkimit të manifestëve dhe ndonjë mbështetje që:

  • kontrollon nĂ«se objekti Ă«shtĂ« nĂ« klaster,
  • ekzekuton krijimin fillestar tĂ« burimit,
  • azhornohet ose fshihet.

Duke azhurnuar, duhet tĂ« kemi parasysh se burimi mund tĂ« ketĂ« ndryshuar qĂ« nga hera e fundit merr dhe tĂ« trajtojmĂ« automatikisht rastin e optimistic locking — tĂ« bĂ«jmĂ« pĂ«rpjekje tĂ« pĂ«rsĂ«ritura pĂ«r azhurnimin.

Megjithatë, pse të shpikim bicikletën, kur kube-apiserver ofron një mënyrë tjetër për të azhurnuar burimet: operacionin patch, i cili heq disa nga problemet e përshkruara nga përdoruesi?

Patch

Ja ku arritëm te patch-et.

Patch-et janë mënyra kryesore për të aplikuar ndryshime në objektet ekzistuese në Kubernetes. Operacioni patch funksionon në mënyrë që:

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

Optimistic locking në këtë rast nuk kërkohet. Ky operacion është më deklarativ në krahasim me zëvendësimin, megjithëse fillimisht mund të duket ndryshe.

Pra:

  • nĂ«pĂ«rmjet operacionit krijo krijojmĂ« objektin sipas manifestit nga Git,
  • me anĂ« tĂ« fshi — e fshijmĂ«, nĂ«se objekti nuk Ă«shtĂ« mĂ« i nevojshĂ«m,
  • me anĂ« tĂ« patch — e ndryshojmĂ« objektin, duke e sjellĂ« atĂ« nĂ« formĂ«n qĂ« Ă«shtĂ« pĂ«rshkruar nĂ« Git.

Megjithatë, për të bërë këtë, është e nevojshme të krijohet patch i saktë!

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

Kur përcaktoni një version të ri, Helm kryen një operacion krijo për burimet e chart-it.

Kur përditësoni versionin Helm për secilën burim:

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

Patch-i i tillë do ta quajmë patch 2-way-merge, sepse në krijimin e tij përfshihen 2 manifesete:

  • manifesti i burimit nga versioni i kaluar,
  • manifesti i burimit nga burimi aktual.

Kur fshini, operacioni fshi në kube apiserver thirret për burimet që ishin të shpallura në versionin e kaluar, por nuk janë shpallur në atë aktual.

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

Illustrimi i problemit me shembuj

  • NĂ« Git, nĂ« chart ruhet njĂ« manifest, nĂ« tĂ« cilin fusha image nĂ« Deployment ka vlerĂ«n ubuntu:18.04.
  • PĂ«rdoruesi pĂ«rmes kubectl edit ndryshoi vlerĂ«n e kĂ«saj fushe nĂ« ubuntu:19.04.
  • Kur ri-deploy gjenje chart-i Helm nuk gjeneron patch, sepse fusha image nĂ« versionin e kaluar dhe nĂ« chart-in e tanishĂ«m janĂ« tĂ« njĂ«jtat.
  • Pas ri-deploy, image mbetet ubuntu:19.04, ndonĂ«se nĂ« chart shkruhet ubuntu:18.04.

Kështu kemi pasur asinkronizim dhe humbëm deklarativitetin.

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

Në përgjithësi, përputhja e plotë e manifestit të burimit në klasterin e punës dhe manifestit nga Git nuk është e mundur. Sepse në manifestin e vërtetë mund të ketë annotime/etiketa të shërbimit, kontejnerë shtesë dhe të dhëna të tjera që shtohen dhe fshihen nga burimi dinamikisht nga disa kontrolerë. Këto të dhëna ne nuk mund dhe nuk duam t'i mbajmë në Git. Megjithatë, ne duam që kur të publikojmë, fushat e caktuara që kemi specifikuar në Git të pranojnë vlerat përkatëse.

Pra, kemi një rregull të përgjithshëm të burimit të sinkronizuar: gjatë publikimit të burimit mund të ndryshohen ose fshihen vetëm ato fusha që janë qartësisht të shkruara në manifestin nga Git (ose ishin shënuar në versionin e kaluar dhe tani janë fshirë).

patch 3-way-merge

Ideja kryesore patch 3-way-merge: gjeneron një patch midis versionit 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 i punës. Patch-i përfundimtar duhet të përputhet me rregullin e burimit të sinkronizuar:

  • fushat e reja, tĂ« shtuar nĂ« versionin e synuar, shtohen me anĂ« tĂ« patch-it;
  • fushat qĂ« ekzistonin mĂ« parĂ« nĂ« versionin e fundit tĂ« aplikuar dhe nuk ekzistojnĂ« nĂ« versionin e synuar - nullohen me anĂ« tĂ« patch-it;
  • fushat nĂ« versionin aktual tĂ« objektit, qĂ« dallohet nga versioni i synuar i manifestit, - pĂ«rditĂ«sohen me anĂ« tĂ« patch-it.

Në këtë mënyrë, patch-et gjenerohen kubectl aplikoni:

  • versioni i fundit i aplikuar i manifestit ruhet nĂ« annotimin e vetĂ« objektit,
  • versioni i synuar merret nga skedari YAML i caktuar,
  • versioni aktual - nga klasteri i punĂ«s.

Tani, pasi i kuptuam teoritë, është koha të flasim për atë që kemi bërë në werf.

Raportimi i ndryshimeve në werf

Më parë, werf, ashtu si Helm 2, përdorte patch-at 2-way-merge.

Patch-i i Riparimit

Për të kaluar në llojin e ri të patch-it - 3-way-merge, hapi i parë që kemi marrë është prezantimi i ashtuquajtur patch i riparimit.

Gjatë publikimit përdoret standardi 2-way-merge patch, por werf gjithashtu krijon një patch që sinkronizon gjendjen reale të burimit me atë që është shkruar në Git (në krijimin e këtij patch-i përdoret rregulli i sinkronizimit të burimeve, siç u përmend më lart).

Në rast se ndodh një asinkronizim, në fund të publikimit përdoruesi merr një WARNING me mesazhin dhe patch-in përkatës që duhet të aplikohet për të sjellë burimin në një gjendje të sinkronizuar. Gjithashtu, ky patch regjistrohet në një annotim të veçantë werf.io/repair-patch. Supozohet se përdoruesi manualisht vetë do ta aplikojë këtë patch: werf nuk do ta aplikojë.

Gjenerimi i repair-patch-eve është një masë e përkohshme që lejon testimin e realizimit të patch-eve sipas parimit të 3-way-merge, por patch-et këto nuk aplikohen automatikisht. Aktualisht, ky mod është aktivizuar me parazgjedhje.

Patch i 3-way-merge vetëm për lëshime të reja

Deri më 1 dhjetor 2019, versionet beta dhe alpha të werf fillojnë në mënyrë default të përdorin patch-et e plota 3-way-merge për të kryer ndryshime vetëm për lëshime të reja Helm të publikuara nëpërmjet werf. Lëshimet ekzistuese do të vazhdojnë të përdorin qasjen me 2-way-merge + repair-patch-e.

Ky mod funksionimi mund të aktivizohet qartë duke e konfiguruar WERF_THREE_WAY_MERGE_MODE=onlyNewReleases të shkarkohet tashmë.

Shënim: funksionaliteti është shfaqur në werf për gjatë disa lëshimeve: në kanal alpha ka qenë i gatshëm që nga versioni v1.0.5-alpha.19, ndërsa në kanal beta - nga v1.0.4-beta.20.

Patch i 3-way-merge për të gjitha lëshimet

Deri më 15 dhjetor 2019, versionet beta dhe alpha të werf fillojnë të përdorin automatikisht patch-et e plota 3-way-merge për të kryer ndryshime për të gjitha lëshimet.

Ky mod funksionimi mund të aktivizohet qartë duke e konfiguruar WERF_THREE_WAY_MERGE_MODE=enabled të shkarkohet tashmë.

Si të menaxhojmë automatizimin e burimeve?

Në Kubernetes ekzistojnë 2 lloje automatizimi: HPA (horizontal) dhe VPA (vertical).

Horizontalja pĂ«rzgjedh automatikisht numrin e kopjeve, ndĂ«rsa vertikalia — sasinĂ« e burimeve. Si numri i kopjeve ashtu edhe kĂ«rkesat pĂ«r burimet specifikohen nĂ« manifestin e burimit (shih. spec.replicas ose spec.containers[].resources.limits.cpu, spec.containers[].resources.limits.memory dhe tĂ« tjera).

Problemi: nëse përdoruesi konfigurion burimin në chart duke specifikuar vlera të caktuara për burimet ose kopjet dhe për këtë burim aktivizohen automatizuesit, atëherë në çdo shpërndarje werf do të rikthejë këto vlera në ato që janë të regjistruara në manifestin e chartit.

Ka dy zgjidhje për këtë problem. Fillimisht, është më mirë të heqim dorë nga specifikimi i qartë të vlerave të automatizueshme në manifestin e chartit. Nëse kjo opsion për disa arsye nuk është i përshtatshëm (për shembull, sepse në chart është e lehtë të vendosësh kufij fillestarë për burimet dhe numrin e kopjeve), atëherë werf ofron këto anotacione:

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

Me pasjen e një anotacioni të tillë, werf nuk do të rikthejë vlerat përkatëse në çdo shpërndarje, por vetëm do t'i vendosë ato gjatë krijimit të parë të burimit.

PĂ«r mĂ« shumĂ« informacione – shih nĂ« dokumentacionin e projektit pĂ«r HPA dhe VPA.

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

Përdoruesi mund të ndalojë për momentin 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, kjo ndalesë do të ndalojë së funksionuari dhe do të jetë e mundur vetëm përdorimi i patch-eve 3-way-merge.

Adoptimi i burimeve në werf

Zhvillimi i metodës së zbatimit të ndryshimeve me patch-e 3-way-merge na lejojnë të implementojmë një karakteristikë të tillë si adoptimi i burimeve ekzistuese në klaster në Helm-release.

Helm 2 ka një problem: nuk është e mundur të shtosh në manifestet e chartit një burim që ekziston tashmë në klaster pa e rindërtuar këtë burim nga e para (shih. #6031, #3275). Ne mësuam werf të pranojë burimet ekzistuese në release. Për këtë, duhet të vendosni në versionin aktual të burimit nga klasteri aktiv një anotacion (për shembull, përmes kubectl edit):

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

Tani burimi duhet të përshkruhet në chart dhe gjatë shpërndarjes tjetër të werf-it të release me emrin përkatës, burimi ekzistues do të pranohet në këtë release dhe do të mbetet nën menaxhimin e tij. Më shumë se kaq, në procesin e pranimit të burimit në release, werf do të sjellë gjendjen aktuale të burimit nga klasteri aktiv në gjendjen, siç përshkruhet në chart, duke përdorur të njëjtat patch-e 3-way-merge dhe rregullin e burimeve të sinkronizuara.

ShĂ«nim: konfigurimi WERF_THREE_WAY_MERGE_MODE nuk ndikon nĂ« adoptimin e burimeve — nĂ« rastin e adoptimit gjithmonĂ« pĂ«rdoret patch-i 3-way-merge.

Detajet – nĂ« dokumentacion.

Konkluzionet dhe planet e ardhshme

Shpresoj, pas këtij artikulli ka shkuar më qartë se çfarë janë patch-et 3-way-merge dhe pse arritëm këtu. Nga një pikëpamje praktike e zhvillimit të projektit werf, implementimi i tyre u bë një hap tjetër në përmirësimin e shpërndarjes së ngjashme me Helm. Tani mund të harrojmë problemet me sinkronizimin e konfiguracionit që shpesh shfaqeshin gjatë përdorimit të Helm 2. Gjithashtu, u shtua një karakteristikë e re e dobishme të adoptimit të burimeve Kubernetes të shkarkuara.

Në shpërndarjen e ngjashme me Helm vazhdojnë të mbeten disa probleme dhe vështirësi, siç janë përdorimi i templating-ve Go, dhe ne do të vazhdojmë t'i zgjidhim ato.

Informacion për metodat e përditësimit të burimeve dhe adoptimit gjithashtu mund të gjendet në këtë faqe dokumentacioni.

Helm 3

NjĂ« vĂ«rejtje e veçantĂ« meriton versioni i ri i rĂ«ndĂ«sishĂ«m i lĂ«shuar para disa ditĂ«sh Helm — v3, — i cili gjithashtu pĂ«rdor patch-e 3-way-merge dhe heq Tiller. Versioni i ri i Helm kĂ«rkon migrimi instalimet ekzistuese qĂ« t'i konvertojnĂ« ato nĂ« formatin e ri tĂ« ruajtjes sĂ« releases.

Werf nga ana e tij për momentin nuk e përdor më Tiller, është ndërruar në 3-way-merge dhe ka shtuar shumë më tepër, duke qëndruar në përputhje me instalimet ekzistuese në Helm 2 (nuk nevojiten skripte migrimi). Prandaj, sa herë që werf nuk është kaluar në Helm 3, përdoruesit e werf nuk humbasin përfitimet kryesore të Helm 3 në krahasim me Helm 2 (ato janë gjithashtu të pranishme në werf).

Megjithatë, kalimi i werf në kodin bazë të Helm 3 është i pashmangshëm dhe do të ndodhë në të ardhmen e afërt. Supozohet se kjo do të jetë werf 1.1 ose werf 1.2 (për momentin, versioni kryesor i werf është 1.0; për më shumë rreth ndërtimit të versioneve të werf shih. këtu). Gjatë kësaj kohe, Helm 3 do të stabilizohet.

P.S.

Lexoni gjithashtu në blogun tonë:

Burimi: habr.com

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