Σωστή σύγκριση του Kubernetes Apply, Replace and Patch

Το Kubernetes έχει πολλές επιλογές για την ενημέρωση πόρων: εφαρμογή, επεξεργασία, ενημέρωση κώδικα και αντικατάσταση. Υπάρχει σύγχυση σχετικά με το τι κάνει ο καθένας και πότε να τα χρησιμοποιήσει. Ας το καταλάβουμε.

Σωστή σύγκριση του Kubernetes Apply, Replace and Patch

αν αναζήτηση στο Google βρίσκεται η φράση "kubernetes ισχύουν έναντι αντικατάστασης". απάντηση στο StackOverflow, το οποίο δεν είναι σωστό. Κατά την αναζήτηση "kubernetes application vs patch" ο πρώτος σύνδεσμος είναι η τεκμηρίωση για 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, εάν εργάζεστε με συμπλέγματα μέσω βιβλιοθήκη πελάτη για Kubernetes API χρησιμοποιώντας κάποια γλώσσα προγραμματισμού. Η βιβλιοθήκη χειρίζεται αυτές τις μεθόδους μέσω αιτημάτων HTTP χρησιμοποιώντας τις μεθόδους 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 υποστηρίζει δύο άλλες προσεγγίσεις ενημέρωσης: Ενημερωμένη έκδοση κώδικα συγχώνευσης JSON и Ενημερωμένη έκδοση κώδικα JSON. Η προσέγγιση ενημερωμένης έκδοσης κώδικα συγχώνευσης JSON λαμβάνει μια μερική προδιαγραφή Kubernetes ως είσοδο και υποστηρίζει συγχώνευση αντικειμένων παρόμοια με την προσέγγιση ενημέρωσης κώδικα στρατηγικής συγχώνευσης. Η διαφορά μεταξύ των δύο είναι ότι υποστηρίζει μόνο αντικατάσταση πίνακα, συμπεριλαμβανομένης της συστοιχίας κοντέινερ στην προδιαγραφή pod. Αυτό σημαίνει ότι όταν χρησιμοποιείτε μια ενημερωμένη έκδοση κώδικα συγχώνευσης JSON, πρέπει να παρέχετε πλήρεις προδιαγραφές για όλα τα κοντέινερ σε περίπτωση που αλλάξει κάποια ιδιότητα οποιουδήποτε κοντέινερ. Έτσι, αυτή η προσέγγιση είναι χρήσιμη για την αφαίρεση στοιχείων από έναν πίνακα σε ένα BOM. Στη γραμμή εντολών μπορείτε να επιλέξετε την ενημερωμένη έκδοση κώδικα συγχώνευσης JSON χρησιμοποιώντας 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". Τουλάχιστον έως ότου αυτό το άρθρο αντικαταστήσει την τρέχουσα απάντηση.

Σωστή σύγκριση του Kubernetes Apply, Replace and Patch

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο