Kubernetes: γιατί είναι τόσο σημαντικό να ρυθμίσετε τη διαχείριση πόρων του συστήματος;

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

Kubernetes: γιατί είναι τόσο σημαντικό να ρυθμίσετε τη διαχείριση πόρων του συστήματος;

Πρέπει να ξεκινήσετε με ποιους κύριους τύπους πόρων υπάρχουν στο σύστημα - αυτό, φυσικά, είναι ο χρόνος επεξεργαστή και η μνήμη RAM. Στις εκδηλώσεις k8s, αυτοί οι τύποι πόρων μετρώνται στις ακόλουθες μονάδες:

  • CPU - σε πυρήνες
  • RAM - σε byte

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

Είναι σημαντικό να κατανοήσουμε ότι το μανιφέστο δεν χρειάζεται να ορίζει ρητά και τους δύο τύπους, αλλά η συμπεριφορά θα είναι η εξής:

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

Είναι επίσης δυνατό να διαμορφώσετε τη διαχείριση πόρων όχι μόνο σε επίπεδο συγκεκριμένου κοντέινερ, αλλά και σε επίπεδο χώρου ονομάτων χρησιμοποιώντας τις ακόλουθες οντότητες:

  • Όριο Εύρος — περιγράφει την πολιτική περιορισμού σε επίπεδο κοντέινερ/λοβού σε ns και είναι απαραίτητη για την περιγραφή των προεπιλεγμένων ορίων στο δοχείο/λοβό, καθώς και για την αποφυγή δημιουργίας δοχείων/λοβών προφανώς λιπαρών (ή αντίστροφα), τον περιορισμό του αριθμού τους και προσδιορίστε την πιθανή διαφορά στις τιμές σε όρια και αιτήματα
  • ResourceQuotas — περιγράφει την πολιτική περιορισμού γενικά για όλα τα κοντέινερ σε ns και χρησιμοποιείται, κατά κανόνα, για την οριοθέτηση πόρων μεταξύ των περιβαλλόντων (χρήσιμο όταν τα περιβάλλοντα δεν είναι αυστηρά οριοθετημένα σε επίπεδο κόμβου)

Τα ακόλουθα είναι παραδείγματα εκδηλώσεων που θέτουν όρια πόρων:

  • Στο συγκεκριμένο επίπεδο κοντέινερ:

    containers:
    - name: app-nginx
      image: nginx
      resources:
        requests:
          memory: 1Gi
        limits:
          cpu: 200m

    Εκείνοι. Σε αυτήν την περίπτωση, για να τρέξετε ένα κοντέινερ με nginx, θα χρειαστείτε τουλάχιστον 1G δωρεάν RAM και 0.2 CPU στον κόμβο, ενώ το πολύ το κοντέινερ μπορεί να καταναλώσει 0.2 CPU και όλη τη διαθέσιμη μνήμη RAM στον κόμβο.

  • Στο ακέραιο επίπεδο ns:

    apiVersion: v1
    kind: ResourceQuota
    metadata:
      name: nxs-test
    spec:
      hard:
        requests.cpu: 300m
        requests.memory: 1Gi
        limits.cpu: 700m
        limits.memory: 2Gi

    Εκείνοι. το άθροισμα όλων των κοντέινερ αιτημάτων στα προεπιλεγμένα ns δεν μπορεί να υπερβαίνει τα 300m για την CPU και το 1G για το OP και το άθροισμα όλων των ορίων είναι 700m για την CPU και 2G για το OP.

  • Προεπιλεγμένα όρια για κοντέινερ σε ns:

    apiVersion: v1
    kind: LimitRange
    metadata:
      name: nxs-limit-per-container
    spec:
     limits:
       - type: Container
         defaultRequest:
           cpu: 100m
           memory: 1Gi
         default:
           cpu: 1
           memory: 2Gi
         min:
           cpu: 50m
           memory: 500Mi
         max:
           cpu: 2
           memory: 4Gi

    Εκείνοι. στον προεπιλεγμένο χώρο ονομάτων για όλα τα κοντέινερ, το αίτημα θα οριστεί σε 100 m για CPU και 1G για OP, όριο - 1 CPU και 2G. Ταυτόχρονα, ορίζεται επίσης ένα όριο στις πιθανές τιμές σε αίτημα/όριο για CPU (50m < x < 2) και RAM (500M < x < 4G).

  • Περιορισμοί σε επίπεδο pod ns:

    apiVersion: v1
    kind: LimitRange
    metadata:
     name: nxs-limit-pod
    spec:
     limits:
     - type: Pod
       max:
         cpu: 4
         memory: 1Gi

    Εκείνοι. για κάθε pod στο προεπιλεγμένο ns θα υπάρχει ένα όριο 4 vCPU και 1G.

