Confronto corretto tra applicazione, sostituzione e patch di Kubernetes

Kubernetes dispone di diverse opzioni per l'aggiornamento delle risorse: applica, modifica, applica patch e sostituisci. C'è confusione su cosa fa ciascuno e quando usarli. Scopriamolo.

Confronto corretto tra applicazione, sostituzione e patch di Kubernetes

se cercare su Google si trova la frase "kubernetes applica vs sostituisci". risposta a StackOverflow, il che non è corretto. Durante la ricerca "kubernetes apply vs patch" il primo collegamento è la documentazione per kubectl patch, che non include il confronto apply и patch. Questo articolo esaminerà le diverse opzioni, nonché l'uso corretto di ciascuna di esse.

Durante il ciclo di vita di una risorsa Kubernetes (servizio, distribuzione, ingresso, ecc.), a volte è necessario modificare, aggiungere o rimuovere alcune proprietà di questa risorsa. Ad esempio, aggiungi una nota, aumenta o diminuisci il numero di repliche.

CLI di Kubernetes

Se stai già lavorando con i cluster Kubernetes tramite la CLI, hai già familiarità con apply и edit. Squadra apply legge la specifica della risorsa dal file e crea un "upsert" nel cluster Kubernetes, ad es. crea la risorsa se non esiste e la aggiorna se esiste. Squadra edit legge una risorsa tramite l'API, quindi scrive la specifica della risorsa in un file locale, che viene quindi aperto in un editor di testo. Dopo aver modificato e salvato il file, kubectl invierà le modifiche apportate tramite l'API, che applicherà attentamente queste modifiche alla risorsa.

Non tutti conoscono i comandi patch и replace. Squadra patch consente di modificare parte della specifica di una risorsa, fornendo solo la parte modificata sulla riga di comando. Squadra replace funziona allo stesso modo di edit, ma tutto deve essere fatto manualmente: è necessario scaricare la versione corrente delle specifiche della risorsa, ad esempio utilizzando kubectl get -o yaml, modificalo, quindi utilizza replace per aggiornare una risorsa in base a una specifica modificata. Squadra replace non funzionerà se si sono verificati cambiamenti tra la lettura e la sostituzione della risorsa.

API di Kubernetes

Probabilmente hai familiarità con i metodi CoreV1().Pods().Update(), replaceNamespacedService o patch_namespaced_deployment, se lavori con i cluster tramite libreria client per l'API Kubernetes utilizzando qualche linguaggio di programmazione. La libreria gestisce questi metodi tramite richieste HTTP utilizzando i metodi PUT и PATCH. In questo caso, update и replace usato PUTE patch, non importa quanto banale possa essere, usa PATCH.

Va notato che kubectl funziona anche con i cluster tramite API. In altre parole, kubectlè un wrapper sopra la libreria client per il linguaggio Go, che offre in gran parte la possibilità di fornire sottocomandi in una forma più compatta e leggibile oltre alle funzionalità API standard. Ad esempio, come avrai già notato, il metodo apply non è stato menzionato sopra nel paragrafo precedente. Attualmente (maggio 2020, ca. traduttore) tutta logica kubectl apply, cioè. la creazione di risorse inesistenti e l'aggiornamento di quelle esistenti funziona interamente dal lato del codice kubectl. Si stanno facendo degli sforzi sul trasferimento logico apply al lato API, ma è ancora in versione beta. Scriverò più dettagliatamente di seguito.

Patch per impostazione predefinita

Meglio usato patch, se desideri aggiornare la risorsa. Ecco come funzionano entrambe le librerie client sull'API Kubernetes e kubectl (non sorprende, poiché è un wrapper per la libreria client, ca. traduttore).

Lavora in modo strategico

Tutte le squadre kubectl apply, edit и patch utilizzare il metodo PATCH nelle richieste HTTP per aggiornare una risorsa esistente. Se approfondisci l'implementazione dei comandi in modo più dettagliato, tutti utilizzano l'approccio patch di fusione strategica per aggiornare le risorse, anche se il comando patch possono utilizzare altri approcci (ne parleremo più avanti). L'approccio di fusione strategica delle patch tenta di "fare le cose bene" unendo la specifica fornita con quella esistente. Più specificamente, tenta di combinare sia oggetti che array, il che significa che le modifiche tendono ad essere cumulative. Ad esempio, eseguendo il comando patch con una nuova variabile di ambiente nella specifica del contenitore pod, fa sì che tale variabile di ambiente venga aggiunta alle variabili di ambiente esistenti anziché sovrascriverle. Per rimuovere utilizzando questo approccio, è necessario forzare il valore del parametro su null nella specifica fornita. Quale delle squadre kubectl È meglio usarlo per l'aggiornamento?

