Taŭga Komparo de Kubernetes Apliki, Anstataŭigi kaj Flikilo

Kubernetes havas plurajn eblojn por ĝisdatigi rimedojn: apliki, redakti, fliki kaj anstataŭigi. Estas konfuzo pri tio, kion ĉiu faras kaj kiam uzi ilin. Ni eltrovu ĝin.

Taŭga Komparo de Kubernetes Apliki, Anstataŭigi kaj Flikilo

se serĉi en Guglo la frazo "kubernetes apliki vs anstataŭi" troviĝas respondi al StackOverflow, kio ne estas ĝusta. Dum serĉado "kubernetes apply vs patch" la unua ligilo estas la dokumentado por kubectl patch, kiu ne inkluzivas komparon apply и patch. Ĉi tiu artikolo rigardos la malsamajn eblojn, same kiel la ĝustan uzon de ĉiu.

Dum la vivociklo de Kubernetes-rimedo (servo, deplojo, eniro, ktp.), foje vi devas ŝanĝi, aldoni aŭ forigi iujn ecojn de ĉi tiu rimedo. Ekzemple, aldonu noton, pliigu aŭ malpliigu la nombron da kopioj.

Kubernetes CLI

Se vi jam laboras kun Kubernetes-grupoj per la CLI, vi jam konas apply и edit. Teamo apply legas la rimedan specifon de la dosiero kaj faras "upsert" al la Kubernetes-areto, t.e. kreas la rimedon se ĝi ne ekzistas kaj ĝisdatigas ĝin se ĝi ekzistas. Teamo edit legas rimedon per la API, tiam skribas la rimedan specifon al loka dosiero, kiu tiam estas malfermita en tekstredaktilo. Post kiam vi redaktas kaj konservas la dosieron, kubectl sendos la ŝanĝojn faritajn reen per la API, kiu zorge aplikos ĉi tiujn ŝanĝojn al la rimedo.

Ne ĉiuj konas la ordonojn patch и replace. Teamo patch permesas vin ŝanĝi parton de rimeda specifo, provizante nur la ŝanĝitan parton sur la komandlinio. Teamo replace funkcias same kiel edit, sed ĉio devas esti farita permane: vi devas elŝuti la nunan version de la rimeda specifo, ekzemple, uzante kubectl get -o yaml, redaktu ĝin, poste uzu replace ĝisdatigi rimedon laŭ ŝanĝita specifo. Teamo replace ne funkcios se iuj ŝanĝoj okazis inter legado kaj anstataŭigo de la rimedo.

Kubernetes API

Vi verŝajne konas la metodojn CoreV1().Pods().Update(), replaceNamespacedServicepatch_namespaced_deployment, se vi laboras kun aretoj per klienta biblioteko por Kubernetes API uzante iun programlingvon. La biblioteko pritraktas ĉi tiujn metodojn per HTTP-petoj uzante la metodojn PUT и PATCH... En kio update и replace uzi PUTkaj patch, kiom ajn bagatela ĝi estu, uzas PATCH.

Indas rimarki tion kubectl ankaŭ funkcias kun aretoj per API. Alivorte, kubectlestas envolvaĵo supre de la klienta biblioteko por la lingvo Go, kiu plejparte disponigas la kapablon provizi subkomandojn en pli kompakta kaj legebla formo aldone al la normaj API-kapabloj. Ekzemple, kiel vi eble jam rimarkis, la metodo apply ne estis menciita supre en la antaŭa paragrafo. Nuntempe (majo 2020, ĉ. tradukisto) ĉiu logiko kubectl apply, t.e. krei neekzistantajn rimedojn kaj ĝisdatigi ekzistantajn, funkcias tute ĉe la koda flanko kubectl. Oni klopodas pri logika translokigo apply al la API-flanko, sed ĝi ankoraŭ estas en beta. Mi skribos pli detale sube.

Flikaĵo defaŭlte

Plej bone uzata patch, se vi volas ĝisdatigi la rimedon. Jen kiel ambaŭ klientbibliotekoj funkcias supre de la Kubernetes API kaj kubectl (ne surprize, ĉar ĝi estas envolvaĵo por la klienta biblioteko, ĉ. tradukisto).

Laboru strategie

