Οι ανιχνευτές ζωντάνιας στο Kubernetes μπορεί να είναι επικίνδυνοι

Σημείωση. μετάφρ.: Ο επικεφαλής μηχανικός από το Zalando, ο Henning Jacobs, έχει επανειλημμένα παρατηρήσει προβλήματα μεταξύ των χρηστών του Kubernetes όσον αφορά την κατανόηση του σκοπού των ανιχνευτών ζωντανότητας (και ετοιμότητας) και τη σωστή χρήση τους. Ως εκ τούτου, συγκέντρωσε τις σκέψεις του σε αυτό το μεγάλο σημείωμα, το οποίο τελικά θα γίνει μέρος της τεκμηρίωσης του K8.

Οι ανιχνευτές ζωντάνιας στο Kubernetes μπορεί να είναι επικίνδυνοι

Έλεγχοι υγείας, γνωστοί στο Kubernetes ως ανιχνευτές ζωντάνιας (δηλαδή, κυριολεκτικά, "δοκιμές βιωσιμότητας" - περίπου μετάφρ.), μπορεί να είναι αρκετά επικίνδυνο. Συνιστώ να τα αποφύγετε εάν είναι δυνατόν: οι μόνες εξαιρέσεις είναι όταν είναι πραγματικά απαραίτητες και έχετε πλήρη επίγνωση των ιδιαιτεροτήτων και των συνεπειών της χρήσης τους. Αυτή η δημοσίευση θα μιλήσει για τους ελέγχους ζωντάνιας και ετοιμότητας και θα σας πει επίσης σε ποιες περιπτώσεις Κόστος και δεν πρέπει να τα χρησιμοποιείτε.

Ο συνάδελφός μου Sandor μοιράστηκε πρόσφατα στο Twitter τα πιο συνηθισμένα σφάλματα που συναντά, συμπεριλαμβανομένων εκείνων που σχετίζονται με τη χρήση ανιχνευτών ετοιμότητας/ζωηρότητας:

Οι ανιχνευτές ζωντάνιας στο Kubernetes μπορεί να είναι επικίνδυνοι

Εσφαλμένη διαμόρφωση livenessProbe μπορεί να επιδεινώσει καταστάσεις υψηλού φορτίου (απενεργοποίηση χιονόμπαλας + δυνητικά μεγάλος χρόνος εκκίνησης κοντέινερ/εφαρμογής) και να οδηγήσει σε άλλες αρνητικές συνέπειες, όπως πτώση εξάρτησης (δείτε επίσης πρόσφατο άρθρο μου σχετικά με τον περιορισμό του αριθμού των αιτημάτων στο συνδυασμό K3s+ACME). Είναι ακόμη χειρότερο όταν ο ανιχνευτής ζωντάνιας συνδυάζεται με έναν έλεγχο υγείας, ο οποίος είναι μια εξωτερική βάση δεδομένων: μια μεμονωμένη αποτυχία DB θα επανεκκινήσει όλα τα κοντέινερ!

Γενικό μήνυμα "Μην χρησιμοποιείτε ανιχνευτές ζωντάνιας" σε αυτήν την περίπτωση δεν βοηθάει πολύ, οπότε ας δούμε σε τι χρησιμεύουν οι έλεγχοι ετοιμότητας και ζωντάνιας.

Σημείωση: Το μεγαλύτερο μέρος της παρακάτω δοκιμής συμπεριλήφθηκε αρχικά στην εσωτερική τεκμηρίωση προγραμματιστή του Zalando.

Έλεγχοι ετοιμότητας και ζωντάνιας

Το Kubernetes παρέχει δύο σημαντικούς μηχανισμούς που ονομάζονται ανιχνευτές ζωντάνιας και ανιχνευτές ετοιμότητας. Εκτελούν περιοδικά κάποια ενέργεια—όπως αποστολή αιτήματος HTTP, άνοιγμα σύνδεσης TCP ή εκτέλεση εντολής στο κοντέινερ—για να επιβεβαιώσουν ότι η εφαρμογή λειτουργεί όπως αναμένεται.

Χρήσεις Kubernetes ανιχνευτές ετοιμότηταςγια να καταλάβετε πότε το κοντέινερ είναι έτοιμο να δεχθεί κίνηση. Ένα λοβό θεωρείται έτοιμο για χρήση εάν όλα τα δοχεία του είναι έτοιμα. Μία χρήση αυτού του μηχανισμού είναι να ελέγχετε ποια pods χρησιμοποιούνται ως backend για τις υπηρεσίες Kubernetes (και ειδικά το Ingress).

