Comparació adequada de l'aplicació, substitució i pedaç de Kubernetes

Kubernetes té diverses opcions per actualitzar recursos: aplicar, editar, aplicar pedaços i substituir. Hi ha confusió sobre què fa cadascú i quan utilitzar-los. Anem a esbrinar-ho.

Comparació adequada de l'aplicació, substitució i pedaç de Kubernetes

Si cerca a Google es troba la frase "kubernetes s'aplica vs reemplaça". respon a StackOverflow, que no és correcte. En buscar "kubernetes apply vs patch" el primer enllaç és la documentació kubectl patch, que no inclou comparacions apply и patch. Aquest article analitzarà les diferents opcions, així com l'ús adequat de cadascuna.

Durant el cicle de vida d'un recurs de Kubernetes (servei, desplegament, entrada, etc.), de vegades cal canviar, afegir o eliminar algunes propietats d'aquest recurs. Per exemple, afegir una nota, augmentar o disminuir el nombre de rèpliques.

CLI de Kubernetes

Si ja esteu treballant amb clústers de Kubernetes mitjançant la CLI, ja ho coneixeu apply и edit. Equip apply llegeix l'especificació del recurs del fitxer i fa un "upsert" al clúster de Kubernetes, és a dir. crea el recurs si no existeix i l'actualitza si existeix. Equip edit llegeix un recurs mitjançant l'API i després escriu l'especificació del recurs en un fitxer local, que s'obre en un editor de text. Després d'editar i desar el fitxer, kubectl enviarà els canvis fets a través de l'API, que aplicarà amb cura aquests canvis al recurs.

No tothom coneix les ordres patch и replace. Equip patch us permet canviar part d'una especificació de recurs, proporcionant només la part modificada a la línia d'ordres. Equip replace funciona igual que edit, però tot s'ha de fer manualment: heu de descarregar la versió actual de l'especificació del recurs, per exemple, utilitzant kubectl get -o yaml, editeu-lo i després feu servir replace per actualitzar un recurs segons una especificació modificada. Equip replace no funcionarà si s'ha produït cap canvi entre la lectura i la substitució del recurs.

API de Kubernetes

Probablement coneixeu els mètodes CoreV1().Pods().Update(), replaceNamespacedService o patch_namespaced_deployment, si treballeu amb clústers mitjançant biblioteca client per a l'API de Kubernetes utilitzant algun llenguatge de programació. La biblioteca gestiona aquests mètodes mitjançant peticions HTTP mitjançant els mètodes PUT и PATCH... On update и replace ús PUTI patch, per trivial que sigui, utilitza PATCH.

Cal assenyalar que kubectl també funciona amb clústers mitjançant API. En altres paraules, kubectlés un embolcall a la part superior de la biblioteca del client per a l'idioma Go, que ofereix en gran mesura la possibilitat de proporcionar subordres d'una forma més compacta i llegible a més de les capacitats estàndard de l'API. Per exemple, com potser ja heu notat, el mètode apply no s'ha esmentat anteriorment en el paràgraf anterior. Actualment (maig de 2020, aprox. traductor) tota lògica kubectl apply, és a dir la creació de recursos inexistents i l'actualització dels existents, funciona completament en el costat del codi kubectl. S'estan fent esforços sobre la transferència lògica apply al costat de l'API, però encara està en versió beta. Escriuré amb més detall a continuació.

Pegat per defecte

Millor utilitzat patch, si voleu actualitzar el recurs. Així és com funcionen ambdues biblioteques de client a la part superior de l'API de Kubernetes i kubectl (no és sorprenent, ja que és un embolcall per a la biblioteca del client, aprox. traductor).

Treballar estratègicament

Tots els equips kubectl apply, edit и patch utilitzar el mètode PATCH a les sol·licituds HTTP per actualitzar un recurs existent. Si aprofundeix en la implementació de les ordres amb més detall, tots utilitzen l'enfocament pegats de combinació estratègica per actualitzar recursos, encara que l'ordre patch pot utilitzar altres enfocaments (més sobre això a continuació). L'enfocament de pedaços de combinació estratègica intenta "fer-ho bé" fusionant l'especificació subministrada amb l'especificació existent. Més concretament, intenta combinar objectes i matrius, la qual cosa significa que els canvis solen ser additius. Per exemple, executant l'ordre patch amb una nova variable d'entorn a l'especificació del contenidor del pod, fa que aquesta variable d'entorn s'afegeixi a les variables d'entorn existents en lloc de sobreescriure-les. Per eliminar amb aquest enfocament, heu de forçar el valor del paràmetre a nul a l'especificació proporcionada. Quin dels equips kubectl És millor utilitzar-lo per actualitzar?

Si creeu i gestioneu els vostres recursos utilitzant kubectl apply, en actualitzar és millor utilitzar-lo sempre kubectl applyi que kubectl podria gestionar la configuració i fer un seguiment adequat dels canvis sol·licitats d'una aplicació a una altra. Avantatge utilitzar sempre apply és que fa un seguiment d'una especificació aplicada prèviament, cosa que li permet saber quan s'eliminen explícitament les propietats de l'especificació i els elements de la matriu. Això us permet utilitzar apply per eliminar propietats i elements de matriu, mentre que una fusió estratègica normal no funcionarà. Equips edit и patch no actualitzeu les notes que kubectl apply utilitza per fer un seguiment dels seus canvis, de manera que qualsevol canvi que es fa un seguiment i es fa mitjançant l'API de Kubernetes, però que es fa mitjançant ordres edit и patch, invisible per a les ordres posteriors applyAixò és, apply no els elimina encara que no apareguin a l'especificació d'entrada per apply (La documentació diu això edit и patch fer actualitzacions de les notes utilitzades apply, però a la pràctica - no).

Si no feu servir l'ordre apply, es pot utilitzar com a editI patch, escollint l'ordre que millor s'adapti al canvi que s'està realitzant. Quan s'afegeixen i es canvien les propietats de la BOM, els dos enfocaments són aproximadament els mateixos. Quan s'esborren propietats d'especificació o elements de matriu edit es comporta com un llançament únic apply, inclòs fer un seguiment de com era l'especificació abans i després d'editar-la, de manera que pugueu eliminar de manera explícita propietats i elements de matriu d'un recurs. Heu d'establir explícitament el valor de la propietat com a nul a l'especificació de patchper eliminar-lo del recurs. L'eliminació d'un element de matriu mitjançant pedaços de combinació estratègica és més complex perquè requereix l'ús de directives de combinació. Consulteu altres enfocaments d'actualització a continuació per obtenir alternatives més viables.

Per implementar mètodes d'actualització a la biblioteca del client que es comporten de manera similar a les ordres anteriors kubectl, s'ha d'establir a les sol·licituds content-type в application/strategic-merge-patch+json. Si voleu eliminar propietats d'una especificació, heu d'establir explícitament els seus valors a null de manera similar kubectl patch. Si necessiteu eliminar elements de la matriu, hauríeu d'incloure directives de combinació a l'especificació d'actualització o utilitzar un enfocament diferent per a les actualitzacions.

Altres enfocaments de les actualitzacions

Kubernetes admet altres dos enfocaments d'actualització: Pedaç de combinació JSON и Pedaç JSON. L'enfocament de pedaç de fusió JSON pren una especificació parcial de Kubernetes com a entrada i admet la fusió d'objectes similars a l'enfocament de pedaç de fusió estratègica. La diferència entre tots dos és que només admet la substitució de matrius, inclosa la matriu de contenidors a l'especificació del pod. Això vol dir que quan utilitzeu un pedaç de combinació JSON, heu de proporcionar especificacions completes per a tots els contenidors en cas que canviï alguna propietat d'algun contenidor. Per tant, aquest enfocament és útil per eliminar elements d'una matriu en una LDM. A la línia d'ordres, podeu seleccionar el pegat de combinació JSON mitjançant kubectl patch --type=merge. Quan treballeu amb l'API de Kubernetes, hauríeu d'utilitzar el mètode de sol·licitud PATCH i instal·lació content-type в application/merge-patch+json.

L'enfocament del pedaç JSON, en lloc de proporcionar una especificació parcial d'un recurs, utilitza proporcionar els canvis que voleu fer al recurs com a matriu, en què cada element de la matriu representa una descripció del canvi que s'està realitzant al recurs. Aquest enfocament és una manera més flexible i potent d'expressar els canvis que s'estan realitzant, però a costa d'enumerar els canvis que s'estan realitzant en un format separat, que no sigui de Kubernetes, en lloc d'enviar una especificació parcial del recurs. EN kubectl podeu seleccionar el pedaç JSON mitjançant kubectl patch --type=json. Quan s'utilitza l'API de Kubernetes, aquest enfocament funciona mitjançant el mètode de sol·licitud PATCH i instal·lació content-type в application/json-patch+json.

Necessitem confiança: utilitzeu substituir

En alguns casos, cal assegurar-se que no es fan canvis en un recurs entre el moment en què es llegeix el recurs i el moment en què s'actualitza. En altres paraules, hauríeu d'assegurar-vos que tots els canvis seran atòmic. En aquest cas, per actualitzar els recursos que hauríeu d'utilitzar replace. Per exemple, si teniu un ConfigMap amb un comptador que s'actualitza per diverses fonts, hauríeu d'assegurar-vos que dues fonts no actualitzin el comptador alhora, la qual cosa farà que es perdi l'actualització. Per demostrar-ho, imagineu una seqüència d'esdeveniments utilitzant l'enfocament patch:

  • A i B obtenen l'estat actual del recurs de l'API
  • Cadascun actualitza localment l'especificació augmentant el comptador en un i també afegint "A" o "B" respectivament a la nota "actualitzat per"
  • I actualitza el recurs una mica més ràpid
  • B actualitza el recurs

