Kubernetes: tại sao việc cấu hình quản lý tài nguyên hệ thống lại quan trọng đến vậy?

Theo quy định, luôn cần phải cung cấp một nhóm tài nguyên dành riêng cho ứng dụng để ứng dụng đó hoạt động chính xác và ổn định. Nhưng điều gì sẽ xảy ra nếu nhiều ứng dụng đang chạy trên cùng một nguồn điện? Làm thế nào để cung cấp cho mỗi người trong số họ những nguồn lực cần thiết tối thiểu? Làm thế nào bạn có thể hạn chế tiêu thụ tài nguyên? Làm thế nào để phân phối tải chính xác giữa các nút? Làm cách nào để đảm bảo cơ chế chia tỷ lệ theo chiều ngang hoạt động nếu tải ứng dụng tăng?

Kubernetes: tại sao việc cấu hình quản lý tài nguyên hệ thống lại quan trọng đến vậy?

Bạn cần bắt đầu với những loại tài nguyên chính tồn tại trong hệ thống - tất nhiên, đây là thời gian xử lý và RAM. Trong tệp kê khai k8s, các loại tài nguyên này được đo bằng các đơn vị sau:

  • CPU - trong lõi
  • RAM - tính bằng byte

Hơn nữa, đối với mỗi tài nguyên, có thể đặt hai loại yêu cầu - yêu cầu и giới hạn. Yêu cầu - mô tả các yêu cầu tối thiểu đối với tài nguyên miễn phí của một nút để chạy một vùng chứa (và toàn bộ nhóm), trong khi các giới hạn đặt giới hạn cứng đối với các tài nguyên có sẵn cho vùng chứa.

Điều quan trọng là phải hiểu rằng tệp kê khai không nhất thiết phải xác định rõ ràng cả hai loại nhưng hành vi sẽ như sau:

  • Nếu chỉ giới hạn của tài nguyên được chỉ định rõ ràng thì các yêu cầu đối với tài nguyên này sẽ tự động nhận giá trị bằng giới hạn (bạn có thể xác minh điều này bằng cách gọi các thực thể mô tả). Những thứ kia. trên thực tế, vùng chứa sẽ bị giới hạn ở cùng lượng tài nguyên mà nó yêu cầu để chạy.
  • Nếu chỉ các yêu cầu được chỉ định rõ ràng cho một tài nguyên thì không có hạn chế cao hơn nào được đặt đối với tài nguyên này - tức là. vùng chứa chỉ bị giới hạn bởi tài nguyên của chính nút đó.

Cũng có thể định cấu hình quản lý tài nguyên không chỉ ở cấp vùng chứa cụ thể mà còn ở cấp không gian tên bằng cách sử dụng các thực thể sau:

  • Phạm vi giới hạn — mô tả chính sách hạn chế ở cấp độ vùng chứa/nhóm tính bằng ns và cần thiết để mô tả các giới hạn mặc định trên vùng chứa/nhóm, cũng như ngăn chặn việc tạo ra các vùng chứa/nhóm chất béo rõ ràng (hoặc ngược lại), giới hạn số lượng của chúng và xác định sự khác biệt có thể có trong các giá trị trong giới hạn và yêu cầu
  • Hạn ngạch tài nguyên — mô tả chính sách hạn chế nói chung cho tất cả các vùng chứa trong ns và được sử dụng theo quy tắc để phân định tài nguyên giữa các môi trường (hữu ích khi các môi trường không được phân định chặt chẽ ở cấp nút)

Sau đây là ví dụ về các tệp kê khai đặt giới hạn tài nguyên:

  • Ở cấp độ vùng chứa cụ thể:

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

    Những thứ kia. trong trường hợp này, để chạy một container với nginx, bạn sẽ cần ít nhất 1G RAM trống và 0.2 CPU trên nút, trong khi tối đa container có thể tiêu thụ 0.2 CPU và tất cả RAM có sẵn trên nút.

  • Ở mức số nguyên ns:

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

    Những thứ kia. tổng của tất cả các vùng chứa yêu cầu trong ns mặc định không thể vượt quá 300m đối với CPU và 1G đối với OP và tổng của tất cả các giới hạn là 700m đối với CPU và 2G đối với OP.

  • Giới hạn mặc định cho vùng chứa trong 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

    Những thứ kia. trong không gian tên mặc định cho tất cả các vùng chứa, yêu cầu sẽ được đặt thành 100m cho CPU và 1G cho OP, giới hạn - 1 CPU và 2G. Đồng thời, giới hạn cũng được đặt cho các giá trị có thể có trong yêu cầu/giới hạn cho CPU (50m < x < 2) và RAM (500M < x < 4G).

  • Hạn chế cấp nhóm ns:

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

    Những thứ kia. đối với mỗi nhóm trong ns mặc định sẽ có giới hạn là 4 vCPU và 1G.

