Kubernetes: เหตุใดการตั้งค่าการจัดการทรัพยากรระบบจึงมีความสำคัญ

ตามกฎแล้ว จำเป็นต้องจัดเตรียมแหล่งทรัพยากรเฉพาะให้กับแอปพลิเคชันเสมอเพื่อการทำงานที่ถูกต้องและมีเสถียรภาพ แต่จะเกิดอะไรขึ้นหากแอพพลิเคชั่นหลายตัวทำงานด้วยพลังงานเดียวกัน? จะจัดหาทรัพยากรที่จำเป็นขั้นต่ำให้กับแต่ละคนได้อย่างไร? คุณจะจำกัดการใช้ทรัพยากรได้อย่างไร? จะกระจายโหลดระหว่างโหนดได้อย่างถูกต้องได้อย่างไร? จะมั่นใจได้อย่างไรว่ากลไกการปรับขนาดแนวนอนทำงานหากโหลดแอปพลิเคชันเพิ่มขึ้น

Kubernetes: เหตุใดการตั้งค่าการจัดการทรัพยากรระบบจึงมีความสำคัญ

คุณต้องเริ่มต้นด้วยทรัพยากรประเภทหลักที่มีอยู่ในระบบ - แน่นอนว่านี่คือเวลาโปรเซสเซอร์และ RAM ใน k8s manifest ประเภททรัพยากรเหล่านี้จะถูกวัดในหน่วยต่อไปนี้:

  • CPU - ในคอร์
  • RAM - เป็นไบต์

นอกจากนี้ สำหรับแต่ละทรัพยากร คุณสามารถกำหนดข้อกำหนดได้สองประเภท - การร้องขอ и ขีด จำกัด. คำขอ - อธิบายข้อกำหนดขั้นต่ำสำหรับทรัพยากรว่างของโหนดเพื่อเรียกใช้คอนเทนเนอร์ (และพ็อดโดยรวม) ในขณะที่ขีดจำกัดจะกำหนดขีดจำกัดที่ชัดเจนสำหรับทรัพยากรที่พร้อมใช้งานสำหรับคอนเทนเนอร์

สิ่งสำคัญคือต้องเข้าใจว่ารายการไม่จำเป็นต้องกำหนดทั้งสองประเภทอย่างชัดเจน แต่ลักษณะการทำงานจะเป็นดังนี้:

  • หากมีการระบุเฉพาะขีดจำกัดของทรัพยากรอย่างชัดเจน คำขอสำหรับทรัพยากรนี้จะใช้ค่าเท่ากับขีดจำกัดโดยอัตโนมัติ (คุณสามารถตรวจสอบได้โดยการเรียกเอนทิตีอธิบาย) เหล่านั้น. ที่จริงแล้วคอนเทนเนอร์จะถูกจำกัดให้ใช้ทรัพยากรในปริมาณเท่ากันที่ต้องใช้ในการทำงาน
  • หากมีการระบุเฉพาะคำขออย่างชัดเจนสำหรับทรัพยากร จะไม่มีการตั้งค่าข้อจำกัดขั้นสูงบนทรัพยากรนี้ - กล่าวคือ คอนเทนเนอร์ถูกจำกัดโดยทรัพยากรของโหนดเท่านั้น