Ĉiuj teamoj kubectl apply, edit и patch uzu la metodon PATCH en HTTP-petoj ĝisdatigi ekzistantan rimedon. Se vi pli detale pliprofundigas la efektivigon de komandoj, tiam ĉiuj uzas la aliron strategia-kunfanda flikaĵo ĝisdatigi rimedojn, kvankam la komando patch povas uzi aliajn alirojn (pli pri tio ĉi malsupre). La strategia-kunfanda flikaliro provas "ĝustigi ĝin" kunfandante la provizitan specifon kun la ekzistanta specifo. Pli specife, ĝi provas kombini kaj objektojn kaj tabelojn, kio signifas, ke la ŝanĝoj tendencas esti aldonaj. Ekzemple, ruli la komandon patch kun nova mediovariablo en la podujo-specifo, igas tiun mediovariablon esti aldonita al la ekzistantaj mediovariabloj prefere ol anstataŭi ilin. Por forigi ĉi tiun aliron, vi devas devigi la parametran valoron nul en la provizita specifo. Kiu el la teamoj kubectl Ĉu estas plej bone uzi por ĝisdatigo?

Se vi kreas kaj administras viajn rimedojn uzante kubectl apply, dum ĝisdatigo estas pli bone ĉiam uzi kubectl applyal kubectl povis administri agordon kaj ĝuste spuri petitajn ŝanĝojn de aplikaĵo al aplikaĵo. Avantaĝo ĉiam uzu apply estas ke ĝi konservas trakon de antaŭe aplikata specifo, permesante al ĝi scii kiam specifecoj kaj tabelelementoj estas eksplicite forigitaj. Ĉi tio permesas vin uzi apply forigi trajtojn kaj tabelelementojn, dum normala strategia kunfandiĝo ne funkcios. Teamoj edit и patch ne ĝisdatigu notojn tion kubectl apply uzas por spuri ĝiajn ŝanĝojn, do ĉiuj ŝanĝoj kiuj estas spuritaj kaj faritaj per la Kubernetes API, sed faritaj per komandoj edit и patch, nevidebla al postaj komandoj applytio estas apply ne forigas ilin eĉ se ili ne aperas en la eniga specifo por apply (La dokumentaro diras tion edit и patch fari ĝisdatigojn al la uzataj notoj apply, sed praktike - ne).

Se vi ne uzas la komandon apply, povas esti uzata kiel edit, kaj patch, elektante la komandon kiu plej konvenas al la farita ŝanĝo. Aldonante kaj ŝanĝante BOM-ecojn, ambaŭ aliroj estas proksimume la samaj. Kiam vi forigas specifajn proprietojn aŭ tabelelementojn edit kondutas kiel unufoja lanĉo apply, inkluzive de konservi trakon de kia estis la specifo antaŭ kaj post kiam ĝi estis redaktita, do vi povas eksplicite forigi trajtojn kaj tabelelementojn de rimedo. Vi devas eksplicite agordi la posedaĵvaloron al nulo en la specifo por patchforigi ĝin el la rimedo. Forigi tabelelementon uzantan strategia-kunfandan flikaĵon estas pli kompleksa ĉar ĝi postulas la uzon de kunfandaj direktivoj. Vidu aliajn ĝisdatigajn alirojn sube por pli realigeblaj alternativoj.

Efektivigi ĝisdatigajn metodojn en la klienta biblioteko, kiuj kondutas simile al la supraj komandoj kubectl, devus esti agordita en petoj content-type в application/strategic-merge-patch+json. Se vi volas forigi trajtojn en specifo, vi devas eksplicite agordi iliajn valorojn al nulo simile. kubectl patch. Se vi bezonas forigi tabelelementojn, vi devus inkluzivi kunfandi direktivojn en la ĝisdatiga specifo aŭ uzi malsaman aliron al ĝisdatigoj.

Aliaj aliroj al ĝisdatigoj

Kubernetes subtenas du aliajn ĝisdatigajn alirojn: JSON kunfandi flikaĵo и JSON flikaĵo. La JSON-kunfanda flikaliro prenas partan Kubernetes-specifon kiel enigaĵon kaj subtenas kunfandi objektojn similajn al la strategia-kunfanda flikaliro. La diferenco inter la du estas, ke ĝi nur subtenas tabelanstataŭaĵon, inkluzive de la uja tabelo en la podspecifo. Ĉi tio signifas, ke kiam vi uzas JSON-kunfandan diakilon, vi devas provizi kompletajn specifojn por ĉiuj ujoj en la okazo ke iu ajn posedaĵo de iu ajn ujo ŝanĝiĝas. Do ĉi tiu aliro estas utila por forigi elementojn de tabelo en BOM. Sur la komandlinio vi povas elekti JSON kunfandi diakilon uzante kubectl patch --type=merge. Kiam vi laboras kun la Kubernetes API, vi devas uzi la petan metodon PATCH kaj instalado content-type в application/merge-patch+json.