Τώρα θα ήθελα να σας πω ποια πλεονεκτήματα μπορεί να μας δώσει η ρύθμιση αυτών των περιορισμών.

Μηχανισμός εξισορρόπησης φορτίου μεταξύ κόμβων

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

  1. φιλτράρισμα
  2. Που κυμαίνονται

Εκείνοι. σύμφωνα με την περιγραφόμενη πολιτική, αρχικά επιλέγονται κόμβοι στους οποίους είναι δυνατή η εκκίνηση ενός pod με βάση ένα σύνολο κατηγορήματα (συμπεριλαμβανομένου του ελέγχου εάν ο κόμβος έχει αρκετούς πόρους για την εκτέλεση του pod - PodFitsResources), και στη συνέχεια για καθέναν από αυτούς τους κόμβους, σύμφωνα με προτεραιότητες απονέμονται πόντοι (συμπεριλαμβανομένου, όσο περισσότερους ελεύθερους πόρους έχει ένας κόμβος, τόσο περισσότεροι βαθμοί του εκχωρούνται - LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) και το pod εκκινείται στον κόμβο με τους περισσότερους πόντους (αν αρκετοί κόμβοι ικανοποιούν αυτήν την προϋπόθεση ταυτόχρονα, τότε επιλέγεται ένα τυχαίο) .

Ταυτόχρονα, πρέπει να κατανοήσετε ότι ο προγραμματιστής, κατά την αξιολόγηση των διαθέσιμων πόρων ενός κόμβου, καθοδηγείται από τα δεδομένα που είναι αποθηκευμένα στο etcd - δηλ. για την ποσότητα του ζητούμενου/οριακού πόρου κάθε ομάδας που εκτελείται σε αυτόν τον κόμβο, αλλά όχι για την πραγματική κατανάλωση πόρων. Αυτές οι πληροφορίες μπορούν να ληφθούν από την έξοδο εντολών kubectl describe node $NODE, για παράδειγμα:

# kubectl describe nodes nxs-k8s-s1
..
Non-terminated Pods:         (9 in total)
  Namespace                  Name                                         CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                  ----                                         ------------  ----------  ---------------  -------------  ---
  ingress-nginx              nginx-ingress-controller-754b85bf44-qkt2t    0 (0%)        0 (0%)      0 (0%)           0 (0%)         233d
  kube-system                kube-flannel-26bl4                           150m (0%)     300m (1%)   64M (0%)         500M (1%)      233d
  kube-system                kube-proxy-exporter-cb629                    0 (0%)        0 (0%)      0 (0%)           0 (0%)         233d
  kube-system                kube-proxy-x9fsc                             0 (0%)        0 (0%)      0 (0%)           0 (0%)         233d
  kube-system                nginx-proxy-k8s-worker-s1                    25m (0%)      300m (1%)   32M (0%)         512M (1%)      233d
  nxs-monitoring             alertmanager-main-1                          100m (0%)     100m (0%)   425Mi (1%)       25Mi (0%)      233d
  nxs-logging                filebeat-lmsmp                               100m (0%)     0 (0%)      100Mi (0%)       200Mi (0%)     233d
  nxs-monitoring             node-exporter-v4gdq                          112m (0%)     122m (0%)   200Mi (0%)       220Mi (0%)     233d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests           Limits
  --------           --------           ------
  cpu                487m (3%)          822m (5%)
  memory             15856217600 (2%)  749976320 (3%)
  ephemeral-storage  0 (0%)             0 (0%)

