Ang matagal na nating hinihintay (at hindi lang tayo) ay nangyari na: , ang aming open-source na utility para sa pagbuo ng mga application at paghahatid ng mga ito sa Kubernetes, ngayon ay sumusuporta sa paglalapat ng mga pagbabago gamit ang 3-way merge patch! Bukod pa rito, posible na ngayong gamitin ang mga kasalukuyang mapagkukunan ng K8 sa mga release ng Helm nang hindi nililikha muli ang mga ito.

Sa madaling salita, inilagay namin WERF_THREE_WAY_MERGE=enabled — nakakakuha tayo ng deployment “as in kubectl apply", tugma sa mga kasalukuyang Helm 2 installation at kahit kaunti pa.
Ngunit magsimula tayo sa teorya: ano ang mga 3-way-merge na patch, paano nakaisip ang mga tao ng diskarte sa pagbuo ng mga ito, at bakit mahalaga ang mga ito sa mga proseso ng CI/CD na may imprastraktura na nakabatay sa Kubernetes? Pagkatapos nito, titingnan natin kung ano talaga ang 3-way-merge sa werf, anong mga mode ang ginagamit bilang default, at kung paano ito pamahalaan.
Ano ang 3-way merge patch?
Kaya, magsimula tayo sa gawain ng paglulunsad ng mga mapagkukunang inilarawan sa mga manifest ng YAML sa Kubernetes.
Ang Kubernetes API ay nag-aalok ng mga sumusunod na pangunahing operasyon para sa pagtatrabaho sa mga mapagkukunan: gumawa, mag-patch, magpalit, at magtanggal. Ang mga ito ay nilayon na gamitin upang bumuo ng isang maginhawa, tuluy-tuloy na paglulunsad ng mapagkukunan sa cluster. Paano?
Mga imperative na utos ng kubectl
Ang unang diskarte sa pamamahala ng mga bagay sa Kubernetes ay ang paggamit ng mga kinakailangang kubectl na utos upang gawin, baguhin, at tanggalin ang mga bagay na ito. Sa madaling salita:
- koponan
kubectl runMaaari mong patakbuhin ang Deployment o Trabaho:kubectl run --generator=deployment/apps.v1 DEPLOYMENT_NAME --image=IMAGE - koponan
kubectl scale— baguhin ang bilang ng mga replika:kubectl scale --replicas=3 deployment/mysql - at iba pa
Ang diskarte na ito ay maaaring mukhang maginhawa sa unang tingin. Gayunpaman, may mga problema:
- Mahirap para sa kanya awtomatiko.
- Bilang sumasalamin sa pagsasaayos sa Git? Paano ko susuriin ang mga pagbabagong ginawa sa cluster?
- Paano masisiguro reproducibility mga configuration sa pag-restart?
- ...
Malinaw na ang diskarteng ito ay hindi angkop sa pag-iimbak ng application code at imprastraktura bilang code (IaC; o kahit na (bilang isang mas modernong opsyon na nakakakuha ng katanyagan sa Kubernetes ecosystem). Samakatuwid, ang mga utos na ito sa kubectl ay hindi pa binuo.
Gumawa, kumuha, palitan, at magtanggal ng mga pagpapatakbo
Sa pangunahin paglikha Simple lang: ipinapadala namin ang manifest sa operasyon create Ang kube API at mapagkukunan ay nilikha. Ang representasyon ng YAML ng manifest ay maaaring maimbak sa Git, at para gawin ito, gamitin ang command kubectl create -f manifest.yaml.
С pagtanggal simple lang din: pareho nating pinapalitan manifest.yaml mula sa Git hanggang sa koponan kubectl delete -f manifest.yaml.
Operasyon replace Nagbibigay-daan sa iyong ganap na palitan ang configuration ng isang mapagkukunan ng bago, nang hindi muling nililikha ang mapagkukunan. Nangangahulugan ito na bago gumawa ng pagbabago sa isang mapagkukunan, lohikal na humiling ng kasalukuyang bersyon na may operasyon get, baguhin ito at i-update ito sa operasyon replaceAng Kube ay may built in na apiserver. at kung pagkatapos ng operasyon get ang bagay ay nagbago, pagkatapos ay ang operasyon replace hindi ito gagana.
Upang maimbak ang configuration sa Git at i-update ito gamit ang replace, kailangan mong gawin ang operasyon get, pagsamahin ang config mula sa Git sa kung ano ang nakuha namin, at patakbuhin replaceBilang default, pinapayagan ka lang ng kubectl na gamitin ang command kubectl replace -f manifest.yamlSaan manifest.yaml — isang ganap na handa (sa aming kaso, pinagsama) na manifest na kailangang i-install. Nangangahulugan ito na kailangan ng user na pagsamahin ang mga manifest, na hindi isang maliit na gawain...
Ito rin ay nagkakahalaga ng pagpuna na bagaman manifest.yaml at nakaimbak sa Git, hindi natin malalaman nang maaga kung ang isang bagay ay kailangang gawin o i-update—dapat itong gawin ng software ng user.
Kabuuan: Maaari ba tayong bumuo ng tuluy-tuloy na paglulunsad? gamit lang gumawa, palitan, at tanggalin, na tinitiyak na ang configuration ng imprastraktura ay nakaimbak sa Git kasama ang code at maginhawang CI/CD?
Sa prinsipyo, kaya natin... Para dito kakailanganing ipatupad ang merge operation manifestos at ilang uri ng pagbubuklod, na:
- sinusuri ang pagkakaroon ng isang bagay sa kumpol,
- nagsasagawa ng paunang paglikha ng isang mapagkukunan,
- ina-update o tinatanggal ito.
Kapag nag-a-update, mangyaring tandaan iyon maaaring nagbago ang mapagkukunan mula noong huli get at awtomatikong pangasiwaan ang kaso ng optimistic locking - gumawa ng paulit-ulit na pagtatangka na mag-update.
Gayunpaman, bakit muling likhain ang gulong kapag nag-aalok ang kube-apiserver ng isa pang paraan upang i-update ang mga mapagkukunan: ang operasyon patch, na nagpapagaan sa gumagamit ng ilan sa mga problemang inilarawan?
magtagpi
Kaya, sa wakas naabot na namin ang mga patch.
Ang mga patch ay ang pangunahing paraan upang maglapat ng mga pagbabago sa mga umiiral nang object sa Kubernetes. Operasyon patch gumagana sa paraang:
- Ang kube-apiserver user ay kailangang magpadala ng patch sa JSON format at tukuyin ang object,
- at ang apiserver mismo ay haharapin ang kasalukuyang estado ng bagay at dalhin ito sa kinakailangang form.
Hindi kinakailangan ang optimistikong pag-lock sa kasong ito. Ang operasyong ito ay mas deklaratibo kaysa palitan, bagama't sa una ay tila kabaligtaran.
Sa ganitong paraan:
- sa pamamagitan ng operasyon
createlumikha kami ng isang bagay batay sa manifest mula sa Git, - sa tulong
delete- tanggalin kung hindi na kailangan ang bagay, - sa tulong
patch— binabago namin ang bagay, dinadala ito sa form na inilarawan sa Git.
Gayunpaman, upang gawin ito, kailangan mong lumikha tamang patch!
Paano Gumagana ang Mga Patch sa Helm 2: 2-Way merges
Kapag una kang nag-install ng release, ginagawa ng Helm ang operasyon create para sa mga mapagkukunan ng tsart.
Kapag nag-a-update ng isang release ng Helm para sa bawat mapagkukunan:
- kinakalkula ang patch sa pagitan ng bersyon ng mapagkukunan mula sa nakaraang chart at kasalukuyang bersyon ng chart,
- nalalapat ang patch na ito.
Tatawagan namin ang gayong patch 2-way-merge na patch, dahil dalawang manifesto ang kasangkot sa paglikha nito:
- resource manifest mula sa nakaraang release,
- resource manifest mula sa kasalukuyang resource.
Kapag tinatanggal ang operasyon delete Sa kube, apiserver ay tinatawag para sa mga mapagkukunan na idineklara sa nakaraang release ngunit hindi ipinahayag sa kasalukuyang isa.
May problema ang 2-way merge patch approach: humahantong ito sa desynchronization ng aktwal na estado ng mapagkukunan sa cluster at ang manifest sa Git.
Pagpapakita ng problema sa isang halimbawa
- Sa Git, ang tsart ay nag-iimbak ng isang manifest kung saan ang field
imageMay halaga ang deploymentubuntu:18.04. - Gumagamit sa pamamagitan ng
kubectl editbinago ang halaga ng field na ito saubuntu:19.04. - Kapag muling nag-deploy ng Helm chart hindi bumubuo ng isang patch, dahil ang field
imagesa nakaraang bersyon ng release at sa kasalukuyang chart ay pareho. - Pagkatapos ng redeployment
imagelabiubuntu:19.04, bagama't sinasabi ng tsartubuntu:18.04.
Na-desynchronize kami at nawalan ng declarativeness.
Ano ang isang naka-synchronize na mapagkukunan?
Sa pangkalahatan, kumpleto Imposibleng makakuha ng tugma sa pagitan ng resource manifest sa tumatakbong cluster at manifest mula sa Git. Ito ay dahil ang isang tunay na manifest ay maaaring maglaman ng mga anotasyon/label ng serbisyo, karagdagang container, at iba pang data na dynamic na idinagdag at inalis sa resource ng ilang controller. Hindi namin magagawa at ayaw naming iimbak ang data na ito sa Git. Gayunpaman, gusto namin ang mga field na tahasang tinukoy namin sa Git na magkaroon ng naaangkop na mga halaga sa panahon ng pag-deploy.
Napaka-general pala naka-synchronize na tuntunin sa mapagkukunan: Kapag naglulunsad ng mapagkukunan, maaari mo lamang baguhin o tanggalin ang mga field na iyon na tahasang tinukoy sa Git manifest (o tinukoy sa nakaraang bersyon at naalis na ngayon).
3-way-merge na patch
sentral na ideya : Bumuo ng patch sa pagitan ng huling inilapat na bersyon ng Git manifest at ng target na bersyon ng Git manifest, na isinasaalang-alang ang kasalukuyang bersyon ng manifest mula sa tumatakbong cluster. Ang resultang patch ay dapat sumunod sa naka-synchronize na tuntunin ng mapagkukunan:
- ang mga bagong field na idinagdag sa target na bersyon ay idinaragdag sa pamamagitan ng isang patch;
- ang mga dating umiiral na field sa huling inilapat na bersyon at ang mga wala sa target na bersyon ay ni-reset gamit ang isang patch;
- Ang mga field sa kasalukuyang bersyon ng object na naiiba sa target na bersyon ng manifest ay ina-update gamit ang isang patch.
Ito ang prinsipyo kung saan nabuo ang mga patch. kubectl apply:
- ang huling inilapat na bersyon ng manifest ay naka-imbak sa anotasyon ng object mismo,
- target - kinuha mula sa tinukoy na YAML file,
- kasalukuyang - mula sa isang tumatakbong kumpol.
Ngayon na nasaklaw na namin ang teorya, oras na para sabihin sa iyo kung ano ang ginawa namin sa werf.
Paglalapat ng mga pagbabago sa werf
Dati, ang werf, tulad ng Helm 2, ay gumamit ng 2-way-merge na mga patch.
Ayusin ang patch
Upang lumipat sa isang bagong uri ng mga patch - 3-way-merge - ang unang hakbang na ginawa namin ay ipakilala ang tinatawag na repair patch.
Kapag nagde-deploy, isang karaniwang 2-way-merge na patch ang ginagamit, ngunit ang werf ay bubuo din ng isang patch na magsi-synchronize sa totoong estado ng mapagkukunan sa kung ano ang nakasulat sa Git (ginawa ang patch na ito gamit ang parehong naka-synchronize na panuntunan ng mapagkukunan na inilarawan sa itaas).
Kung may nangyaring desync, sa pagtatapos ng deployment, makakatanggap ang user ng WARNING message na may kaukulang mensahe at patch na dapat ilapat upang maibalik ang resource sa sync. Isinulat din ang patch na ito sa isang espesyal na anotasyon. werf.io/repair-patchIpinapalagay na ang gumagamit ay gumagamit ng kanyang mga kamay siya mismo ilalapat ang patch na ito: hindi ito ilalapat ng werf sa prinsipyo.
Ang pagbuo ng mga repair patch ay isang pansamantalang panukalang nagbibigay-daan sa iyong subukan ang 3-way-merge na proseso ng pagbuo ng patch, ngunit hindi awtomatikong inilalapat ang mga patch na ito. Ang mode na ito ay kasalukuyang pinagana bilang default.
3-way-merge na patch para sa mga bagong release lang
Simula sa Disyembre 1, 2019, magsisimula ang beta at alpha na bersyon ng werf bilang default Gumamit ng buong 3-way-merge na mga patch para maglapat lang ng mga pagbabago sa mga bagong release ng Helm na na-deploy sa pamamagitan ng werf. Ang mga kasalukuyang release ay patuloy na gagamit ng 2-way-merge + repair patch approach.
Ang operating mode na ito ay maaaring tahasang paganahin sa pamamagitan ng pagtatakda WERF_THREE_WAY_MERGE_MODE=onlyNewReleases ngayon.
Nota: lumitaw ang feature sa werf sa ilang paglabas: sa alpha channel naging handa ito sa bersyon , at sa beta channel - kasama ang .
3-way-merge na patch para sa lahat ng release
Simula sa Disyembre 15, 2019, ang beta at alpha na bersyon ng werf ay gagamit ng buong 3-way na merge patch bilang default para maglapat ng mga pagbabago para sa lahat ng release.
Ang operating mode na ito ay maaaring tahasang paganahin sa pamamagitan ng pagtatakda WERF_THREE_WAY_MERGE_MODE=enabled ngayon.
Paano haharapin ang resource autoscaling?
Mayroong dalawang uri ng autoscaling sa Kubernetes: HPA (horizontal) at VPA (vertical).
Awtomatikong pinipili ng pahalang ang bilang ng mga replika, habang pinipili ng patayo ang bilang ng mga mapagkukunan. Parehong tinukoy ang bilang ng mga replika at resource na kinakailangan sa resource manifest (tingnan ang spec.replicas o spec.containers[].resources.limits.cpu, spec.containers[].resources.limits.memory и ).
Problema: Kung ang isang user ay nag-configure ng isang mapagkukunan sa isang tsart upang ito ay tumukoy ng mga partikular na halaga para sa mga mapagkukunan o mga replika, at ang mga autoscaler ay pinagana para sa mapagkukunang ito, pagkatapos ay sa bawat pag-deploy, ire-reset ng werf ang mga halagang ito sa kung ano ang nakasulat sa manifest ng tsart.
Mayroong dalawang solusyon sa problemang ito. Ang pinakamahusay na paraan upang magsimula ay upang maiwasan ang tahasang pagtukoy ng mga halaga ng autoscaling sa manifest ng chart. Kung hindi angkop ang opsyong ito sa ilang kadahilanan (halimbawa, dahil maginhawang tukuyin ang mga paunang limitasyon sa mapagkukunan at ang bilang ng mga replika sa chart), inaalok ng werf ang mga sumusunod na anotasyon:
-
werf.io/set-replicas-only-on-creation=true -
werf.io/set-resources-only-on-creation=true
Sa annotation na ito, hindi ire-reset ng werf ang mga katumbas na halaga sa bawat deployment, ngunit itatakda lamang ang mga ito kapag ang mapagkukunan ay unang ginawa.
Para sa higit pang mga detalye, tingnan ang dokumentasyon ng proyekto. и .
Huwag paganahin ang paggamit ng 3-way-merge na patch
Kasalukuyang hindi paganahin ng user ang paggamit ng mga bagong patch sa werf gamit ang isang environment variable. WERF_THREE_WAY_MERGE_MODE=disabledGayunpaman, simula Ang pagbabawal na ito ay hindi na ilalapat simula Marso 1, 2020. at magiging posible lamang na gumamit ng 3-way-merge na mga patch.
Pag-ampon ng mga mapagkukunan sa werf
Ang pag-master ng 3-way-merge na paraan ng patch ng paglalapat ng mga pagbabago ay nagbigay-daan sa amin na agad na ipatupad ang isang feature gaya ng paggamit ng mga kasalukuyang mapagkukunan ng cluster sa isang release ng Helm.
May problema ang Helm 2: hindi ka makakapagdagdag ng resource sa isang chart manifest na mayroon na sa cluster nang hindi nililikha ang resource na iyon mula sa simula (tingnan sa ibaba). , ). Itinuro namin sa werf na tanggapin ang mga kasalukuyang mapagkukunan sa isang release. Upang gawin ito, kailangan mong mag-install ng anotasyon sa kasalukuyang bersyon ng isang mapagkukunan mula sa isang tumatakbong cluster (halimbawa, gamit ang kubectl edit):
"werf.io/allow-adoption-by-release": RELEASE_NAMENgayon ang resource ay kailangang ilarawan sa chart, at sa susunod na mag-deploy ang werf ng release na may katumbas na pangalan, ang kasalukuyang resource ay tatanggapin sa release na iyon at mananatili sa ilalim ng pamamahala nito. Higit pa rito, sa panahon ng proseso ng pagtanggap ng resource sa release, iko-convert ng werf ang kasalukuyang estado ng resource mula sa running cluster patungo sa state na inilalarawan sa chart, gamit ang parehong 3-way-merge na mga patch at ang naka-synchronize na panuntunan ng mapagkukunan.
Nota: setting WERF_THREE_WAY_MERGE_MODE hindi nakakaapekto sa pag-aampon ng mga mapagkukunan - sa kaso ng pag-aampon, ang 3-way-merge na patch ay palaging ginagamit.
Ang mga detalye ay nasa .
Mga konklusyon at mga plano sa hinaharap
Sana ay ginawang mas malinaw ng artikulong ito kung ano ang mga 3-way na merge na patch at kung bakit sila napili. Mula sa isang praktikal na pananaw para sa proyekto ng werf, ang kanilang pagpapatupad ay nagmamarka ng isa pang hakbang tungo sa pagpapabuti ng deployment na parang Helm. Ang mga isyu sa pag-synchronize ng configuration na madalas lumitaw sa Helm 2 ay maaari na ngayong makalimutan. Kasabay nito, may idinagdag na bago at kapaki-pakinabang na feature: pag-adopt ng mga na-deploy na mapagkukunan ng Kubernetes sa isang release ng Helm.
Mayroon pa ring ilang isyu at hamon sa deployment na parang Helm, gaya ng paggamit ng mga template ng Go, at patuloy naming tutugunan ang mga ito.
Ang impormasyon sa mga paraan ng pag-update ng mapagkukunan at pag-aampon ay matatagpuan din sa .
Helm 3
Karapat-dapat sa espesyal na pagbanggit Noong isang araw lang, isang bagong pangunahing bersyon ng Helm—v3— ang inilabas, na gumagamit din ng 3-way-merge na mga patch at inaalis ang Tiller. Ang bagong bersyon ng Helm ay nangangailangan kasalukuyang mga pag-install upang i-convert ang mga ito sa bagong format ng imbakan ng release.
Ang Werf, sa bahagi nito, ay inalis na ngayon ang paggamit ng Tiller, lumipat sa 3-way-merge at idinagdag , habang nananatiling tugma sa mga kasalukuyang pag-install ng Helm 2 (walang kinakailangang mga script sa paglilipat). Samakatuwid, hanggang sa lumipat si werf sa Helm 3, hindi mawawala sa mga user ng werf ang mga pangunahing bentahe ng Helm 3 kumpara sa Helm 2 (mayroon ding mga kalamangan ang werf).
Gayunpaman, ang paglipat ni werf sa Helm 3 codebase ay hindi maiiwasan at mangyayari sa malapit na hinaharap. Ito ay malamang na magiging werf 1.1 o werf 1.2 (sa kasalukuyan, ang pangunahing bersyon ng werf ay 1.0; para sa higit pang impormasyon sa werf versioning, tingnan ang ). Sa panahong ito, magkakaroon ng oras ang Helm 3 para mag-stabilize.
PS
Basahin din sa aming blog:
- Isang serye ng mga tala tungkol sa mga inobasyon sa werf:
- «";
- «";
- «'.
- «";
- «";
- «'.
Pinagmulan: www.habr.com