Bây giờ tôi muốn cho bạn biết những lợi ích mà việc đặt ra những hạn chế này có thể mang lại cho chúng ta.

Cơ chế cân bằng tải giữa các nút

Như bạn đã biết, thành phần k8s chịu trách nhiệm phân phối các nhóm giữa các nút, chẳng hạn như scheduler, hoạt động theo một thuật toán cụ thể. Thuật toán này trải qua hai giai đoạn khi chọn nút tối ưu để khởi chạy:

  1. lọc
  2. Ranging

Những thứ kia. theo chính sách được mô tả, ban đầu các nút được chọn để có thể khởi chạy nhóm dựa trên một tập hợp vị ngữ (bao gồm việc kiểm tra xem nút có đủ tài nguyên để chạy nhóm hay không - PodFitsResources), sau đó kiểm tra từng nút này, theo ưu tiên điểm được trao (bao gồm nút càng có nhiều tài nguyên miễn phí thì nút đó càng được chỉ định nhiều điểm - LeastResourceAllocation/LeastRequestedPriority/BalancedResourceAllocation) và nhóm được khởi chạy trên nút có nhiều điểm nhất (nếu một số nút thỏa mãn điều kiện này cùng một lúc thì một cái ngẫu nhiên được chọn).

Đồng thời, bạn cần hiểu rằng bộ lập lịch, khi đánh giá các tài nguyên có sẵn của một nút, được hướng dẫn bởi dữ liệu được lưu trữ trong etcd - tức là. đối với lượng tài nguyên được yêu cầu/giới hạn của mỗi nhóm chạy trên nút này, nhưng không phải đối với mức tiêu thụ tài nguyên thực tế. Thông tin này có thể được lấy từ đầu ra lệnh kubectl describe node $NODE, ví dụ:

# 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%)

Ở đây chúng ta thấy tất cả các nhóm đang chạy trên một nút cụ thể, cũng như các tài nguyên mà mỗi nhóm yêu cầu. Và đây là giao diện của nhật ký bộ lập lịch khi nhóm cronjob-cron-events-1573793820-xt6q9 được khởi chạy (thông tin này sẽ xuất hiện trong nhật ký bộ lập lịch khi bạn đặt cấp độ ghi nhật ký thứ 10 trong đối số lệnh khởi động -v=10):

đăng nhập

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

Ở đây, chúng ta thấy rằng ban đầu bộ lập lịch lọc và tạo danh sách 3 nút mà nó có thể được khởi chạy trên đó (nxs-k8s-s8, nxs-k8s-s9, nxs-k8s-s10). Sau đó, nó tính điểm dựa trên một số tham số (bao gồm BalancedResourceAllocation, LeastResourceAllocation) cho từng nút này để xác định nút phù hợp nhất. Cuối cùng, nhóm được lên lịch trên nút có số điểm cao nhất (ở đây hai nút cùng một lúc có cùng số điểm 100037, do đó, một nút ngẫu nhiên được chọn - nxs-k8s-s10).

Đầu ra: nếu một nút chạy các nhóm không có hạn chế nào được đặt, thì đối với k8 (từ quan điểm tiêu thụ tài nguyên), điều này sẽ tương đương như thể không có nhóm nào như vậy trên nút này. Do đó, nếu bạn có điều kiện, có một nhóm có quy trình háu ăn (ví dụ: wowza) và không có hạn chế nào được đặt ra cho nó, thì một tình huống có thể phát sinh khi nhóm này thực sự ăn tất cả tài nguyên của nút, nhưng đối với k8, nút này được coi là không tải và nó sẽ được thưởng cùng số điểm khi xếp hạng (chính xác là điểm đánh giá tài nguyên sẵn có) như một nút không có nhóm hoạt động, điều này cuối cùng có thể dẫn đến sự phân bổ tải không đồng đều giữa các nút.

