Το Kubernetes έχει πολλές επιλογές για την ενημέρωση πόρων: εφαρμογή, επεξεργασία, ενημέρωση κώδικα και αντικατάσταση. Υπάρχει σύγχυση σχετικά με το τι κάνει ο καθένας και πότε να τα χρησιμοποιήσει. Ας το καταλάβουμε.
αν kubectl patch
, το οποίο δεν περιλαμβάνει σύγκριση apply
и patch
. Αυτό το άρθρο θα εξετάσει τις διάφορες επιλογές, καθώς και τη σωστή χρήση της καθεμιάς.
Κατά τη διάρκεια του κύκλου ζωής ενός πόρου Kubernetes (υπηρεσία, ανάπτυξη, είσοδος κ.λπ.), μερικές φορές χρειάζεται να αλλάξετε, να προσθέσετε ή να αφαιρέσετε ορισμένες ιδιότητες αυτού του πόρου. Για παράδειγμα, προσθέστε μια σημείωση, αυξήστε ή μειώστε τον αριθμό των αντιγράφων.
Kubernetes CLI
Εάν εργάζεστε ήδη με συμπλέγματα Kubernetes μέσω του CLI, είστε ήδη εξοικειωμένοι apply
и edit
. Ομάδα apply
διαβάζει την προδιαγραφή του πόρου από το αρχείο και κάνει ένα "upsert" στο σύμπλεγμα Kubernetes, δηλ. δημιουργεί τον πόρο εάν δεν υπάρχει και τον ενημερώνει εάν υπάρχει. Ομάδα edit
διαβάζει έναν πόρο μέσω του API και, στη συνέχεια, γράφει την προδιαγραφή του πόρου σε ένα τοπικό αρχείο, το οποίο στη συνέχεια ανοίγει σε ένα πρόγραμμα επεξεργασίας κειμένου. Αφού επεξεργαστείτε και αποθηκεύσετε το αρχείο, kubectl
θα στείλει πίσω τις αλλαγές που έγιναν μέσω του API, το οποίο θα εφαρμόσει προσεκτικά αυτές τις αλλαγές στον πόρο.
Δεν γνωρίζουν όλοι τις εντολές patch
и replace
. Ομάδα patch
σας επιτρέπει να αλλάξετε μέρος μιας προδιαγραφής πόρου, παρέχοντας μόνο το αλλαγμένο τμήμα στη γραμμή εντολών. Ομάδα replace
λειτουργεί το ίδιο με edit
, αλλά όλα πρέπει να γίνουν χειροκίνητα: πρέπει να κάνετε λήψη της τρέχουσας έκδοσης της προδιαγραφής πόρων, για παράδειγμα, χρησιμοποιώντας kubectl get -o yaml
, επεξεργαστείτε το και μετά χρησιμοποιήστε το replace
για να ενημερώσετε έναν πόρο σύμφωνα με μια αλλαγμένη προδιαγραφή. Ομάδα replace
δεν θα λειτουργήσει εάν πραγματοποιηθούν αλλαγές μεταξύ της ανάγνωσης και της αντικατάστασης του πόρου.
Kubernetes API
Μάλλον είστε εξοικειωμένοι με τις μεθόδους CoreV1().Pods().Update()
, replaceNamespacedService
ή patch_namespaced_deployment
, εάν εργάζεστε με συμπλέγματα μέσω PUT
и PATCH
... Εν update
и replace
χρήση PUT
Και patch
, όσο ασήμαντο κι αν είναι, χρησιμοποιεί PATCH
.
Θα πρέπει να σημειωθεί ότι οι kubectl
λειτουργεί επίσης με συμπλέγματα μέσω API. Με άλλα λόγια, kubectl
είναι ένα περιτύλιγμα στην κορυφή της βιβλιοθήκης πελάτη για τη γλώσσα Go, το οποίο παρέχει σε μεγάλο βαθμό τη δυνατότητα παροχής υποεντολών σε πιο συμπαγή και ευανάγνωστη μορφή εκτός από τις τυπικές δυνατότητες API. Για παράδειγμα, όπως ίσως έχετε ήδη παρατηρήσει, η μέθοδος apply
δεν αναφέρθηκε παραπάνω στην προηγούμενη παράγραφο. Επί του παρόντος (Μάιος 2020, περίπου. μεταφράστης) όλη η λογική kubectl apply
, δηλ. η δημιουργία ανύπαρκτων πόρων και η ενημέρωση των υπαρχόντων, λειτουργεί εξ ολοκλήρου από την πλευρά του κώδικα kubectl
. Γίνονται προσπάθειες apply
στην πλευρά του API, αλλά είναι ακόμα σε έκδοση beta. Θα γράψω πιο αναλυτικά παρακάτω.
Ενημερωμένη έκδοση κώδικα από προεπιλογή
Καλύτερα χρησιμοποιημένο patch
, εάν θέλετε να ενημερώσετε τον πόρο. Έτσι λειτουργούν και οι δύο βιβλιοθήκες πελατών πάνω από το Kubernetes API και kubectl
(δεν προκαλεί έκπληξη, καθώς είναι ένα περιτύλιγμα για τη βιβλιοθήκη πελάτη, περίπου. μεταφράστης).
Εργαστείτε στρατηγικά
Όλες οι ομάδες kubectl
apply
, edit
и patch
χρησιμοποιήστε τη μέθοδο PATCH
στο HTTP ζητά να ενημερώσει έναν υπάρχοντα πόρο. Εάν εμβαθύνετε στην υλοποίηση των εντολών με περισσότερες λεπτομέρειες, τότε όλες χρησιμοποιούν την προσέγγιση patch
μπορεί να χρησιμοποιήσει άλλες προσεγγίσεις (περισσότερα για αυτό παρακάτω). Η προσέγγιση επιδιόρθωσης στρατηγικής συγχώνευσης επιχειρεί να "το κάνει σωστά" συγχωνεύοντας τις παρεχόμενες προδιαγραφές με τις υπάρχουσες προδιαγραφές. Πιο συγκεκριμένα, προσπαθεί να συνδυάσει τόσο αντικείμενα όσο και πίνακες, πράγμα που σημαίνει ότι οι αλλαγές τείνουν να είναι προσθετικές. Για παράδειγμα, εκτελώντας την εντολή patch
με μια νέα μεταβλητή περιβάλλοντος στην προδιαγραφή κοντέινερ pod, προκαλεί την προσθήκη αυτής της μεταβλητής περιβάλλοντος στις υπάρχουσες μεταβλητές περιβάλλοντος αντί να τις αντικαθιστά. Για να καταργήσετε χρησιμοποιώντας αυτήν την προσέγγιση, πρέπει να εξαναγκάσετε την τιμή της παραμέτρου ως μηδενική στην παρεχόμενη προδιαγραφή. Ποια από τις ομάδες kubectl
Είναι καλύτερο να το χρησιμοποιήσετε για ενημέρωση;
Εάν δημιουργείτε και διαχειρίζεστε τους πόρους σας χρησιμοποιώντας kubectl apply
, κατά την ενημέρωση είναι καλύτερα να χρησιμοποιείτε πάντα kubectl apply
να kubectl
θα μπορούσε να διαχειριστεί τη διαμόρφωση και να παρακολουθεί σωστά τις αλλαγές που ζητούνται από εφαρμογή σε εφαρμογή. Πλεονέκτημα πάντα χρήση apply
είναι ότι παρακολουθεί μια προδιαγραφή που εφαρμόστηκε προηγουμένως, επιτρέποντάς του να γνωρίζει πότε αφαιρούνται ρητά οι ιδιότητες προδιαγραφών και τα στοιχεία πίνακα. Αυτό σας επιτρέπει να χρησιμοποιήσετε apply
για να αφαιρέσετε ιδιότητες και στοιχεία πίνακα, ενώ μια κανονική στρατηγική συγχώνευση δεν θα λειτουργήσει. Της ομάδας edit
и patch
μην ενημερώσετε τις σημειώσεις που kubectl apply
χρησιμοποιεί για την παρακολούθηση των αλλαγών του, επομένως τυχόν αλλαγές που παρακολουθούνται και γίνονται μέσω του Kubernetes API, αλλά γίνονται μέσω εντολών edit
и patch
, αόρατο σε επόμενες εντολές apply
Δηλαδή, apply
δεν τα αφαιρεί ακόμα κι αν δεν εμφανίζονται στις προδιαγραφές εισαγωγής για apply
(Το λέει η τεκμηρίωση edit
и patch
πραγματοποιήστε ενημερώσεις στις σημειώσεις που χρησιμοποιούνται apply
, αλλά στην πράξη - όχι).
Εάν δεν χρησιμοποιήσετε την εντολή apply
, μπορεί να χρησιμοποιηθεί ως edit
Και patch
, επιλέγοντας την εντολή που ταιριάζει καλύτερα στην αλλαγή που γίνεται. Κατά την προσθήκη και αλλαγή ιδιοτήτων BOM, και οι δύο προσεγγίσεις είναι περίπου ίδιες. Κατά τη διαγραφή ιδιοτήτων προδιαγραφών ή στοιχείων πίνακα edit
συμπεριφέρεται σαν μια εφάπαξ εκτόξευση apply
, συμπεριλαμβανομένης της παρακολούθησης του πώς ήταν η προδιαγραφή πριν και μετά την επεξεργασία της, ώστε να μπορείτε να αφαιρέσετε ρητά ιδιότητες και στοιχεία πίνακα από έναν πόρο. Πρέπει να ορίσετε ρητά την τιμή της ιδιότητας ως μηδενική στην προδιαγραφή για patch
για να το αφαιρέσετε από τον πόρο. Η κατάργηση ενός στοιχείου πίνακα με χρήση επιδιόρθωσης στρατηγικής συγχώνευσης είναι πιο περίπλοκη επειδή απαιτεί τη χρήση οδηγιών συγχώνευσης. Δείτε άλλες προσεγγίσεις αναβάθμισης παρακάτω για πιο βιώσιμες εναλλακτικές λύσεις.
Για να εφαρμόσετε μεθόδους ενημέρωσης στη βιβλιοθήκη πελάτη που συμπεριφέρονται παρόμοια με τις παραπάνω εντολές kubectl
, θα πρέπει να οριστεί στα αιτήματα content-type
в application/strategic-merge-patch+json
. Εάν θέλετε να αφαιρέσετε ιδιότητες σε μια προδιαγραφή, πρέπει να ορίσετε ρητά τις τιμές τους σε null με παρόμοιο τρόπο kubectl patch
. Εάν πρέπει να καταργήσετε στοιχεία πίνακα, θα πρέπει να συμπεριλάβετε οδηγίες συγχώνευσης στην προδιαγραφή ενημέρωσης ή να χρησιμοποιήσετε διαφορετική προσέγγιση για τις ενημερώσεις.
Άλλες προσεγγίσεις για ενημερώσεις
Το Kubernetes υποστηρίζει δύο άλλες προσεγγίσεις ενημέρωσης: kubectl patch --type=merge
. Όταν εργάζεστε με το Kubernetes API, θα πρέπει να χρησιμοποιείτε τη μέθοδο αιτήματος PATCH
και εγκατάσταση content-type
в application/merge-patch+json
.
Η προσέγγιση ενημέρωσης κώδικα JSON, αντί να παρέχει μια μερική προδιαγραφή ενός πόρου, χρησιμοποιεί την παροχή των αλλαγών που θέλετε να κάνετε στον πόρο ως πίνακα, στον οποίο κάθε στοιχείο του πίνακα αντιπροσωπεύει μια περιγραφή της αλλαγής που γίνεται στον πόρο. Αυτή η προσέγγιση είναι ένας πιο ευέλικτος και ισχυρός τρόπος έκφρασης των αλλαγών που γίνονται, αλλά με κόστος την καταχώριση των αλλαγών που γίνονται σε ξεχωριστή, μη Kubernetes μορφή, αντί για αποστολή μερικής προδιαγραφής πόρων. ΣΕ kubectl
μπορείτε να επιλέξετε την ενημερωμένη έκδοση κώδικα JSON χρησιμοποιώντας kubectl patch --type=json
. Όταν χρησιμοποιείτε το Kubernetes API, αυτή η προσέγγιση λειτουργεί χρησιμοποιώντας τη μέθοδο αιτήματος PATCH
και εγκατάσταση content-type
в application/json-patch+json
.
Χρειαζόμαστε εμπιστοσύνη - χρησιμοποιήστε αντικαταστήστε
Σε ορισμένες περιπτώσεις, πρέπει να βεβαιωθείτε ότι δεν γίνονται αλλαγές σε έναν πόρο από τη στιγμή που διαβάζεται ο πόρος και όταν ενημερώνεται. Με άλλα λόγια, θα πρέπει να βεβαιωθείτε ότι όλες οι αλλαγές θα γίνουν ατομικός. Σε αυτήν την περίπτωση, για να ενημερώσετε τους πόρους που πρέπει να χρησιμοποιήσετε replace
. Για παράδειγμα, εάν έχετε ένα ConfigMap με έναν μετρητή που ενημερώνεται από πολλές πηγές, θα πρέπει να βεβαιωθείτε ότι δύο πηγές δεν ενημερώνουν τον μετρητή ταυτόχρονα, με αποτέλεσμα να χαθεί η ενημέρωση. Για να δείξετε, φανταστείτε μια ακολουθία γεγονότων χρησιμοποιώντας την προσέγγιση patch
:
- Τα Α και Β λαμβάνουν την τρέχουσα κατάσταση του πόρου από το API
- Κάθε ένα ενημερώνει τοπικά την προδιαγραφή αυξάνοντας τον μετρητή κατά ένα και προσθέτοντας επίσης το "A" ή "B" αντίστοιχα στη σημείωση "updated-by"
- Και ενημερώνει τον πόρο λίγο πιο γρήγορα
- Το B ενημερώνει τον πόρο
Ως αποτέλεσμα, η ενημέρωση Α χάνεται. Τελευταία επέμβαση patch
κερδίζει, ο μετρητής αυξάνεται κατά ένα αντί για δύο και η τιμή της σημείωσης "updated-by" τελειώνει με "B" και δεν περιέχει "A". Ας συγκρίνουμε τα παραπάνω με αυτό που συμβαίνει όταν οι ενημερώσεις γίνονται χρησιμοποιώντας την προσέγγιση replace
:
- Τα Α και Β λαμβάνουν την τρέχουσα κατάσταση του πόρου από το API
- Κάθε ένα ενημερώνει τοπικά την προδιαγραφή αυξάνοντας τον μετρητή κατά ένα και προσθέτοντας επίσης το "A" ή "B" αντίστοιχα στη σημείωση "updated-by"
- Και ενημερώνει τον πόρο λίγο πιο γρήγορα
- Το B προσπαθεί να ενημερώσει τον πόρο, αλλά η ενημέρωση απορρίπτεται από το API επειδή η έκδοση του πόρου βρίσκεται στις προδιαγραφές
replace
δεν ταιριάζει με την τρέχουσα έκδοση του πόρου στο Kubernetes επειδή η έκδοση του πόρου αυξήθηκε με τη λειτουργία αντικατάστασης του Α.
Στην παραπάνω περίπτωση, ο B θα πρέπει να ανακτήσει ξανά τον πόρο, να κάνει αλλαγές στη νέα κατάσταση και να προσπαθήσει ξανά replace
. Αυτό θα έχει ως αποτέλεσμα ο μετρητής να αυξηθεί κατά δύο και η σημείωση "updated-by" να περιλαμβάνει "AB" στο τέλος.
Το παραπάνω παράδειγμα υπονοεί ότι κατά την εκτέλεση replace
Ολόκληρος ο πόρος έχει αντικατασταθεί πλήρως. Προδιαγραφή που χρησιμοποιείται για replace
, δεν πρέπει να είναι μερική ή τμηματικά όπως στο apply
, αλλά πλήρης, συμπεριλαμβανομένης της προσθήκης resourceVersion
στα μεταδεδομένα προδιαγραφών. Εάν δεν έχετε ενεργοποιήσει resourceVersion
ή η έκδοση που παρέχετε δεν είναι τρέχουσα, η αντικατάσταση θα απορριφθεί. Έτσι, η καλύτερη προσέγγιση για χρήση είναι replace
– διαβάστε τον πόρο, ενημερώστε τον και αντικαταστήστε τον αμέσως. Χρησιμοποιώντας kubectl
, μπορεί να μοιάζει με αυτό:
$ kubectl get deployment my-deployment -o json
| jq '.spec.template.spec.containers[0].env[1].value = "new value"'
| kubectl replace -f -
Αξίζει να σημειωθεί ότι οι ακόλουθες δύο εντολές, που εκτελούνται διαδοχικά, θα εκτελεστούν με επιτυχία, αφού deployment.yaml
δεν περιέχει ιδιότητα .metadata.resourceVersion
$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml
Αυτό φαίνεται να έρχεται σε αντίθεση με όσα ειπώθηκαν παραπάνω, δηλ. "προσθέτωντας resourceVersion
στα μεταδεδομένα προδιαγραφών." Είναι λάθος να το λέμε αυτό; Όχι, δεν είναι, γιατί αν kubectl
ειδοποιήσεις που δεν διευκρινίσατε resourceVersion
, θα το διαβάσει από τον πόρο και θα το προσθέσει στην προδιαγραφή που ορίσατε και μόνο μετά θα το εκτελέσει replace
. Επειδή αυτό είναι δυνητικά επικίνδυνο εάν βασίζεστε στην ατομικότητα, η μαγεία λειτουργεί εξ ολοκλήρου στο πλάι kubectl
, δεν πρέπει να βασίζεστε σε αυτό όταν χρησιμοποιείτε βιβλιοθήκες πελατών που λειτουργούν με το API. Σε αυτήν την περίπτωση θα πρέπει να διαβάσετε την τρέχουσα προδιαγραφή πόρων, να την ενημερώσετε και στη συνέχεια να την εκτελέσετε PUT
αίτηση.
Δεν μπορείτε να κάνετε ένα patch - κάνουμε μια αντικατάσταση
Μερικές φορές χρειάζεται να κάνετε κάποιες αλλαγές που δεν μπορούν να χειριστούν το API. Σε αυτές τις περιπτώσεις, μπορείτε να αναγκάσετε την αντικατάσταση του πόρου διαγράφοντας και δημιουργώντας τον ξανά. Αυτό γίνεται χρησιμοποιώντας kubectl replace --force
. Η εκτέλεση της εντολής αφαιρεί αμέσως τους πόρους και στη συνέχεια τους δημιουργεί εκ νέου από τις παρεχόμενες προδιαγραφές. Δεν υπάρχει πρόγραμμα χειρισμού "force replace" στο API και για να το κάνετε αυτό μέσω του API, πρέπει να εκτελέσετε δύο λειτουργίες. Πρώτα πρέπει να διαγράψετε τον πόρο ρυθμίζοντας τον gracePeriodSeconds
στο μηδέν (0) και propagationPolicy
στο "Φόντο" και, στη συνέχεια, δημιουργήστε ξανά αυτόν τον πόρο με τις επιθυμητές προδιαγραφές.
Προειδοποίηση: Αυτή η προσέγγιση είναι δυνητικά επικίνδυνη και μπορεί να οδηγήσει σε απροσδιόριστη κατάσταση.
Εφαρμόστε στην πλευρά του διακομιστή
Όπως αναφέρθηκε παραπάνω, οι προγραμματιστές του Kubernetes εργάζονται για την εφαρμογή της λογικής apply
του kubectl
στο Kubernetes API. Λογικές apply
διαθέσιμο στο Kubernetes 1.18 μέσω kubectl apply --server-side
ή μέσω του API χρησιμοποιώντας τη μέθοδο PATCH
с content-type
application/apply-patch+YAML
.
Σημείωση: Το JSON είναι επίσης έγκυρο YAML, επομένως μπορείτε να στείλετε την προδιαγραφή ως JSON ακόμα κι αν
content-type
θαapplication/apply-patch+yaml
.
Εκτός από αυτή τη λογική kubectl
γίνεται διαθέσιμο σε όλους μέσω API, apply
από την πλευρά του διακομιστή, παρακολουθεί ποιος είναι υπεύθυνος για τα πεδία της προδιαγραφής, επιτρέποντας έτσι την ασφαλή πολλαπλή πρόσβαση για την επεξεργασία χωρίς συγκρούσεις. Με άλλα λόγια, αν apply
από την πλευρά του διακομιστή θα γίνει πιο διαδεδομένη, θα εμφανιστεί μια καθολική ασφαλής διεπαφή διαχείρισης πόρων για διαφορετικούς πελάτες, για παράδειγμα, kubectl, Pulumi ή Terraform, GitOps, καθώς και αυτογραφικά σενάρια που χρησιμοποιούν βιβλιοθήκες πελατών.
Αποτελέσματα της
Ελπίζω αυτή η σύντομη επισκόπηση των διαφορετικών τρόπων ενημέρωσης πόρων σε συμπλέγματα ήταν χρήσιμη για εσάς. Είναι καλό να γνωρίζετε ότι δεν είναι απλώς εφαρμογή έναντι αντικατάστασης· είναι δυνατό να ενημερώσετε έναν πόρο χρησιμοποιώντας εφαρμογή, επεξεργασία, ενημέρωση κώδικα ή αντικατάσταση. Εξάλλου, κατ 'αρχήν, κάθε προσέγγιση έχει τη δική της περιοχή εφαρμογής. Για ατομικές αλλαγές, η αντικατάσταση είναι προτιμότερη· διαφορετικά, θα πρέπει να χρησιμοποιήσετε την ενημερωμένη έκδοση κώδικα στρατηγικής συγχώνευσης μέσω εφαρμογής. Τουλάχιστον, περιμένω να καταλάβετε ότι δεν μπορείτε να εμπιστευτείτε την Google ή το StackOerflow όταν κάνετε αναζήτηση για το "kubernetes application vs replace". Τουλάχιστον έως ότου αυτό το άρθρο αντικαταστήσει την τρέχουσα απάντηση.
Πηγή: www.habr.com