Com a resultat, es perd l'actualització A. Última operació patch guanya, el comptador s'incrementa en un en lloc de dos, i el valor de la nota "actualitzada per" acaba amb "B" i no conté "A". Comparem l'anterior amb el que passa quan es fan actualitzacions mitjançant l'enfocament replace:

  • A i B obtenen l'estat actual del recurs de l'API
  • Cadascun actualitza localment l'especificació augmentant el comptador en un i també afegint "A" o "B" respectivament a la nota "actualitzat per"
  • I actualitza el recurs una mica més ràpid
  • B intenta actualitzar el recurs, però l'API rebutja l'actualització perquè la versió del recurs es troba a l'especificació replace no coincideix amb la versió actual del recurs a Kubernetes perquè l'operació de substitució d'A ha augmentat la versió del recurs.

En el cas anterior, B haurà de tornar a recuperar el recurs, fer canvis al nou estat i tornar-ho a provar. replace. Això farà que el comptador s'incrementi en dos i que la nota "actualitzada per" inclogui "AB" al final.

L'exemple anterior implica que quan s'executa replace Tot el recurs es substitueix completament. Especificació utilitzada per replace, no ha de ser parcial, ni en parts com en apply, però complet, inclosa l'addició resourceVersion a les metadades de l'especificació. Si no l'heu habilitat resourceVersion o la versió que proporcioneu no és actual, la substitució serà rebutjada. Per tant, el millor enfocament a utilitzar és replace – llegiu el recurs, actualitzeu-lo i substituïu-lo immediatament. Utilitzant kubectl, podria semblar així:

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

Val la pena assenyalar que les dues ordres següents, executades seqüencialment, s'executaran amb èxit, ja que deployment.yaml no conté propietats .metadata.resourceVersion

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

Això sembla contradir el que s'ha dit anteriorment, és a dir. "afegint resourceVersion a les metadades de l'especificació." Està malament dir això? No, no ho és, perquè si kubectl avisos que no heu especificat resourceVersion, el llegirà del recurs i l'afegirà a l'especificació que heu especificat i només després l'executarà replace. Com que això és potencialment perillós si confieu en l'atomicitat, la màgia funciona completament al costat kubectl, no hauríeu de confiar-hi quan feu servir biblioteques de client que funcionen amb l'API. En aquest cas, haureu de llegir l'especificació del recurs actual, actualitzar-la i executar-la PUT petició.

No podeu fer un pegat, nosaltres fem un reemplaçament

De vegades cal fer alguns canvis que l'API no pot gestionar. En aquests casos, podeu forçar la substitució del recurs suprimint-lo i tornant-lo a crear. Això es fa utilitzant kubectl replace --force. L'execució de l'ordre elimina immediatament els recursos i després els recrea a partir de l'especificació subministrada. No hi ha cap controlador de "reemplaçament forçat" a l'API i, per fer-ho mitjançant l'API, heu de realitzar dues operacions. Primer heu de suprimir el recurs configurant-lo gracePeriodSeconds a zero (0) i propagationPolicy a "Fonds" i torneu a crear aquest recurs amb l'especificació desitjada.

Advertència: aquest enfocament és potencialment perillós i pot conduir a un estat indefinit.

Aplicar al costat del servidor

Com s'ha esmentat anteriorment, els desenvolupadors de Kubernetes estan treballant per implementar la lògica apply d' kubectl a l'API de Kubernetes. Lògiques apply disponible a Kubernetes 1.18 via kubectl apply --server-side o mitjançant l'API utilitzant el mètode PATCH с content-type application/apply-patch+YAML.

Nota: JSON també és YAML vàlid, de manera que podeu enviar l'especificació com a JSON encara que sigui content-type voluntat application/apply-patch+yaml.

A més d'aquesta lògica kubectl està disponible per a tothom mitjançant l'API, apply al costat del servidor, fa un seguiment de qui és responsable dels camps de l'especificació, permetent així un accés múltiple segur per a la seva edició sense conflictes. En altres paraules, si apply al costat del servidor s'estendrà més, apareixerà una interfície de gestió de recursos segura universal per a diferents clients, per exemple, kubectl, Pulumi o Terraform, GitOps, així com scripts escrits per compte propi mitjançant biblioteques de client.

Resultats de

Espero que aquesta breu visió general de diferents maneres d'actualitzar els recursos en clústers us hagi estat útil. És bo saber que no només es tracta d'aplicar versus reemplaçar; és possible actualitzar un recurs mitjançant aplicar, editar, aplicar pedaços o substituir. Després de tot, en principi, cada enfocament té la seva pròpia àrea d'aplicació. Per als canvis atòmics, és preferible substituir; en cas contrari, hauríeu d'utilitzar el pegat de combinació estratègica mitjançant l'aplicació. Com a mínim, espero que entengueu que no podeu confiar en Google o StackOerflow quan cerqueu "kubernetes aplica vs reemplaça". Almenys fins que aquest article substitueixi la resposta actual.

Comparació adequada de l'aplicació, substitució i pedaç de Kubernetes

Font: www.habr.com

Afegeix comentari