Εδώ βλέπουμε όλα τα pods να τρέχουν σε έναν συγκεκριμένο κόμβο, καθώς και τους πόρους που ζητά κάθε pod. Και εδώ είναι πώς φαίνονται τα αρχεία καταγραφής προγραμματιστή όταν εκκινείται το cronjob-cron-events-1573793820-xt6q9 pod (αυτές οι πληροφορίες θα εμφανιστούν στο αρχείο καταγραφής προγραμματιστή όταν οριστεί το 10ο επίπεδο καταγραφής στα ορίσματα της εντολής εκκίνησης -v=10 ):

κούτσουρο

I1115 07:57:21.637791       1 scheduling_queue.go:908] About to try and schedule pod nxs-stage/cronjob-cron-events-1573793820-xt6q9                                                                                                                                           
I1115 07:57:21.637804       1 scheduler.go:453] Attempting to schedule pod: nxs-stage/cronjob-cron-events-1573793820-xt6q9                                                                                                                                                    
I1115 07:57:21.638285       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s5 is allowed, Node is running only 16 out of 110 Pods.                                                                               
I1115 07:57:21.638300       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s6 is allowed, Node is running only 20 out of 110 Pods.                                                                               
I1115 07:57:21.638322       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s3 is allowed, Node is running only 20 out of 110 Pods.                                                                               
I1115 07:57:21.638322       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s4 is allowed, Node is running only 17 out of 110 Pods.                                                                               
I1115 07:57:21.638334       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s10 is allowed, Node is running only 16 out of 110 Pods.                                                                              
I1115 07:57:21.638365       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s12 is allowed, Node is running only 9 out of 110 Pods.                                                                               
I1115 07:57:21.638334       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s11 is allowed, Node is running only 11 out of 110 Pods.                                                                              
I1115 07:57:21.638385       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s1 is allowed, Node is running only 19 out of 110 Pods.                                                                               
I1115 07:57:21.638402       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s2 is allowed, Node is running only 21 out of 110 Pods.                                                                               
I1115 07:57:21.638383       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s9 is allowed, Node is running only 16 out of 110 Pods.                                                                               
I1115 07:57:21.638335       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s8 is allowed, Node is running only 18 out of 110 Pods.                                                                               
I1115 07:57:21.638408       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s13 is allowed, Node is running only 8 out of 110 Pods.                                                                               
I1115 07:57:21.638478       1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s10 is allowed, existing pods anti-affinity terms satisfied.                                                                         
I1115 07:57:21.638505       1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s8 is allowed, existing pods anti-affinity terms satisfied.                                                                          
I1115 07:57:21.638577       1 predicates.go:1369] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s9 is allowed, existing pods anti-affinity terms satisfied.                                                                          
I1115 07:57:21.638583       1 predicates.go:829] Schedule Pod nxs-stage/cronjob-cron-events-1573793820-xt6q9 on Node nxs-k8s-s7 is allowed, Node is running only 25 out of 110 Pods.                                                                               
I1115 07:57:21.638932       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: BalancedResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 2343 millicores 9640186880 memory bytes, score 9        
I1115 07:57:21.638946       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: LeastResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 2343 millicores 9640186880 memory bytes, score 8           
I1115 07:57:21.638961       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: BalancedResourceAllocation, capacity 39900 millicores 66620170240 memory bytes, total request 4107 millicores 11307422720 memory bytes, score 9        
I1115 07:57:21.638971       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: BalancedResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 5847 millicores 24333637120 memory bytes, score 7        
I1115 07:57:21.638975       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: LeastResourceAllocation, capacity 39900 millicores 66620170240 memory bytes, total request 4107 millicores 11307422720 memory bytes, score 8           
I1115 07:57:21.638990       1 resource_allocation.go:78] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: LeastResourceAllocation, capacity 39900 millicores 66620178432 memory bytes, total request 5847 millicores 24333637120 memory bytes, score 7           
I1115 07:57:21.639022       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: TaintTolerationPriority, Score: (10)                                                                                                        
I1115 07:57:21.639030       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: TaintTolerationPriority, Score: (10)                                                                                                         
I1115 07:57:21.639034       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: TaintTolerationPriority, Score: (10)                                                                                                         
I1115 07:57:21.639041       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: NodeAffinityPriority, Score: (0)                                                                                                            
I1115 07:57:21.639053       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: NodeAffinityPriority, Score: (0)                                                                                                             
I1115 07:57:21.639059       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: NodeAffinityPriority, Score: (0)                                                                                                             
I1115 07:57:21.639061       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: InterPodAffinityPriority, Score: (0)                                                                                                                   
I1115 07:57:21.639063       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s10: SelectorSpreadPriority, Score: (10)                                                                                                                   
I1115 07:57:21.639073       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: InterPodAffinityPriority, Score: (0)                                                                                                                    
I1115 07:57:21.639077       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s8: SelectorSpreadPriority, Score: (10)                                                                                                                    
I1115 07:57:21.639085       1 interpod_affinity.go:237] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: InterPodAffinityPriority, Score: (0)                                                                                                                    
I1115 07:57:21.639088       1 selector_spreading.go:146] cronjob-cron-events-1573793820-xt6q9 -> nxs-k8s-s9: SelectorSpreadPriority, Score: (10)                                                                                                                    
I1115 07:57:21.639103       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s10: SelectorSpreadPriority, Score: (10)                                                                                                         
I1115 07:57:21.639109       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s8: SelectorSpreadPriority, Score: (10)                                                                                                          
I1115 07:57:21.639114       1 generic_scheduler.go:726] cronjob-cron-events-1573793820-xt6q9_nxs-stage -> nxs-k8s-s9: SelectorSpreadPriority, Score: (10)                                                                                                          
I1115 07:57:21.639127       1 generic_scheduler.go:781] Host nxs-k8s-s10 => Score 100037                                                                                                                                                                            
I1115 07:57:21.639150       1 generic_scheduler.go:781] Host nxs-k8s-s8 => Score 100034                                                                                                                                                                             
I1115 07:57:21.639154       1 generic_scheduler.go:781] Host nxs-k8s-s9 => Score 100037                                                                                                                                                                             
I1115 07:57:21.639267       1 scheduler_binder.go:269] AssumePodVolumes for pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", node "nxs-k8s-s10"                                                                                                               
I1115 07:57:21.639286       1 scheduler_binder.go:279] AssumePodVolumes for pod "nxs-stage/cronjob-cron-events-1573793820-xt6q9", node "nxs-k8s-s10": all PVCs bound and nothing to do                                                                             
I1115 07:57:21.639333       1 factory.go:733] Attempting to bind cronjob-cron-events-1573793820-xt6q9 to nxs-k8s-s10

