Πώς να αποκτήσετε πρόσβαση στους πόρους του Kubernetes Pod

Πώς να αποκτήσετε πρόσβαση στους πόρους του Kubernetes PodΗ ανταμοιβή του Tohad

Όταν ξεκινάτε με το Kubernetes, είναι συνηθισμένο να ξεχνάτε τη ρύθμιση πόρων κοντέινερ. Σε αυτό το σημείο, αρκεί να διασφαλίσουμε ότι η εικόνα Docker λειτουργεί και μπορεί να αναπτυχθεί στο σύμπλεγμα Kubernetes.

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

Ομάδα Kubernetes aaS από το Mail.ru μετέφρασε ένα άρθρο σχετικά με πόρους κοντέινερ (CPU & MEM), αιτήματα και περιορισμούς πόρων. Θα μάθετε τα οφέλη αυτών των ρυθμίσεων και τι θα συμβεί αν δεν τις ορίσετε.

Υπολογιστικοί πόροι

Έχουμε δύο τύπους πόρων με τις ακόλουθες μονάδες:

  • Κεντρική μονάδα επεξεργασίας (CPU) - πυρήνες.
  • Μνήμη (MEM) - byte.

Οι πόροι καθορίζονται για κάθε κοντέινερ. Στο ακόλουθο αρχείο Pod YAML, θα δείτε μια ενότητα πόρων που περιέχει τους ζητούμενους και τους περιορισμένους πόρους:

  • Requested Pod Resources = άθροισμα των ζητούμενων πόρων όλων των κοντέινερ.
  • Όριο πόρων Pod = Άθροισμα όλων των ορίων πόρων Pod.

apiVersion: v1
kind: Pod
metadata:
  name: backend-pod-name
  labels:
    application: backend
spec:
  containers:
    — name: main-container
      image: my-backend
      tag: v1
      ports:
      — containerPort: 8080
      resources:
        requests:
          cpu: 0.2 # REQUESTED CPU: 200m cores
          memory: "1Gi" # REQUESTED MEM: 1Gi
        limits:
          cpu: 1 # MAX CPU USAGE: 1 core
          memory: "1Gi" # MAX MEM USAGE:  1Gi
    — name: other-container
      image: other-app
      tag: v1
      ports:
      — containerPort: 8000
      resources:
        requests:
          cpu: "200m" # REQUESTED CPU: 200m cores
          memory: "0.5Gi" # REQUESTED MEM: 0.5Gi
        limits:
          cpu: 1 # MAX CPU USAGE: 1 core
          memory: "1Gi" # MAX MEM USAGE:  1Gi

Παράδειγμα Ζητούμενων και Περιορισμένων Πόρων

Πεδίο resources.requested από την προδιαγραφή Το Pod είναι ένα από τα στοιχεία που χρησιμοποιείται για την εύρεση του επιθυμητού κόμβου. Μπορείτε ήδη να προγραμματίσετε την ανάπτυξη του Pod για αυτό. Πώς βρίσκετε έναν κατάλληλο κόμβο;

Το Kubernetes αποτελείται από πολλά στοιχεία, συμπεριλαμβανομένου ενός κύριου κόμβου ή ενός κύριου κόμβου (Kubernetes Control Plane). Ο κύριος κόμβος έχει διάφορες διεργασίες: kube-apiserver, kube-controller-manager και kube-scheduler.

Η διαδικασία kube-scheduler είναι υπεύθυνη για τον έλεγχο των ομάδων που δημιουργήθηκαν πρόσφατα και την εύρεση πιθανών κόμβων εργαζομένων που ταιριάζουν με όλα τα αιτήματα ομάδας, συμπεριλαμβανομένου του αριθμού των πόρων που ζητήθηκαν. Η λίστα των κόμβων που βρέθηκαν από το kube-scheduler κατατάσσεται. Το pod είναι προγραμματισμένο στον κόμβο με τις υψηλότερες βαθμολογίες.

Πώς να αποκτήσετε πρόσβαση στους πόρους του Kubernetes PodΠού θα τοποθετηθεί το μωβ Pod;

Στην εικόνα μπορείτε να δείτε ότι ο kube-scheduler πρέπει να προγραμματίσει ένα νέο μωβ Pod. Το σύμπλεγμα Kubernetes περιέχει δύο κόμβους: A και B. Όπως μπορείτε να δείτε, το kube-scheduler δεν μπορεί να προγραμματίσει ένα Pod στον κόμβο A - οι διαθέσιμοι (μη ζητούμενοι) πόροι δεν ταιριάζουν με τα αιτήματα του μωβ Pod. Έτσι, το 1 GB μνήμης που ζητά το μωβ Pod δεν χωράει στον κόμβο Α, αφού η διαθέσιμη μνήμη είναι 0,5 GB. Αλλά ο κόμβος Β έχει αρκετούς πόρους. Ως αποτέλεσμα, ο kube-scheduler αποφασίζει ότι ο προορισμός του μωβ Pod είναι ο κόμβος Β.

Τώρα γνωρίζουμε πώς οι ζητούμενοι πόροι επηρεάζουν την επιλογή του κόμβου για την εκτέλεση του Pod. Ποιος είναι όμως ο αντίκτυπος των οριακών πόρων;

Το όριο πόρων είναι ένα όριο που η CPU/MEM δεν μπορεί να περάσει. Ωστόσο, ο πόρος της CPU είναι ευέλικτος, επομένως τα κοντέινερ που φτάνουν τα όρια της CPU δεν θα προκαλέσουν την έξοδο του Pod. Αντίθετα, θα ξεκινήσει ο στραγγαλισμός της CPU. Εάν επιτευχθεί το όριο χρήσης MEM, το κοντέινερ θα σταματήσει λόγω OOM-Killer και θα επανεκκινηθεί εάν επιτρέπεται από τη ρύθμιση RestartPolicy.

Αναλυτικά ζητούμενοι και μέγιστοι πόροι

Πώς να αποκτήσετε πρόσβαση στους πόρους του Kubernetes PodΕπικοινωνία πόρων μεταξύ Docker και Kubernetes

Ο καλύτερος τρόπος για να εξηγήσετε πώς λειτουργούν τα αιτήματα πόρων και τα όρια πόρων είναι να εισαγάγετε τη σχέση μεταξύ Kubernetes και Docker. Στην παραπάνω εικόνα μπορείτε να δείτε πώς σχετίζονται τα πεδία Kubernetes και οι σημαίες εκκίνησης Docker.

Μνήμη: αίτημα και περιορισμός

containers:
...
 resources:
   requests:
     memory: "0.5Gi"
   limits:
     memory: "1Gi"

Όπως αναφέρθηκε παραπάνω, η μνήμη μετριέται σε byte. Βασισμένο στο Τεκμηρίωση Kubernetes, μπορούμε να καθορίσουμε τη μνήμη ως αριθμό. Συνήθως είναι ακέραιος, για παράδειγμα 2678 - δηλαδή 2678 byte. Μπορείτε επίσης να χρησιμοποιήσετε επιθήματα G и Gi, το κύριο πράγμα είναι να θυμάστε ότι δεν είναι ισοδύναμα. Το πρώτο είναι δεκαδικό και το δεύτερο είναι δυαδικό. Όπως το παράδειγμα που αναφέρεται στην τεκμηρίωση του k8s: 128974848, 129e6, 129M, 123Mi - είναι πρακτικά ισοδύναμα.

Επιλογή Kubernetes limits.memory ταιριάζει με τη σημαία --memory από το Docker. Σε περίπτωση που request.memory Δεν υπάρχει βέλος για το Docker επειδή το Docker δεν χρησιμοποιεί αυτό το πεδίο. Μπορείτε να ρωτήσετε, είναι αυτό ακόμη απαραίτητο; Ναι ανάγκη. Όπως είπα και πριν, το πεδίο έχει σημασία για την Kubernetes. Με βάση τις πληροφορίες από αυτό, ο kube-scheduler αποφασίζει σε ποιον κόμβο θα προγραμματίσει το Pod.

Τι συμβαίνει εάν ορίσετε ανεπαρκή μνήμη για ένα αίτημα;

Εάν το κοντέινερ έχει φτάσει τα όρια της ζητούμενης μνήμης, τότε το Pod τοποθετείται σε μια ομάδα Pods που σταματούν όταν δεν υπάρχει αρκετή μνήμη στον κόμβο.

Τι συμβαίνει εάν ρυθμίσετε το όριο μνήμης πολύ χαμηλό;

Εάν το κοντέινερ υπερβεί το όριο μνήμης, θα τερματιστεί λόγω OOM-Killed. Και θα επανεκκινήσει εάν είναι δυνατόν με βάση το RestartPolicy όπου είναι η προεπιλεγμένη τιμή Always.

Τι θα συμβεί εάν δεν καθορίσετε την απαιτούμενη μνήμη;

Το Kubernetes θα λάβει την οριακή τιμή και θα την ορίσει ως την προεπιλεγμένη τιμή.

Τι μπορεί να συμβεί εάν δεν καθορίσετε ένα όριο μνήμης;

Το δοχείο δεν έχει περιορισμούς, μπορεί να χρησιμοποιήσει όση μνήμη θέλει. Εάν αρχίσει να χρησιμοποιεί όλη τη διαθέσιμη μνήμη του κόμβου, τότε το OOM θα τον σκοτώσει. Στη συνέχεια, το κοντέινερ θα επανεκκινηθεί, εάν είναι δυνατόν, με βάση το RestartPolicy.

Τι θα συμβεί αν δεν καθορίσετε όρια μνήμης;

Αυτό είναι το χειρότερο σενάριο: ο προγραμματιστής δεν γνωρίζει πόσους πόρους απαιτεί το κοντέινερ και αυτό μπορεί να προκαλέσει σοβαρά προβλήματα στον κόμβο. Σε αυτήν την περίπτωση, θα ήταν ωραίο να υπάρχουν προεπιλεγμένα όρια στον χώρο ονομάτων (που ορίζονται από το LimitRange). Δεν υπάρχουν προεπιλεγμένα όρια - το Pod δεν έχει όρια, μπορεί να χρησιμοποιήσει όση μνήμη θέλει.

Εάν η ζητούμενη μνήμη είναι μεγαλύτερη από αυτή που μπορεί να προσφέρει ο κόμβος, το Pod δεν θα προγραμματιστεί. Είναι σημαντικό να το θυμάστε αυτό Requests.memory - όχι η ελάχιστη τιμή. Αυτή είναι μια περιγραφή της ποσότητας μνήμης που είναι επαρκής για να διατηρείται η συνεχής λειτουργία του δοχείου.

Συνήθως συνιστάται να ορίσετε την ίδια τιμή για request.memory и limit.memory. Αυτό διασφαλίζει ότι το Kubernetes δεν θα προγραμματίσει ένα Pod σε έναν κόμβο που έχει αρκετή μνήμη για να τρέξει το Pod αλλά όχι αρκετή για να το εκτελέσει. Λάβετε υπόψη: Ο σχεδιασμός του Kubernetes Pod λαμβάνει υπόψη μόνο requests.memoryΚαι limits.memory δεν λαμβάνει υπόψη.

CPU: αίτημα και όριο

containers:
...
 resources:
   requests:
     cpu: 1
   limits:
     cpu: "1200m"

Με μια CPU όλα είναι λίγο πιο περίπλοκα. Επιστρέφοντας στην εικόνα της σχέσης μεταξύ Kubernetes και Docker, μπορείτε να το δείτε request.cpu αντιστοιχεί --cpu-shares, ενώ limit.cpu ταιριάζει με τη σημαία cpus στο Docker.

Η CPU που ζητά η Kubernetes πολλαπλασιάζεται επί 1024, το ποσοστό των κύκλων της CPU. Εάν θέλετε να ζητήσετε 1 πλήρη πυρήνα, πρέπει να προσθέσετε cpu: 1όπως φαίνεται παραπάνω.

Το να ζητήσετε έναν πλήρη πυρήνα (αναλογία = 1024) δεν σημαίνει ότι το κοντέινερ σας θα το λάβει. Εάν ο κεντρικός υπολογιστής σας έχει μόνο έναν πυρήνα και χρησιμοποιείτε περισσότερα από ένα κοντέινερ, τότε όλα τα κοντέινερ πρέπει να μοιράζονται τη διαθέσιμη CPU μεταξύ τους. Πώς συμβαίνει αυτό; Ας δούμε την εικόνα.

Πώς να αποκτήσετε πρόσβαση στους πόρους του Kubernetes Pod
CPU Request - Single Core System

Ας φανταστούμε ότι έχετε ένα κεντρικό σύστημα ενός πυρήνα που εκτελεί κοντέινερ. Η μαμά (Kubernetes) έψησε μια πίτα (CPU) και θέλει να τη μοιράσει στα παιδιά (δοχεία). Τρία παιδιά θέλουν ολόκληρη πίτα (αναλογία = 1024), άλλο ένα παιδί θέλει μισή πίτα (512). Η μαμά θέλει να είναι δίκαιη και κάνει έναν απλό υπολογισμό.

# Сколько пирогов хотят дети?
# 3 ребенка хотят по целому пирогу и еще один хочет половину пирога
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
# Выражение получается так:
3 (ребенка/контейнера) * 1 (целый пирог/полное ядро) + 1 (ребенок/контейнер) * 0.5 (половина пирога/половина ядра)
# Сколько пирогов испечено?
availableCakesNumber = 1
# Сколько пирога (максимально) дети реально могут получить?
newMaxRequest = 1 / 3.5 =~ 28%

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

Πώς να αποκτήσετε πρόσβαση στους πόρους του Kubernetes Pod
CPU Request - Multi-Core (4) System

Στην παραπάνω εικόνα μπορείτε να δείτε ότι τρία παιδιά θέλουν μια ολόκληρη πίτα και το ένα θέλει τη μισή. Αφού η μαμά έψηνε τέσσερις πίτες, το καθένα από τα παιδιά της θα πάρει όσες θέλει. Σε ένα σύστημα πολλαπλών πυρήνων, οι πόροι του επεξεργαστή κατανέμονται σε όλους τους διαθέσιμους πυρήνες επεξεργαστή. Εάν ένα κοντέινερ περιορίζεται σε λιγότερο από έναν πλήρη πυρήνα CPU, μπορεί να το χρησιμοποιήσει στο 100%.

Οι παραπάνω υπολογισμοί απλοποιούνται για να κατανοήσουμε πώς η CPU κατανέμεται μεταξύ των κοντέινερ. Φυσικά, εκτός από τα ίδια τα κοντέινερ, υπάρχουν και άλλες διεργασίες που χρησιμοποιούν επίσης πόρους CPU. Όταν οι διεργασίες σε ένα κοντέινερ είναι αδρανείς, άλλες μπορούν να χρησιμοποιήσουν τον πόρο του. CPU: "200m" αντιστοιχεί CPU: 0,2, που σημαίνει περίπου το 20% ενός πυρήνα.

Τώρα ας μιλήσουμε για limit.cpu. Η CPU που περιορίζει το Kubernetes πολλαπλασιάζεται επί 100. Το αποτέλεσμα είναι ο χρόνος που μπορεί να χρησιμοποιήσει το δοχείο κάθε 100 μs (cpu-period).

limit.cpu ταιριάζει με τη σημαία Docker --cpus. Αυτός είναι ένας νέος συνδυασμός παλιού --cpu-period и --cpu-quota. Ρυθμίζοντάς το, υποδεικνύουμε πόσους διαθέσιμους πόρους CPU μπορεί να χρησιμοποιήσει στο μέγιστο το κοντέινερ πριν ξεκινήσει ο στραγγαλισμός:

  • επεξεργαστές - συνδυασμός cpu-period и cpu-quota. cpus = 1.5 ισοδυναμεί με τη ρύθμιση cpu-period = 100000 и cpu-quota = 150000;
  • Περίοδος CPU - περίοδος Προγραμματιστής CPU CFS, προεπιλογή 100 μικροδευτερόλεπτα.
  • CPU-Ποσόστωση - αριθμός μικροδευτερόλεπτων στο εσωτερικό cpu-period, το οποίο οριοθετείται από το δοχείο.

Τι συμβαίνει εάν εγκαταστήσετε ανεπαρκή ζητούμενη CPU;

Εάν το κοντέινερ χρειάζεται περισσότερα από αυτά που έχει εγκαταστήσει, θα κλέψει την CPU από άλλες διεργασίες.

Τι συμβαίνει εάν θέσετε το όριο της CPU πολύ χαμηλό;

Δεδομένου ότι ο πόρος της CPU είναι ρυθμιζόμενος, ο στραγγαλισμός θα ενεργοποιηθεί.

Τι συμβαίνει εάν δεν καθορίσετε ένα αίτημα CPU;

Όπως και με τη μνήμη, η τιμή αιτήματος είναι ίση με το όριο.

Τι θα συμβεί αν δεν καθορίσετε όριο CPU;

Το δοχείο θα χρησιμοποιεί όση CPU χρειάζεται. Εάν οριστεί μια προεπιλεγμένη πολιτική CPU (LimitRange) στον χώρο ονομάτων, τότε αυτό το όριο χρησιμοποιείται επίσης για το κοντέινερ.

Τι συμβαίνει εάν δεν καθορίσετε ούτε αίτημα ούτε όριο CPU;

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

Θυμηθείτε: εάν ζητήσετε περισσότερη CPU από αυτή που μπορούν να παρέχουν οι κόμβοι, το Pod δεν θα προγραμματιστεί. Requests.cpu - όχι η ελάχιστη τιμή, αλλά μια τιμή επαρκής για να ξεκινήσει το Pod και να λειτουργήσει χωρίς αστοχίες. Εάν η εφαρμογή δεν εκτελεί σύνθετους υπολογισμούς, η καλύτερη επιλογή είναι να εγκαταστήσετε request.cpu <= 1 και ξεκινήστε όσα αντίγραφα χρειάζεται.

Ιδανική ποσότητα απαιτούμενων πόρων ή όριο πόρων

Μάθαμε για τον περιορισμό των υπολογιστικών πόρων. Τώρα ήρθε η ώρα να απαντήσουμε στην ερώτηση: «Πόσους πόρους απαιτεί το Pod μου για να τρέξει την εφαρμογή χωρίς προβλήματα; Ποια είναι η ιδανική ποσότητα;

Δυστυχώς, δεν υπάρχουν σαφείς απαντήσεις σε αυτά τα ερωτήματα. Εάν δεν γνωρίζετε πώς λειτουργεί η εφαρμογή σας ή πόση CPU ή μνήμη χρειάζεται, η καλύτερη επιλογή είναι να δώσετε στην εφαρμογή πολλή μνήμη και CPU και στη συνέχεια να εκτελέσετε δοκιμές απόδοσης.

Εκτός από τις δοκιμές απόδοσης, παρακολουθήστε τη συμπεριφορά της εφαρμογής στην παρακολούθηση για μια εβδομάδα. Εάν τα γραφήματα υποδεικνύουν ότι η εφαρμογή σας καταναλώνει λιγότερους πόρους από αυτούς που ζητήσατε, μπορείτε να μειώσετε την απαιτούμενη ποσότητα CPU ή μνήμης.

Για παράδειγμα δείτε αυτό Ταμπλό Grafana. Εμφανίζει τη διαφορά μεταξύ των ζητούμενων πόρων ή ορίου πόρων και της τρέχουσας χρήσης πόρων.

Συμπέρασμα

Το να ζητάτε και να περιορίζετε τους πόρους σας βοηθά να διατηρήσετε το σύμπλεγμα Kubernetes σας υγιές. Η σωστή διαμόρφωση ορίων ελαχιστοποιεί το κόστος και διατηρεί τις εφαρμογές σε λειτουργία ανά πάσα στιγμή.

Εν ολίγοις, υπάρχουν μερικά πράγματα που πρέπει να θυμάστε:

  1. Οι αιτούμενοι πόροι είναι μια διαμόρφωση που λαμβάνεται υπόψη κατά την εκκίνηση (όταν η Kubernetes σχεδιάζει να φιλοξενήσει την εφαρμογή). Αντίθετα, ο περιορισμός των πόρων είναι σημαντικός κατά το χρόνο εκτέλεσης — όταν η εφαρμογή εκτελείται ήδη στον κόμβο.
  2. Σε σύγκριση με τη μνήμη, η CPU είναι ένας ρυθμιζόμενος πόρος. Εάν δεν υπάρχει αρκετή CPU, το Pod σας δεν θα κλείσει και ο μηχανισμός στραγγαλισμού θα ενεργοποιηθεί.
  3. Οι αιτούμενοι πόροι και το όριο πόρων δεν είναι ελάχιστες και μέγιστες τιμές! Καθορίζοντας τους πόρους που ζητούνται, διασφαλίζετε ότι η εφαρμογή θα εκτελείται χωρίς προβλήματα.
  4. Μια καλή πρακτική είναι να ορίσετε το αίτημα μνήμης ίσο με το όριο μνήμης.
  5. Εντάξει ζητήθηκε εγκατάσταση CPU <=1, εάν η εφαρμογή δεν εκτελεί σύνθετους υπολογισμούς.
  6. Εάν ζητήσετε περισσότερους πόρους από αυτούς που είναι διαθέσιμοι σε έναν κόμβο, το Pod δεν θα προγραμματιστεί ποτέ σε αυτόν τον κόμβο.
  7. Για να προσδιορίσετε τη σωστή ποσότητα των απαιτούμενων ορίων πόρων/πόρων, χρησιμοποιήστε τη δοκιμή φόρτωσης και την παρακολούθηση.

Ελπίζω αυτό το άρθρο να σας βοηθήσει να κατανοήσετε τη βασική έννοια του περιορισμού των πόρων. Και θα μπορείτε να εφαρμόσετε αυτή τη γνώση στη δουλειά σας.

Καλή τύχη!

Τι άλλο να διαβάσετε:

  1. Παρατηρησιμότητα SRE: Χώροι ονομάτων και μετρική δομή.
  2. 90+ Χρήσιμα εργαλεία για Kubernetes: Ανάπτυξη, Διαχείριση, Παρακολούθηση, Ασφάλεια και άλλα.
  3. Το κανάλι μας Around Kubernetes στο Telegram.

Πηγή: www.habr.com

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