นอกจากนี้ยังสามารถกำหนดค่าการจัดการทรัพยากรได้ไม่เพียงแต่ในระดับคอนเทนเนอร์เฉพาะเท่านั้น แต่ยังรวมถึงระดับเนมสเปซโดยใช้เอนทิตีต่อไปนี้:

  • ช่วงขีดจำกัด — อธิบายนโยบายข้อจำกัดที่ระดับคอนเทนเนอร์/พ็อดในหน่วย ns และจำเป็นเพื่ออธิบายขีดจำกัดเริ่มต้นบนคอนเทนเนอร์/พ็อด รวมถึงป้องกันการสร้างคอนเทนเนอร์/พ็อดที่มีไขมันอย่างเห็นได้ชัด (หรือกลับกัน) จำกัดจำนวน และกำหนดความแตกต่างที่เป็นไปได้ของค่าในขีดจำกัดและคำขอ
  • โควต้าทรัพยากร — อธิบายนโยบายข้อจำกัดโดยทั่วไปสำหรับคอนเทนเนอร์ทั้งหมดใน ns และใช้เป็นกฎเพื่อกำหนดขอบเขตทรัพยากรระหว่างสภาพแวดล้อม (มีประโยชน์เมื่อสภาพแวดล้อมไม่ได้แบ่งเขตอย่างเคร่งครัดที่ระดับโหนด)

ต่อไปนี้เป็นตัวอย่างของรายการที่กำหนดขีดจำกัดทรัพยากร:

  • ที่ระดับคอนเทนเนอร์เฉพาะ:

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

    เหล่านั้น. ในกรณีนี้ ในการรันคอนเทนเนอร์ด้วย nginx คุณจะต้องมี RAM ว่างอย่างน้อย 1G และ CPU 0.2 บนโหนด ในขณะที่คอนเทนเนอร์ส่วนใหญ่สามารถใช้ CPU 0.2 และ 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

    เหล่านั้น. ในเนมสเปซเริ่มต้นสำหรับคอนเทนเนอร์ทั้งหมด คำขอจะถูกตั้งค่าเป็น 100m สำหรับ CPU และ 1G สำหรับ OP จำกัด - 1 CPU และ 2G ในเวลาเดียวกัน ขีดจำกัดยังถูกตั้งค่าที่เป็นไปได้ในคำขอ/ขีดจำกัดสำหรับ CPU (50m < x < 2) และ RAM (500M < x < 4G)

  • ข้อจำกัดระดับพ็อด ns:

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

    เหล่านั้น. สำหรับแต่ละพ็อดในค่าเริ่มต้น ns จะมีขีดจำกัดอยู่ที่ 4 vCPU และ 1G

ตอนนี้ฉันอยากจะบอกคุณว่าการตั้งค่าข้อจำกัดเหล่านี้มีประโยชน์อะไรบ้าง

กลไกการปรับสมดุลโหลดระหว่างโหนด

ดังที่คุณทราบ องค์ประกอบ k8s มีหน้าที่รับผิดชอบในการกระจายพ็อดระหว่างโหนด เช่น กำหนดการซึ่งทำงานตามอัลกอริทึมเฉพาะ อัลกอริธึมนี้ต้องผ่านสองขั้นตอนเมื่อเลือกโหนดที่เหมาะสมที่สุดที่จะเปิดตัว:

  1. กรอง
  2. ระยะ

เหล่านั้น. ตามนโยบายที่อธิบายไว้ ในตอนแรกโหนดจะถูกเลือกซึ่งเป็นไปได้ที่จะเปิดพ็อดตามชุด ภาคแสดง (รวมถึงการตรวจสอบว่าโหนดมีทรัพยากรเพียงพอที่จะรันพ็อด - PodFitsResources หรือไม่) จากนั้นสำหรับแต่ละโหนดเหล่านี้ตาม จัดลำดับความสำคัญ คะแนนจะได้รับ (รวมถึงยิ่งทรัพยากรว่างที่โหนดมีมากเท่าใด ก็จะยิ่งได้รับคะแนนมากขึ้นเท่านั้น - LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) และพ็อดถูกเปิดใช้งานบนโหนดที่มีคะแนนมากที่สุด (หากหลายโหนดตรงตามเงื่อนไขนี้ในคราวเดียว จากนั้น จะมีการสุ่มเลือก)