Se crei e gestisci le tue risorse utilizzando kubectl apply, durante l'aggiornamento è meglio utilizzare sempre kubectl applyA kubectl potrebbe gestire la configurazione e tenere traccia correttamente delle modifiche richieste da un'applicazione all'altra. Utilizzare sempre il vantaggio apply è che tiene traccia di una specifica applicata in precedenza, consentendogli di sapere quando le proprietà della specifica e gli elementi dell'array vengono rimossi esplicitamente. Ciò ti consente di utilizzare apply per rimuovere proprietà ed elementi dell'array, mentre una normale unione strategica non funzionerà. Squadre edit и patch non aggiornare le note kubectl apply utilizza per tenere traccia delle modifiche, quindi qualsiasi modifica tracciata e apportata tramite l'API Kubernetes, ma apportata tramite comandi edit и patch, invisibile ai comandi successivi applyCioè, apply non li rimuove anche se non compaiono nella specifica di input per apply (Lo dice la documentazione edit и patch apportare aggiornamenti alle note utilizzate apply, ma in pratica - no).

Se non usi il comando apply, può essere utilizzato come editE patch, scegliendo il comando che meglio si adatta alla modifica che si sta apportando. Quando si aggiungono e si modificano le proprietà della distinta base, entrambi gli approcci sono più o meno gli stessi. Quando si eliminano proprietà di specifica o elementi di array edit si comporta come un lancio una tantum apply, incluso tenere traccia di come erano le specifiche prima e dopo la modifica, in modo da poter rimuovere in modo esplicito proprietà ed elementi di matrice da una risorsa. È necessario impostare esplicitamente il valore della proprietà su null nella specifica di patchper rimuoverlo dalla risorsa. La rimozione di un elemento dell'array utilizzando l'applicazione di patch di unione strategica è più complessa perché richiede l'uso di direttive di unione. Vedi altri approcci di aggiornamento di seguito per alternative più praticabili.

Per implementare metodi di aggiornamento nella libreria client che si comportino in modo simile ai comandi precedenti kubectl, dovrebbe essere impostato nelle richieste content-type в application/strategic-merge-patch+json. Se desideri rimuovere proprietà in una specifica, devi impostare esplicitamente i loro valori su null in modo simile kubectl patch. Se è necessario rimuovere elementi dell'array, è necessario includere direttive di unione nella specifica dell'aggiornamento o utilizzare un approccio diverso agli aggiornamenti.

Altri approcci agli aggiornamenti

Kubernetes supporta altri due approcci di aggiornamento: Patch di unione JSON и Patch JSON. L'approccio della patch di unione JSON accetta una specifica Kubernetes parziale come input e supporta l'unione di oggetti in modo simile all'approccio di patch di unione strategica. La differenza tra i due è che supporta solo la sostituzione dell'array, incluso l'array del contenitore nelle specifiche del pod. Ciò significa che quando si utilizza una patch di unione JSON, è necessario fornire specifiche complete per tutti i contenitori nel caso in cui venga modificata una proprietà di qualsiasi contenitore. Quindi questo approccio è utile per rimuovere elementi da un array in una distinta base. Nella riga di comando è possibile selezionare la patch di unione JSON utilizzando kubectl patch --type=merge. Quando lavori con l'API Kubernetes, dovresti utilizzare il metodo request PATCH e installazione content-type в application/merge-patch+json.

L'approccio patch JSON, invece di fornire una specifica parziale di una risorsa, utilizza le modifiche che desideri apportare alla risorsa come un array, in cui ciascun elemento dell'array rappresenta una descrizione della modifica apportata alla risorsa. Questo approccio rappresenta un modo più flessibile e potente per esprimere le modifiche apportate, ma al costo di elencare le modifiche apportate in un formato separato, non Kubernetes, anziché inviare una specifica parziale della risorsa. IN kubectl è possibile selezionare la patch JSON utilizzando kubectl patch --type=json. Quando si utilizza l'API Kubernetes, questo approccio funziona utilizzando il metodo request PATCH e installazione content-type в application/json-patch+json.

Abbiamo bisogno di fiducia: usa la sostituzione

In alcuni casi, è necessario assicurarsi che non vengano apportate modifiche a una risorsa tra il momento in cui la risorsa viene letta e il momento in cui viene aggiornata. In altre parole, dovresti assicurarti che tutte le modifiche vengano apportate atomico. In questo caso, per aggiornare le risorse dovresti usare replace. Ad esempio, se si dispone di una ConfigMap con un contatore aggiornato da più origini, è necessario assicurarsi che due origini non aggiornino il contatore contemporaneamente, causando la perdita dell'aggiornamento. Per dimostrarlo, immagina una sequenza di eventi utilizzando l'approccio patch:

  • A e B ottengono lo stato corrente della risorsa dall'API
  • Ognuno aggiorna localmente la specifica incrementando il contatore di uno e aggiungendo rispettivamente "A" o "B" alla nota "aggiornato da"
  • E aggiorna la risorsa un po' più velocemente
  • B aggiorna la risorsa