Sự trục xuất của Pod

Như bạn đã biết, mỗi nhóm được gán một trong 3 lớp QoS:

  1. được đảm bảo — được chỉ định khi đối với mỗi vùng chứa trong nhóm, yêu cầu và giới hạn được chỉ định cho bộ nhớ và CPU, đồng thời các giá trị này phải khớp với nhau
  2. có thể nổ tung — ít nhất một vùng chứa trong nhóm có yêu cầu và giới hạn, với yêu cầu < giới hạn
  3. nỗ lực tốt nhất — khi không có vùng chứa nào trong nhóm bị giới hạn tài nguyên

Đồng thời, khi một nút bị thiếu tài nguyên (đĩa, bộ nhớ), kubelet bắt đầu xếp hạng và loại bỏ các nhóm theo một thuật toán cụ thể có tính đến mức độ ưu tiên của nhóm và lớp QoS của nó. Ví dụ: nếu chúng ta đang nói về RAM, thì dựa trên lớp QoS, điểm sẽ được tính theo nguyên tắc sau:

  • Đảm bảo: -998
  • Nỗ lực tốt nhất: 1000
  • Có thể nổ: min(max(2, 1000 - (1000 * MemoryRequestBytes) / machineMemoryCapacityBytes), 999)

Những thứ kia. với cùng mức độ ưu tiên, trước tiên, kubelet sẽ trục xuất các nhóm có lớp QoS nỗ lực tốt nhất khỏi nút.

Đầu ra: nếu bạn muốn giảm khả năng nhóm mong muốn bị đuổi khỏi nút trong trường hợp thiếu tài nguyên trên đó, thì cùng với mức độ ưu tiên, bạn cũng cần quan tâm đến việc đặt yêu cầu/giới hạn cho nó.

Cơ chế tự động điều chỉnh theo chiều ngang của nhóm ứng dụng (HPA)

Khi nhiệm vụ là tự động tăng và giảm số lượng nhóm tùy thuộc vào việc sử dụng tài nguyên (hệ thống - CPU/RAM hoặc người dùng - rps), chẳng hạn như thực thể k8s như HPA (Bộ chia tỷ lệ tự động Pod ngang). Thuật toán trong đó như sau:

  1. Số đọc hiện tại của tài nguyên được quan sát được xác định (currentMetricValue)
  2. Các giá trị mong muốn cho tài nguyên được xác định (desiredMetricValue), giá trị này đối với tài nguyên hệ thống được đặt bằng yêu cầu
  3. Số lượng bản sao hiện tại được xác định (currentReplicas)
  4. Công thức sau tính toán số lượng bản sao mong muốn (desiredReplicas)
    mong muốnBản sao = [bản sao hiện tại * (currentMetricValue / mong muốnMetricValue)]

Trong trường hợp này, việc chia tỷ lệ sẽ không xảy ra khi hệ số (currentMetricValue /expectedMetricValue) gần bằng 1 (trong trường hợp này, chúng ta có thể tự đặt sai số cho phép; theo mặc định là 0.1).

Hãy xem cách hpa hoạt động bằng cách sử dụng ví dụ về ứng dụng kiểm tra ứng dụng (được mô tả là Triển khai), trong đó cần thay đổi số lượng bản sao tùy thuộc vào mức tiêu thụ CPU:

  • Bản kê khai ứng dụng

    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

    Những thứ kia. Chúng tôi thấy rằng nhóm ứng dụng ban đầu được khởi chạy trong hai phiên bản, mỗi phiên bản chứa hai thùng chứa nginx và nginx-exporter, cho mỗi phiên bản được chỉ định yêu cầu cho CPU.

  • Tuyên ngôn 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

    Những thứ kia. Chúng tôi đã tạo một hpa sẽ giám sát quá trình kiểm tra ứng dụng Triển khai và điều chỉnh số lượng nhóm với ứng dụng dựa trên chỉ báo CPU (chúng tôi hy vọng rằng nhóm sẽ tiêu thụ 30% phần trăm CPU mà nó yêu cầu), với số lượng bản sao là trong khoảng 2-10.

    Bây giờ, hãy xem cơ chế hoạt động của hpa nếu chúng ta tác dụng tải lên một trong các lò sưởi:

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

