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.
Si 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 PUT
и PATCH
... On update
и replace
ús PUT
I 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 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 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 apply
i 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 apply
Això é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 edit
I 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 patch
per 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ó: 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
voluntatapplication/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.
Font: www.habr.com