La JSON-flaĉa aliro, anstataŭ provizi partan specifon de rimedo, uzas provizi la ŝanĝojn, kiujn vi volas fari al la rimedo kiel tabelo, en kiu ĉiu elemento de la tabelo reprezentas priskribon de la ŝanĝo farita al la rimedo. Ĉi tiu aliro estas pli fleksebla kaj potenca maniero esprimi la ŝanĝojn faritajn, sed koste de listigi la ŝanĝojn faritajn en aparta, ne-Kubernetes-formato, prefere ol sendado de parta rimedspecifo. EN kubectl vi povas elekti JSON-diakilon uzante kubectl patch --type=json. Kiam vi uzas la Kubernetes API, ĉi tiu aliro funkcias per la peta metodo PATCH kaj instalado content-type в application/json-patch+json.

Ni bezonas konfidon - uzu anstataŭi

En iuj kazoj, vi devas esti certa, ke neniuj ŝanĝoj estas faritaj al rimedo inter la tempo kiam la rimedo estas legita kaj kiam ĝi estas ĝisdatigita. Alivorte, vi devus certigi, ke ĉiuj ŝanĝoj estos atoma. En ĉi tiu kazo, por ĝisdatigi rimedojn vi devus uzi replace. Ekzemple, se vi havas ConfigMap kun nombrilo kiu estas ĝisdatigita de pluraj fontoj, vi devus esti certa ke du fontoj ne ĝisdatigas la nombrilon samtempe, kaŭzante la ĝisdatigon esti perdita. Por pruvi, imagu sinsekvon de eventoj uzante la aliron patch:

  • A kaj B ricevas la nunan staton de la rimedo de la API
  • Ĉiu loke ĝisdatigas la specifon pliigante la nombrilon je unu kaj ankaŭ aldonante "A" aŭ "B" respektive al la "ĝisdatigita per" noto
  • Kaj ĝi ĝisdatigas la rimedon iom pli rapide
  • B ĝisdatigas la rimedon

Kiel rezulto, ĝisdatigo A estas perdita. Lasta operacio patch gajnas, la nombrilo estas pliigita je unu anstataŭe de du, kaj la valoro de la "ĝisdatigita-per" noto finiĝas kun "B" kaj ne enhavas "A". Ni komparu la supre kun kio okazas kiam ĝisdatigoj estas faritaj per la aliro replace:

  • A kaj B ricevas la nunan staton de la rimedo de la API
  • Ĉiu loke ĝisdatigas la specifon pliigante la nombrilon je unu kaj ankaŭ aldonante "A" aŭ "B" respektive al la "ĝisdatigita per" noto
  • Kaj ĝi ĝisdatigas la rimedon iom pli rapide
  • B provas ĝisdatigi la rimedon, sed la ĝisdatigo estas malakceptita de la API ĉar la rimedversio estas en la specifo replace ne kongruas kun la nuna versio de la rimedo en Kubernetes ĉar la versio de la rimedo estis pliigita per la anstataŭiga operacio de A.

En la supra kazo, B devos repreni la rimedon, fari ŝanĝojn al la nova stato kaj provi denove replace. Ĉi tio igos la nombrilon esti pliigita je du kaj la "ĝisdatigita-per" noto inkluzivi "AB" ĉe la fino.

La supra ekzemplo implicas tion dum ekzekuto replace La tuta rimedo estas tute anstataŭigita. Specifo uzata por replace, ne devas esti parta, aŭ en partoj kiel en apply, sed kompleta, inkluzive de la aldono resourceVersion en la specifmetadatumojn. Se vi ne ebligis resourceVersion aŭ la versio kiun vi provizas ne estas aktuala, la anstataŭaĵo estos malakceptita. Do la plej bona aliro por uzi estas replace – legu la rimedon, ĝisdatigu ĝin kaj anstataŭigu ĝin tuj. Uzanta kubectl, ĝi povus aspekti jene:

$ kubectl get deployment my-deployment -o json 
    | jq '.spec.template.spec.containers[0].env[1].value = "new value"' 
    | kubectl replace -f -

Indas noti, ke la sekvaj du komandoj, ekzekutitaj sinsekve, efektiviĝos sukcese, ĉar deployment.yaml ne enhavas posedaĵon .metadata.resourceVersion

$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml

Ĉi tio ŝajnus kontraŭdiri tion supre dirite, t.e. "aldonante resourceVersion en la specifmetadatumojn." Ĉu estas malĝuste diri tion? Ne, ĝi ne estas, ĉar se kubectl rimarkas, ke vi ne specifis resourceVersion, ĝi legos ĝin el la rimedo kaj aldonos ĝin al la specifo, kiun vi specifis, kaj nur tiam ekzekutos ĝin replace. Ĉar ĉi tio estas potenciale danĝera se vi fidas je atomeco, la magio funkcias tute flanke kubectl, vi ne devus fidi je ĝi kiam vi uzas klientajn bibliotekojn, kiuj funkcias kun la API. En ĉi tiu kazo vi devos legi la nunan rimedan specifon, ĝisdatigi ĝin kaj poste ekzekuti PUT peto.

Vi ne povas fari flikaĵon - ni anstataŭigas

Kelkfoje vi devas fari iujn ŝanĝojn, kiuj ne povas esti pritraktitaj de la API. En ĉi tiuj kazoj, vi povas devigi anstataŭigon de la rimedo forigante kaj rekreante ĝin. Ĉi tio estas farita uzante kubectl replace --force. Ruli la komandon tuj forigas la rimedojn kaj poste rekreas ilin el la provizita specifo. Ne ekzistas "forta anstataŭigo" pritraktilo en la API, kaj por fari tion per la API, vi devas fari du operaciojn. Unue vi devas forigi la rimedon agordante por ĝi gracePeriodSeconds al nulo (0) kaj propagationPolicy en "Fono" kaj poste rekreu ĉi tiun rimedon kun la dezirata specifo.

Averto: Ĉi tiu aliro estas eble danĝera kaj povas konduki al nedifinita stato.

Apliku ĉe la servilo

Kiel menciite supre, Kubernetes-programistoj laboras por efektivigi la logikon apply el kubectl en la Kubernetes API. Logikoj apply havebla en Kubernetes 1.18 tra kubectl apply --server-side aŭ per la API uzante la metodon PATCH с content-type application/apply-patch+YAML.

Noto: JSON ankaŭ validas YAML, do vi povas sendi la specifon kiel JSON eĉ se content-type estos application/apply-patch+yaml.

Krom tiu logiko kubectl iĝas havebla al ĉiuj per API, apply sur la servilflanko, konservas trakon de kiu respondecas pri la kampoj en la specifo, tiel permesante sekuran multoblan aliron por ĝia senkonflikta redaktado. Alivorte, se apply sur la servilo-flanko pli disvastiĝos, universala sekura administradinterfaco de rimedoj aperos por malsamaj klientoj, ekzemple, kubectl, Pulumi aŭ Terraform, GitOps, kaj ankaŭ mem-skribitaj skriptoj uzante klientajn bibliotekojn.

Rezultoj

Mi esperas, ke ĉi tiu mallonga superrigardo de malsamaj manieroj ĝisdatigi rimedojn en aretoj estis helpema al vi. Estas bone scii, ke ĝi ne estas nur apliki kontraŭ anstataŭi; estas eble ĝisdatigi rimedon uzante apliki, redakti, fliki aŭ anstataŭigi. Post ĉio, principe, ĉiu aliro havas sian propran amplekson. Por atomŝanĝoj, anstataŭigo estas preferinda; alie, vi devus uzi strategia-kunfandi flikilon per apliki. Almenaŭ, mi atendas, ke vi komprenos, ke vi ne povas fidi Guglon aŭ StackOerflow serĉante "kubernetes apply vs replace". Almenaŭ ĝis ĉi tiu artikolo anstataŭigos la nunan respondon.

Taŭga Komparo de Kubernetes Apliki, Anstataŭigi kaj Flikilo

fonto: www.habr.com

Aldoni komenton