Ανιχνευτές ζωντάνιας βοηθήστε τον Kubernetes να καταλάβει πότε είναι ώρα να επανεκκινήσετε το κοντέινερ. Για παράδειγμα, ένας τέτοιος έλεγχος σάς επιτρέπει να παρεμποδίσετε ένα αδιέξοδο όταν μια εφαρμογή κολλήσει σε ένα μέρος. Η επανεκκίνηση του κοντέινερ σε αυτήν την κατάσταση βοηθά στην απομάκρυνση της εφαρμογής παρά τα σφάλματα, αλλά μπορεί επίσης να οδηγήσει σε διαδοχικές αστοχίες (δείτε παρακάτω).

Εάν προσπαθήσετε να αναπτύξετε μια ενημέρωση εφαρμογής που αποτυγχάνει στους ελέγχους ζωντανότητας/ ετοιμότητας, η διάθεσή της θα σταματήσει καθώς η Kubernetes περιμένει την κατάσταση Ready από όλους τους λοβούς.

Παράδειγμα

Ακολουθεί ένα παράδειγμα ανιχνευτή ετοιμότητας που ελέγχει μια διαδρομή /health μέσω HTTP με προεπιλεγμένες ρυθμίσεις (διάστημα: 10 δευτερόλεπτα, χρονικού ορίου: 1 δευτερόλεπτο, κατώφλι επιτυχίας: 1, κατώφλι αποτυχίας: 3):

# часть общего описания deployment'а/стека
podTemplate:
  spec:
    containers:
    - name: my-container
      # ...
      readinessProbe:
        httpGet:
          path: /health
          port: 8080

συστάσεις

  1. Για μικροϋπηρεσίες με τελικό σημείο HTTP (REST, κ.λπ.) να ορίζετε πάντα έναν ανιχνευτή ετοιμότητας, το οποίο ελέγχει εάν η εφαρμογή (pod) είναι έτοιμη να δεχθεί κίνηση.
  2. Βεβαιωθείτε ότι ο ανιχνευτής ετοιμότητας καλύπτει τη διαθεσιμότητα της πραγματικής θύρας διακομιστή web:
    • χρήση θυρών για διαχειριστικούς σκοπούς, που ονομάζονται "admin" ή "management" (για παράδειγμα, 9090), για readinessProbe, βεβαιωθείτε ότι το τελικό σημείο επιστρέφει ΟΚ μόνο εάν η κύρια θύρα HTTP (όπως η 8080) είναι έτοιμη να δεχθεί κίνηση*.

      *Γνωρίζω τουλάχιστον μία περίπτωση στο Zalando όπου αυτό δεν συνέβη, δηλ. readinessProbe Έλεγξα τη θύρα "διαχείριση", αλλά ο ίδιος ο διακομιστής δεν άρχισε να λειτουργεί λόγω προβλημάτων φόρτωσης της προσωρινής μνήμης.

    • η προσάρτηση ενός αισθητήρα ετοιμότητας σε μια ξεχωριστή θύρα μπορεί να οδηγήσει στο γεγονός ότι η υπερφόρτωση στην κύρια θύρα δεν θα αντικατοπτρίζεται στον έλεγχο υγείας (δηλαδή, η ομάδα νημάτων στον διακομιστή είναι πλήρης, αλλά ο έλεγχος υγείας εξακολουθεί να δείχνει ότι όλα είναι εντάξει ).
  3. Σιγουρέψου ότι Ο ανιχνευτής ετοιμότητας επιτρέπει την προετοιμασία/μεταφορά της βάσης δεδομένων;
    • Ο ευκολότερος τρόπος για να επιτευχθεί αυτό είναι να επικοινωνήσετε με τον διακομιστή HTTP μόνο αφού ολοκληρωθεί η προετοιμασία (για παράδειγμα, μετεγκατάσταση μιας βάσης δεδομένων από Flyway και ούτω καθεξής.); Δηλαδή, αντί να αλλάξετε την κατάσταση του υγειονομικού ελέγχου, απλώς μην ξεκινήσετε τον διακομιστή web έως ότου ολοκληρωθεί η μετεγκατάσταση της βάσης δεδομένων*.

      * Μπορείτε επίσης να εκτελέσετε μετεγκαταστάσεις βάσης δεδομένων από κοντέινερ init εκτός του pod. Εξακολουθώ να είμαι λάτρης των αυτοδύναμων εφαρμογών, δηλαδή εκείνων στις οποίες το κοντέινερ της εφαρμογής ξέρει πώς να φέρει τη βάση δεδομένων στην επιθυμητή κατάσταση χωρίς εξωτερικό συντονισμό.

  4. χρήση httpGet για ελέγχους ετοιμότητας μέσω τυπικών τελικών σημείων ελέγχου υγείας (για παράδειγμα, /health).
  5. Κατανοήστε τις προεπιλεγμένες παραμέτρους ελέγχου (interval: 10s, timeout: 1s, successThreshold: 1, failureThreshold: 3):
    • Οι προεπιλεγμένες επιλογές σημαίνουν ότι η ομάδα θα γίνει μη-έτοιμο μετά από περίπου 30 δευτερόλεπτα (3 αποτυχημένοι έλεγχοι λογικής).
  6. Χρησιμοποιήστε μια ξεχωριστή θύρα για "διαχειριστής" ή "διαχείριση", εάν το επιτρέπει η στοίβα τεχνολογίας (π.χ. Java/Spring), για να διαχωρίσετε τη διαχείριση υγείας και μετρήσεων από την κανονική επισκεψιμότητα:
    • αλλά μην ξεχνάτε το σημείο 2.
  7. Εάν είναι απαραίτητο, ο ανιχνευτής ετοιμότητας μπορεί να χρησιμοποιηθεί για την προθέρμανση/φόρτωση της κρυφής μνήμης και την επιστροφή ενός κωδικού κατάστασης 503 μέχρι να ζεσταθεί το κοντέινερ:

Προειδοποιήσεις

  1. Μην βασίζεστε σε εξωτερικές εξαρτήσεις (όπως οι αποθήκες δεδομένων) όταν εκτελούνται δοκιμές ετοιμότητας/ζωντανής - αυτό μπορεί να οδηγήσει σε διαδοχικές αστοχίες:
    • Για παράδειγμα, ας πάρουμε μια κρατική υπηρεσία REST με 10 pods ανάλογα με μια βάση δεδομένων Postgres: όταν ο έλεγχος εξαρτάται από μια λειτουργική σύνδεση με το DB, και τα 10 pods μπορεί να αποτύχουν εάν υπάρχει καθυστέρηση στην πλευρά του δικτύου/DB - συνήθως αυτό όλα τελειώνουν χειρότερα απ' όσο θα μπορούσαν.
    • Λάβετε υπόψη ότι το Spring Data ελέγχει τη σύνδεση της βάσης δεδομένων από προεπιλογή*.

      * Αυτή είναι η προεπιλεγμένη συμπεριφορά του Spring Data Redis (τουλάχιστον ήταν η τελευταία φορά που έλεγξα), η οποία οδήγησε σε μια «καταστροφική» αποτυχία: όταν το Redis δεν ήταν διαθέσιμο για μικρό χρονικό διάστημα, όλα τα pods «έσπασαν».

    • "εξωτερικό" με αυτή την έννοια μπορεί επίσης να σημαίνει άλλα λοβές της ίδιας εφαρμογής, δηλαδή, ιδανικά ο έλεγχος δεν θα πρέπει να εξαρτάται από την κατάσταση άλλων λοβών του ίδιου συμπλέγματος για την αποφυγή κλιμακωτών συντριβών:
      • Τα αποτελέσματα ενδέχεται να διαφέρουν για εφαρμογές με κατανεμημένη κατάσταση (για παράδειγμα, προσωρινή αποθήκευση στη μνήμη σε ομάδες διαφημίσεων).
  2. Μην χρησιμοποιείτε ανιχνευτή ζωντάνιας για λοβούς (εξαιρούνται οι περιπτώσεις που είναι πραγματικά απαραίτητα και γνωρίζετε πλήρως τις ιδιαιτερότητες και τις συνέπειες της χρήσης τους):
    • Ένας ανιχνευτής ζωντάνιας μπορεί να βοηθήσει στην ανάκτηση κρεμασμένων κοντέινερ, αλλά εφόσον έχετε τον πλήρη έλεγχο της εφαρμογής σας, ιδανικά δεν θα πρέπει να συμβαίνουν πράγματα όπως οι αναρτημένες διαδικασίες και τα αδιέξοδα: η καλύτερη εναλλακτική είναι να διακόψετε σκόπιμα την εφαρμογή και να την επαναφέρετε στην προηγούμενη σταθερή κατάσταση.
    • ένας αποτυχημένος ανιχνευτής ζωντάνιας θα προκαλέσει την επανεκκίνηση του κοντέινερ, επιδεινώνοντας έτσι πιθανώς τις συνέπειες σφαλμάτων που σχετίζονται με τη φόρτωση: η επανεκκίνηση του κοντέινερ θα οδηγήσει σε διακοπή λειτουργίας (τουλάχιστον κατά τη διάρκεια της εκκίνησης της εφαρμογής, ας πούμε 30 δευτερόλεπτα), προκαλώντας νέα σφάλματα , αύξηση του φορτίου σε άλλα εμπορευματοκιβώτια και αύξηση της πιθανότητας αστοχίας τους κ.λπ.
    • Οι έλεγχοι ζωντάνιας σε συνδυασμό με μια εξωτερική εξάρτηση είναι ο χειρότερος δυνατός συνδυασμός, απειλώντας διαδοχικές αστοχίες: μια μικρή καθυστέρηση από την πλευρά της βάσης δεδομένων θα οδηγήσει σε επανεκκίνηση όλων των κοντέινερ!
  3. Παράμετροι ζωντάνιας και ελέγχους ετοιμότητας πρέπει να είναι διαφορετικό:
    • μπορείτε να χρησιμοποιήσετε έναν ανιχνευτή ζωντάνιας με τον ίδιο έλεγχο υγείας, αλλά υψηλότερο όριο απόκρισης (failureThreshold), για παράδειγμα, εκχωρήστε την κατάσταση μη-έτοιμο μετά από 3 προσπάθειες και θεωρήστε ότι η ανίχνευση ζωντάνιας απέτυχε μετά από 10 προσπάθειες.
  4. Μην χρησιμοποιείτε εκτελεστικούς ελέγχους, δεδομένου ότι σχετίζονται με γνωστά προβλήματα που οδηγούν στην εμφάνιση διεργασιών ζόμπι:

Περίληψη

  • Χρησιμοποιήστε ανιχνευτές ετοιμότητας για να προσδιορίσετε πότε ένα pod είναι έτοιμο να λάβει κίνηση.
  • Χρησιμοποιήστε ανιχνευτές ζωντάνιας μόνο όταν είναι πραγματικά απαραίτητοι.
  • Η ακατάλληλη χρήση των ανιχνευτών ετοιμότητας/ζωηρότητας μπορεί να οδηγήσει σε μειωμένη διαθεσιμότητα και σε διαδοχικές αστοχίες.

Οι ανιχνευτές ζωντάνιας στο Kubernetes μπορεί να είναι επικίνδυνοι

Πρόσθετο υλικό για το θέμα

Ενημέρωση Νο. 1 από 2019-09-29

Σχετικά με τα κοντέινερ init για μετεγκατάσταση της βάσης δεδομένων: Προστέθηκε η υποσημείωση.

μου θύμισε ο EJ σχετικά με το ΠΣΠ: ένα από τα προβλήματα με τους ελέγχους ζωντάνιας είναι η έλλειψη συντονισμού μεταξύ των λοβών. Η Kubernetes έχει Προϋπολογισμοί διαταραχών στο Pod (PDB) για τον περιορισμό του αριθμού των ταυτόχρονων αποτυχιών που μπορεί να αντιμετωπίσει μια εφαρμογή, ωστόσο οι έλεγχοι δεν λαμβάνουν υπόψη το ΠΣΠ. Ιδανικά, θα μπορούσαμε να πούμε στα K8 να "Επανεκκινήσουν ένα pod αν αποτύχει η δοκιμή του, αλλά μην τα επανεκκινήσετε όλα για να αποφύγετε τα χειρότερα".

Ο Μπράιαν το έθεσε τέλεια: «Χρησιμοποιήστε το liveness probing όταν ξέρετε ακριβώς τι το καλύτερο που έχετε να κάνετε είναι να σκοτώσετε την εφαρμογή«(και πάλι μην παρασυρθείς).

Οι ανιχνευτές ζωντάνιας στο Kubernetes μπορεί να είναι επικίνδυνοι

Ενημέρωση Νο. 2 από 2019-09-29

Σχετικά με την ανάγνωση της τεκμηρίωσης πριν από τη χρήση: Δημιούργησα το αντίστοιχο αίτημα (αίτημα λειτουργίας) για να προσθέσετε τεκμηρίωση σχετικά με ανιχνευτές ζωντάνιας.

ΥΓ από τον μεταφραστή

Διαβάστε επίσης στο blog μας:

Πηγή: www.habr.com

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