ในเวลาเดียวกันคุณต้องเข้าใจว่าเมื่อประเมินทรัพยากรที่มีอยู่ของโหนดนั้นตัวกำหนดเวลานั้นจะได้รับคำแนะนำจากข้อมูลที่เก็บไว้ใน ฯลฯ - เช่น สำหรับจำนวนทรัพยากรที่ร้องขอ/จำกัดของแต่ละพ็อดที่ทำงานบนโหนดนี้ แต่ไม่ใช่สำหรับการใช้ทรัพยากรจริง ข้อมูลนี้สามารถรับได้จากเอาต์พุตคำสั่ง 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%)

ที่นี่เราจะเห็นพ็อดทั้งหมดที่ทำงานบนโหนดเฉพาะ รวมถึงทรัพยากรที่แต่ละพ็อดร้องขอ และนี่คือลักษณะของบันทึกของตัวกำหนดเวลาเมื่อมีการเปิดตัวพ็อด cronjob-cron-events-1573793820-xt6q9 (ข้อมูลนี้จะปรากฏในบันทึกของตัวกำหนดเวลาเมื่อคุณตั้งค่าระดับการบันทึกที่ 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) สำหรับแต่ละโหนดเหล่านี้เพื่อกำหนดโหนดที่เหมาะสมที่สุด ในที่สุด พ็อดจะถูกกำหนดเวลาบนโหนดที่มีจำนวนคะแนนสูงสุด (ที่นี่ สองโหนดพร้อมกันมีจำนวนคะแนนเท่ากัน 100037 ดังนั้นจึงเลือกสุ่มหนึ่งอัน - nxs-k8s-s10)

เอาท์พุต: หากโหนดรันพ็อดที่ไม่มีการตั้งค่าข้อจำกัด ดังนั้นสำหรับ k8s (จากมุมมองของการใช้ทรัพยากร) สิ่งนี้จะเทียบเท่ากับราวกับว่าไม่มีพ็อดดังกล่าวบนโหนดนี้เลย ดังนั้นหากคุณตามเงื่อนไขมีพ็อดที่มีกระบวนการตะกละ (เช่น wowza) และไม่มีการกำหนดข้อ จำกัด ไว้สถานการณ์อาจเกิดขึ้นเมื่อพ็อดนี้กินทรัพยากรทั้งหมดของโหนดจริง ๆ แต่สำหรับ k8s โหนดนี้ ถือว่าไม่ได้โหลดและจะได้รับคะแนนเท่ากันเมื่อจัดอันดับ (แม่นยำในคะแนนที่ประเมินทรัพยากรที่มีอยู่) เป็นโหนดที่ไม่มีพ็อดที่ใช้งานได้ ซึ่งท้ายที่สุดอาจนำไปสู่การกระจายโหลดระหว่างโหนดที่ไม่สม่ำเสมอ

การขับไล่พ็อด

ดังที่คุณทราบ แต่ละพ็อดได้รับการกำหนดหนึ่งใน 3 คลาส QoS:

  1. รับประกัน — ได้รับการกำหนดเมื่อมีการระบุคำขอและขีด จำกัด สำหรับแต่ละคอนเทนเนอร์ในพ็อดสำหรับหน่วยความจำและ cpu และค่าเหล่านี้จะต้องตรงกัน
  2. ระเบิดได้ — อย่างน้อยหนึ่งคอนเทนเนอร์ในพ็อดมีคำขอและขีดจำกัด โดยมีคำขอ < ขีดจำกัด
  3. สุดความพยายาม — เมื่อไม่มีคอนเทนเนอร์เดียวในพ็อดที่มีทรัพยากรจำกัด