Εδώ βλέπουμε ότι αρχικά ο προγραμματιστής φιλτράρει και δημιουργεί μια λίστα με 3 κόμβους στους οποίους μπορεί να εκκινηθεί (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Στη συνέχεια, υπολογίζει τις βαθμολογίες με βάση διάφορες παραμέτρους (συμπεριλαμβανομένων BalancedResourceAllocation, LeastResourceAllocation) για κάθε έναν από αυτούς τους κόμβους προκειμένου να προσδιορίσει τον καταλληλότερο κόμβο. Τελικά, το pod είναι προγραμματισμένο στον κόμβο με τον μεγαλύτερο αριθμό σημείων (εδώ δύο κόμβοι έχουν τον ίδιο αριθμό σημείων 100037, επομένως επιλέγεται ένας τυχαίος - nxs-k8s-s10).

Παραγωγή: εάν ένας κόμβος εκτελεί λοβούς για τους οποίους δεν έχουν οριστεί περιορισμοί, τότε για k8 (από την άποψη της κατανάλωσης πόρων) αυτό θα ισοδυναμεί με σαν να μην υπήρχαν καθόλου τέτοιοι δεσμοί σε αυτόν τον κόμβο. Επομένως, εάν, υπό όρους, έχετε ένα pod με μια λαίμαργη διαδικασία (για παράδειγμα, wowza) και δεν έχουν τεθεί περιορισμοί γι 'αυτό, τότε μπορεί να προκύψει μια κατάσταση όταν αυτό το pod πραγματικά έφαγε όλους τους πόρους του κόμβου, αλλά για k8s αυτός ο κόμβος θεωρείται μη φορτωμένος και θα του απονεμηθεί ο ίδιος αριθμός πόντων κατά την κατάταξη (ακριβώς σε σημεία αξιολόγησης των διαθέσιμων πόρων) ως κόμβος που δεν διαθέτει λοβούς εργασίας, κάτι που τελικά μπορεί να οδηγήσει σε ανομοιόμορφη κατανομή του φορτίου μεταξύ των κόμβων.

Έξωση του Ποντ

Όπως γνωρίζετε, σε κάθε ομάδα έχει εκχωρηθεί μία από τις 3 κατηγορίες QoS:

  1. εγγυημένη — εκχωρείται όταν για κάθε κοντέινερ στο pod καθορίζεται ένα αίτημα και ένα όριο για τη μνήμη και την cpu, και αυτές οι τιμές πρέπει να ταιριάζουν
  2. διαρρηγμένος — τουλάχιστον ένα κοντέινερ στην ομάδα έχει ένα αίτημα και ένα όριο, με αίτημα < όριο
  3. καλύτερη προσπάθεια — όταν κανένα κοντέινερ στο pod δεν έχει περιορισμένους πόρους

Ταυτόχρονα, όταν ένας κόμβος αντιμετωπίζει έλλειψη πόρων (δίσκος, μνήμη), το kubelet αρχίζει να ταξινομεί και να αποβάλλει τα pods σύμφωνα με έναν συγκεκριμένο αλγόριθμο που λαμβάνει υπόψη την προτεραιότητα του pod και την κλάση QoS του. Για παράδειγμα, αν μιλάμε για μνήμη RAM, τότε με βάση την κατηγορία QoS, οι βαθμοί απονέμονται σύμφωνα με την ακόλουθη αρχή:

  • Εγγυημένα:-998
  • Καλύτερη προσπάθεια: 1000
  • Διαρρηγμένος: min(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

Εκείνοι. με την ίδια προτεραιότητα, το kubelet θα εξάγει πρώτα τα pods με την καλύτερη δυνατή προσπάθεια κλάσης QoS από τον κόμβο.

Παραγωγή: εάν θέλετε να μειώσετε την πιθανότητα αποβολής του επιθυμητού pod από τον κόμβο σε περίπτωση έλλειψης πόρων σε αυτό, τότε μαζί με την προτεραιότητα, πρέπει επίσης να φροντίσετε να ορίσετε το αίτημα/όριο για αυτό.

Μηχανισμός για οριζόντια αυτόματη κλιμάκωση λοβών εφαρμογής (HPA)

Όταν η εργασία είναι η αυτόματη αύξηση και μείωση του αριθμού των pods ανάλογα με τη χρήση των πόρων (σύστημα - CPU/RAM ή χρήστης - rps), μια οντότητα k8s όπως ΗΡΑ (Horizontal Pod Autoscaler). Ο αλγόριθμος του οποίου έχει ως εξής:

  1. Καθορίζονται οι τρέχουσες μετρήσεις του παρατηρούμενου πόρου (currentMetricValue)
  2. Καθορίζονται οι επιθυμητές τιμές για τον πόρο (desiredMetricValue), οι οποίες για τους πόρους του συστήματος ορίζονται χρησιμοποιώντας αίτημα
  3. Καθορίζεται ο τρέχων αριθμός αντιγράφων (currentReplicas)
  4. Ο παρακάτω τύπος υπολογίζει τον επιθυμητό αριθμό αντιγράφων (επιθυμητά αντίγραφα)
    επιθυμητάReplicas = [currentReplicas * (currentMetricValue / επιθυμητήMetricValue)]

Σε αυτήν την περίπτωση, η κλιμάκωση δεν θα προκύψει όταν ο συντελεστής (currentMetricValue / επιθυμητόMetricValue) είναι κοντά στο 1 (σε αυτήν την περίπτωση, μπορούμε να ορίσουμε μόνοι μας το επιτρεπόμενο σφάλμα, από προεπιλογή είναι 0.1).

Ας δούμε πώς λειτουργεί το hpa χρησιμοποιώντας το παράδειγμα της εφαρμογής δοκιμής εφαρμογής (που περιγράφεται ως Deployment), όπου είναι απαραίτητο να αλλάξετε τον αριθμό των αντιγράφων ανάλογα με την κατανάλωση της CPU:

  • Δηλωτικό εφαρμογής

    kind: Deployment
    apiVersion: apps/v1beta2
    metadata:
    name: app-test
    spec:
    selector:
    matchLabels:
    app: app-test
    replicas: 2
    template:
    metadata:
    labels:
    app: app-test
    spec:
    containers:
    - name: nginx
    image: registry.nixys.ru/generic-images/nginx
    imagePullPolicy: Always
    resources:
    requests:
    cpu: 60m
    ports:
    - name: http
    containerPort: 80
    - name: nginx-exporter
    image: nginx/nginx-prometheus-exporter
    resources:
    requests:
    cpu: 30m
    ports:
    - name: nginx-exporter
    containerPort: 9113
    args:
    - -nginx.scrape-uri
    - http://127.0.0.1:80/nginx-status

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

  • Μανιφέστο HPA

    apiVersion: autoscaling/v2beta2
    kind: HorizontalPodAutoscaler
    metadata:
    name: app-test-hpa
    spec:
    maxReplicas: 10
    minReplicas: 2
    scaleTargetRef:
    apiVersion: extensions/v1beta1
    kind: Deployment
    name: app-test
    metrics:
    - type: Resource
    resource:
    name: cpu
    target:
    type: Utilization
    averageUtilization: 30

    Εκείνοι. Δημιουργήσαμε ένα hpa που θα παρακολουθεί το Deployment app-test και θα προσαρμόζει τον αριθμό των pods με την εφαρμογή με βάση τον δείκτη cpu (αναμένουμε ότι το pod θα καταναλώνει το 30% της CPU που ζητά), με τον αριθμό των αντιγράφων να είναι το εύρος 2-10.

    Τώρα, ας δούμε τον μηχανισμό λειτουργίας του hpa εάν εφαρμόσουμε ένα φορτίο σε μία από τις εστίες:

     # kubectl top pod
    NAME                                                   CPU(cores)   MEMORY(bytes)
    app-test-78559f8f44-pgs58            101m         243Mi
    app-test-78559f8f44-cj4jz            4m           240Mi

Συνολικά έχουμε τα εξής:

  • Η επιθυμητή τιμή (desiredMetricValue) - σύμφωνα με τις ρυθμίσεις hpa, έχουμε 30%
  • Τρέχουσα τιμή (currentMetricValue) - για τον υπολογισμό, ο ελεγκτής-διαχειριστής υπολογίζει τη μέση τιμή της κατανάλωσης πόρων σε %, δηλ. υπό όρους κάνει τα εξής:
    1. Λαμβάνει απόλυτες τιμές μετρήσεων pod από τον διακομιστή μετρήσεων, π.χ. 101μ και 4μ
    2. Υπολογίζει τη μέση απόλυτη τιμή, δηλ. (101m + 4m) / 2 = 53m
    3. Λαμβάνει την απόλυτη τιμή για την επιθυμητή κατανάλωση πόρων (για αυτό, αθροίζονται τα αιτήματα όλων των κοντέινερ) 60m + 30m = 90m
    4. Υπολογίζει το μέσο ποσοστό κατανάλωσης CPU σε σχέση με την ομάδα αιτήματος, π.χ. 53m / 90m * 100% = 59%

Τώρα έχουμε όλα όσα χρειαζόμαστε για να καθορίσουμε εάν πρέπει να αλλάξουμε τον αριθμό των αντιγράφων· για να γίνει αυτό, υπολογίζουμε τον συντελεστή:

ratio = 59% / 30% = 1.96

Εκείνοι. ο αριθμός των αντιγράφων θα πρέπει να αυξηθεί κατά ~2 φορές και να ανέλθει σε [2 * 1.96] = 4.

Συμπέρασμα: Όπως μπορείτε να δείτε, για να λειτουργήσει αυτός ο μηχανισμός, απαραίτητη προϋπόθεση είναι η παρουσία αιτημάτων για όλα τα κοντέινερ στο παρατηρούμενο pod.

Μηχανισμός οριζόντιας αυτόματης κλιμάκωσης κόμβων (Cluster Autoscaler)

Προκειμένου να εξουδετερωθούν οι αρνητικές επιπτώσεις στο σύστημα κατά τις υπερτάσεις φορτίου, δεν αρκεί να έχετε ένα διαμορφωμένο hpa. Για παράδειγμα, σύμφωνα με τις ρυθμίσεις στον διαχειριστή ελεγκτών hpa, αποφασίζει ότι ο αριθμός των αντιγράφων πρέπει να αυξηθεί κατά 2 φορές, αλλά οι κόμβοι δεν έχουν ελεύθερους πόρους για να τρέξουν έναν τέτοιο αριθμό pods (δηλ. ο κόμβος δεν μπορεί να παρέχει ζητήθηκαν πόροι στην ομάδα αιτημάτων) και αυτές οι ομάδες μεταβαίνουν στην κατάσταση Εκκρεμότητα.

Σε αυτήν την περίπτωση, εάν ο πάροχος έχει αντίστοιχο IaaS/PaaS (για παράδειγμα, GKE/GCE, AKS, EKS κ.λπ.), ένα εργαλείο όπως Κόμβος Autoscaler. Σας επιτρέπει να ορίσετε τον μέγιστο και ελάχιστο αριθμό κόμβων στο σύμπλεγμα και να προσαρμόσετε αυτόματα τον τρέχοντα αριθμό κόμβων (καλώντας το API του παρόχου cloud για να παραγγείλετε/αφαιρέσετε έναν κόμβο) όταν υπάρχει έλλειψη πόρων στο σύμπλεγμα και τις ομάδες δεν μπορεί να προγραμματιστεί (βρίσκονται σε κατάσταση εκκρεμότητας).

Συμπέρασμα: Για να μπορείτε να κάνετε αυτόματη κλίμακα κόμβων, είναι απαραίτητο να ορίσετε αιτήματα στα κοντέινερ pod, έτσι ώστε τα k8s να μπορούν να αξιολογήσουν σωστά το φορτίο στους κόμβους και να αναφέρουν κατά συνέπεια ότι δεν υπάρχουν πόροι στο σύμπλεγμα για την εκκίνηση του επόμενου pod.

Συμπέρασμα

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

  1. Για πιο ακριβή λειτουργία του χρονοπρογραμματιστή όσον αφορά την εξισορρόπηση φορτίου μεταξύ κόμβων k8s
  2. Για να μειώσετε την πιθανότητα να συμβεί ένα συμβάν «εξώθησης λοβού».
  3. Για να λειτουργήσει η οριζόντια αυτόματη κλιμάκωση των υποδοχών εφαρμογής (HPA).
  4. Για οριζόντια αυτόματη κλιμάκωση κόμβων (Cluster Autoscaling) για παρόχους cloud

Διαβάστε επίσης άλλα άρθρα στο ιστολόγιό μας:

Πηγή: www.habr.com

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