Di conseguenza, l'aggiornamento A viene perso. Ultima operazione patch vince, il contatore viene incrementato di uno invece di due e il valore della banconota "aggiornato da" termina con "B" e non contiene "A". Confrontiamo quanto sopra con ciò che accade quando gli aggiornamenti vengono eseguiti utilizzando l'approccio replace:

  • A e B ottengono lo stato corrente della risorsa dall'API
  • Ognuno aggiorna localmente la specifica incrementando il contatore di uno e aggiungendo rispettivamente "A" o "B" alla nota "aggiornato da"
  • E aggiorna la risorsa un po' più velocemente
  • B tenta di aggiornare la risorsa, ma l'aggiornamento viene rifiutato dall'API perché la versione della risorsa è nella specifica replace non corrisponde alla versione corrente della risorsa in Kubernetes perché la versione della risorsa è stata aumentata dall'operazione di sostituzione di A.

Nel caso precedente, B dovrà recuperare la risorsa, apportare modifiche al nuovo stato e riprovare replace. Ciò farà sì che il contatore venga incrementato di due e che la nota "aggiornato da" includa "AB" alla fine.

L'esempio precedente implica che durante l'esecuzione replace L'intera risorsa viene completamente sostituita. Specifica utilizzata per replace, non deve essere parziale, o in parti come in apply, ma completo, compresa l'aggiunta resourceVersion nei metadati della specifica. Se non hai abilitato resourceVersion o la versione fornita non è aggiornata, la sostituzione verrà rifiutata. Quindi l'approccio migliore da utilizzare è replace – leggere la risorsa, aggiornarla e sostituirla immediatamente. Utilizzando kubectl, potrebbe assomigliare a questo:

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

Vale la pena notare che i seguenti due comandi, eseguiti in sequenza, verranno eseguiti correttamente, poiché deployment.yaml non contiene proprietà .metadata.resourceVersion

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

Ciò sembrerebbe contraddire quanto detto sopra, cioè "aggiungendo resourceVersion nei metadati delle specifiche." È sbagliato dirlo? No, non lo è, perché if kubectl nota che non hai specificato resourceVersion, lo leggerà dalla risorsa e lo aggiungerà alla specifica specificata, e solo successivamente lo eseguirà replace. Poiché questo è potenzialmente pericoloso se si fa affidamento sull'atomicità, la magia funziona interamente in modo laterale kubectl, non dovresti fare affidamento su di esso quando usi le librerie client che funzionano con l'API. In questo caso dovrai leggere la specifica della risorsa corrente, aggiornarla e quindi eseguirla PUT richiesta.

Non puoi fare una patch: facciamo una sostituzione

A volte è necessario apportare alcune modifiche che non possono essere gestite dall'API. In questi casi è possibile forzare la sostituzione della risorsa eliminandola e ricreandola. Questo viene fatto utilizzando kubectl replace --force. L'esecuzione del comando rimuove immediatamente le risorse e quindi le ricrea dalla specifica fornita. Non esiste un gestore di "sostituzione forzata" nell'API e per farlo tramite l'API è necessario eseguire due operazioni. Per prima cosa devi eliminare la risorsa impostandola gracePeriodSeconds a zero (0) e propagationPolicy in "Sfondo" e quindi ricreare questa risorsa con la specifica desiderata.

Avvertenza: questo approccio è potenzialmente pericoloso e può portare a uno stato indefinito.

Applicare sul lato server

Come accennato in precedenza, gli sviluppatori Kubernetes stanno lavorando all'implementazione della logica apply di kubectl nell'API Kubernetes. Logiche apply disponibile in Kubernetes 1.18 tramite kubectl apply --server-side o tramite l'API utilizzando il metodo PATCH с content-type application/apply-patch+YAML.

Nota: JSON è anche YAML valido, quindi puoi inviare la specifica come JSON anche se content-type volontà application/apply-patch+yaml.

Oltre a quella logica kubectl diventa disponibile a tutti tramite API, apply lato server, tiene traccia di chi è responsabile dei campi nella specifica, consentendo così un accesso multiplo sicuro per la sua modifica senza conflitti. In altre parole, se apply sul lato server diventerà più diffuso, apparirà un'interfaccia universale sicura di gestione delle risorse per diversi client, ad esempio kubectl, Pulumi o Terraform, GitOps, nonché script autoprodotti utilizzando le librerie client.

Risultati di

Spero che questa breve panoramica dei diversi modi per aggiornare le risorse nei cluster ti sia stata utile. È bello sapere che non si tratta solo di applicare o sostituire; è possibile aggiornare una risorsa utilizzando applica, modifica, patch o sostituisci. Dopotutto, in linea di principio, ogni approccio ha il proprio campo di applicazione. Per le modifiche atomiche, è preferibile la sostituzione; altrimenti, è necessario utilizzare la patch di unione strategica tramite applica. Per lo meno, mi aspetto che tu capisca che non puoi fidarti di Google o StackOerflow quando cerchi "kubernetes applica vs sostituisci". Almeno finché questo articolo non sostituirà la risposta attuale.

Confronto corretto tra applicazione, sostituzione e patch di Kubernetes

Fonte: habr.com

Aggiungi un commento