ในเวลาเดียวกัน เมื่อโหนดประสบปัญหาขาดแคลนทรัพยากร (ดิสก์ หน่วยความจำ) kubelet จะเริ่มจัดอันดับและกำจัดพ็อดตามอัลกอริทึมเฉพาะที่คำนึงถึงลำดับความสำคัญของพ็อดและคลาส QoS ของมัน ตัวอย่างเช่นหากเรากำลังพูดถึง RAM ตามคลาส QoS คะแนนจะได้รับตามหลักการดังต่อไปนี้:

  • รับประกัน: 998
  • ความพยายามที่ดีที่สุด: 1000
  • ระเบิดได้: นาที (สูงสุด (2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999)

เหล่านั้น. ด้วยลำดับความสำคัญเท่ากัน kubelet จะไล่พ็อดที่มีคลาส QoS อย่างดีที่สุดออกจากโหนดก่อน

เอาท์พุต: หากคุณต้องการลดโอกาสที่พ็อดที่ต้องการจะถูกไล่ออกจากโหนดในกรณีที่ไม่มีทรัพยากรในโหนดนั้น คุณจะต้องดูแลการตั้งค่าคำขอ/ขีดจำกัดของพ็อดนั้น นอกเหนือจากลำดับความสำคัญแล้ว

กลไกสำหรับการปรับขนาดแนวนอนอัตโนมัติของพ็อดแอปพลิเคชัน (HPA)

เมื่องานคือการเพิ่มและลดจำนวนพ็อดโดยอัตโนมัติขึ้นอยู่กับการใช้ทรัพยากร (ระบบ - CPU/RAM หรือผู้ใช้ - rps) เอนทิตี k8s เช่น HPA (ตัวปรับขนาดอัตโนมัติพ็อดแนวนอน) อัลกอริธึมซึ่งมีดังต่อไปนี้:

  1. การอ่านค่าปัจจุบันของทรัพยากรที่สังเกตได้ถูกกำหนด (currentMetricValue)
  2. ค่าที่ต้องการสำหรับทรัพยากรจะถูกกำหนด (desiredMetricValue) ซึ่งสำหรับทรัพยากรระบบจะถูกตั้งค่าโดยใช้คำขอ
  3. กำหนดจำนวนเรพลิกาปัจจุบัน (currentReplicas)
  4. สูตรต่อไปนี้คำนวณจำนวนแบบจำลองที่ต้องการ (desiredReplicas)
    ที่ต้องการReplicas = [ currentReplicas * ( currentMetricValue / ที่ต้องการMetricValue )]

ในกรณีนี้ มาตราส่วนจะไม่เกิดขึ้นเมื่อค่าสัมประสิทธิ์ (currentMetricValue / WishMetricValue) อยู่ใกล้กับ 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

    เหล่านั้น. เราเห็นว่าพ็อดแอปพลิเคชันเปิดตัวครั้งแรกในสองอินสแตนซ์ โดยแต่ละอินสแตนซ์มีสองคอนเทนเนอร์ nginx และ nginx-exporter โดยแต่ละคอนเทนเนอร์ที่ระบุ การร้องขอ สำหรับซีพียู

  • แถลงการณ์ 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 ที่จะตรวจสอบการทดสอบแอปการปรับใช้และปรับจำนวนพ็อดด้วยแอปพลิเคชันตามตัวบ่งชี้ cpu (เราคาดว่าพ็อดควรใช้ 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. รับค่าสัมบูรณ์ของเมทริกพ็อดจากเซิร์ฟเวอร์เมทริก เช่น 101ม. และ 4ม
    2. คำนวณค่าสัมบูรณ์เฉลี่ย เช่น (101ม. + 4ม.) / 2 = 53ม
    3. รับค่าสัมบูรณ์สำหรับการใช้ทรัพยากรที่ต้องการ (สำหรับสิ่งนี้ คำขอของคอนเทนเนอร์ทั้งหมดจะถูกรวมเข้าด้วยกัน) 60m + 30m = 90m
    4. คำนวณเปอร์เซ็นต์เฉลี่ยของการใช้ CPU ที่สัมพันธ์กับพ็อดคำขอ เช่น 53 ม. / 90 ม. * 100% = 59%

ตอนนี้เรามีทุกสิ่งที่จำเป็นในการพิจารณาว่าจำเป็นต้องเปลี่ยนจำนวนเรพลิกาหรือไม่ โดยคำนวณค่าสัมประสิทธิ์:

ratio = 59% / 30% = 1.96

เหล่านั้น. ควรเพิ่มจำนวนแบบจำลองประมาณ 2 เท่าและจำนวนเป็น [2 * 1.96] = 4

สรุป: อย่างที่คุณเห็นเพื่อให้กลไกนี้ทำงานได้ เงื่อนไขที่จำเป็นคือการมีคำขอสำหรับคอนเทนเนอร์ทั้งหมดในพ็อดที่สังเกต

กลไกสำหรับการปรับขนาดอัตโนมัติแนวนอนของโหนด (Cluster Autoscaler)

เพื่อที่จะต่อต้านผลกระทบด้านลบต่อระบบระหว่างโหลดไฟกระชาก การมี hpa ที่กำหนดค่าไว้นั้นไม่เพียงพอ ตัวอย่างเช่น ตามการตั้งค่าในตัวจัดการคอนโทรลเลอร์ hpa ตัดสินใจว่าจะต้องเพิ่มจำนวนเรพลิกา 2 เท่า แต่โหนดไม่มีทรัพยากรว่างในการรันพ็อดจำนวนดังกล่าว (เช่น โหนดไม่สามารถจัดเตรียม ร้องขอทรัพยากรไปยังพ็อดคำขอ) และพ็อดเหล่านี้จะสลับไปที่สถานะรอดำเนินการ

ในกรณีนี้ หากผู้ให้บริการมี IaaS/PaaS ที่สอดคล้องกัน (เช่น GKE/GCE, AKS, EKS เป็นต้น) เครื่องมืออย่างเช่น ตัวปรับขนาดอัตโนมัติของโหนด. ช่วยให้คุณสามารถตั้งค่าจำนวนโหนดสูงสุดและต่ำสุดในคลัสเตอร์และปรับจำนวนโหนดปัจจุบันโดยอัตโนมัติ (โดยการเรียก API ของผู้ให้บริการระบบคลาวด์เพื่อสั่งซื้อ/ลบโหนด) เมื่อขาดทรัพยากรในคลัสเตอร์และพ็อด ไม่สามารถกำหนดเวลาได้ (อยู่ในสถานะรอดำเนินการ)

สรุป: เพื่อให้สามารถปรับขนาดโหนดอัตโนมัติได้ จำเป็นต้องตั้งค่าคำขอในคอนเทนเนอร์พ็อดเพื่อให้ k8 สามารถประเมินโหลดบนโหนดได้อย่างถูกต้อง และรายงานตามลำดับว่าไม่มีทรัพยากรในคลัสเตอร์ที่จะเปิดตัวพ็อดถัดไป

ข้อสรุป

ควรสังเกตว่าการตั้งค่าขีดจำกัดทรัพยากรคอนเทนเนอร์ไม่ใช่ข้อกำหนดเพื่อให้แอปพลิเคชันทำงานได้สำเร็จ แต่ยังดีกว่าหากทำเช่นนั้นด้วยเหตุผลต่อไปนี้:

  1. เพื่อการทำงานของตัวกำหนดตารางเวลาที่แม่นยำยิ่งขึ้นในแง่ของการปรับสมดุลโหลดระหว่างโหนด k8s
  2. เพื่อลดโอกาสที่จะเกิดเหตุการณ์ "การขับไล่พ็อด"
  3. เพื่อให้การปรับขนาดอัตโนมัติแนวนอนของพ็อดแอปพลิเคชัน (HPA) ทำงาน
  4. สำหรับการปรับขนาดอัตโนมัติแนวนอนของโหนด (Cluster Autoscaling) สำหรับผู้ให้บริการคลาวด์

อ่านบทความอื่น ๆ ในบล็อกของเราด้วย:

ที่มา: will.com

เพิ่มความคิดเห็น