Tổng cộng chúng tôi có những điều sau đây:

  • Giá trị mong muốn (desiredMetricValue) - theo cài đặt hpa, chúng tôi có 30%
  • Giá trị hiện tại (currentMetricValue) - để tính toán, trình quản lý bộ điều khiển tính toán giá trị trung bình của mức tiêu thụ tài nguyên theo%, tức là. có điều kiện thực hiện như sau:
    1. Nhận giá trị tuyệt đối của số liệu nhóm từ máy chủ số liệu, tức là. 101m và 4m
    2. Tính giá trị tuyệt đối trung bình, tức là (101m + 4m) / 2 = 53m
    3. Nhận giá trị tuyệt đối cho mức tiêu thụ tài nguyên mong muốn (đối với điều này, các yêu cầu của tất cả các vùng chứa được tổng hợp) 60m + 30m = 90m
    4. Tính toán phần trăm mức tiêu thụ CPU trung bình so với nhóm yêu cầu, tức là 53m / 90m * 100% = 59%

Bây giờ chúng ta đã có mọi thứ cần thiết để xác định xem có cần thay đổi số lượng bản sao hay không; để thực hiện việc này, chúng ta tính hệ số:

ratio = 59% / 30% = 1.96

Những thứ kia. số lượng bản sao phải tăng lên ~ 2 lần và lên tới [2 * 1.96] = 4.

Kết luận: Như bạn có thể thấy, để cơ chế này hoạt động, điều kiện cần thiết là sự hiện diện của các yêu cầu đối với tất cả các vùng chứa trong nhóm được quan sát.

Cơ chế tự động chia tỷ lệ theo chiều ngang của các nút (Cluster Autoscaler)

Để vô hiệu hóa tác động tiêu cực lên hệ thống trong quá trình tăng tải, việc cấu hình hpa là chưa đủ. Ví dụ: theo cài đặt trong trình quản lý bộ điều khiển hpa, nó quyết định rằng số lượng bản sao cần tăng lên gấp 2 lần, nhưng các nút không có tài nguyên trống để chạy số lượng nhóm như vậy (tức là nút không thể cung cấp tài nguyên được yêu cầu vào nhóm yêu cầu) và các nhóm này chuyển sang trạng thái Đang chờ xử lý.

Trong trường hợp này, nếu nhà cung cấp có IaaS/PaaS tương ứng (ví dụ: GKE/GCE, AKS, EKS, v.v.), một công cụ như Trình chia tỷ lệ nút tự động. Nó cho phép bạn đặt số lượng nút tối đa và tối thiểu trong cụm và tự động điều chỉnh số lượng nút hiện tại (bằng cách gọi API nhà cung cấp đám mây để đặt hàng/xóa một nút) khi thiếu tài nguyên trong cụm và nhóm không thể lên lịch (đang ở trạng thái Đang chờ xử lý).

Kết luận: Để có thể tự động điều chỉnh quy mô các nút, cần phải đặt yêu cầu trong vùng chứa nhóm để k8 có thể đánh giá chính xác tải trên các nút và theo đó báo cáo rằng không có tài nguyên trong cụm để khởi chạy nhóm tiếp theo.

Kết luận

Cần lưu ý rằng việc đặt giới hạn tài nguyên vùng chứa không phải là yêu cầu bắt buộc để ứng dụng chạy thành công nhưng vẫn tốt hơn nên làm như vậy vì những lý do sau:

  1. Để bộ lập lịch hoạt động chính xác hơn về mặt cân bằng tải giữa các nút k8s
  2. Để giảm khả năng xảy ra sự kiện “đuổi nhóm”
  3. Để tính năng tự động điều chỉnh theo chiều ngang của nhóm ứng dụng (HPA) hoạt động
  4. Để tự động điều chỉnh theo chiều ngang của các nút (Tự động điều chỉnh theo cụm) cho các nhà cung cấp đám mây

Cũng đọc các bài viết khác trên blog của chúng tôi:

Nguồn: www.habr.com

Thêm một lời nhận xét