Chín mẹo hiệu suất Kubernetes

Chín mẹo hiệu suất Kubernetes

Chào mọi người! Tên tôi là Oleg Sidorenkov, tôi làm việc tại DomClick với tư cách là trưởng nhóm cơ sở hạ tầng. Chúng tôi đã sử dụng Cube để bán trong hơn ba năm và trong thời gian này, chúng tôi đã trải qua nhiều khoảnh khắc thú vị khác nhau với nó. Hôm nay tôi sẽ cho bạn biết làm thế nào, với cách tiếp cận phù hợp, bạn có thể đạt được hiệu suất cao hơn nữa từ vanilla Kubernetes cho cụm của mình. Sẵn sàng ổn định đi!

Tất cả các bạn đều biết rất rõ rằng Kubernetes là một hệ thống nguồn mở có thể mở rộng để điều phối vùng chứa; tốt, hoặc 5 tệp nhị phân thực hiện phép thuật bằng cách quản lý vòng đời của các dịch vụ siêu nhỏ của bạn trong môi trường máy chủ. Ngoài ra, đây là một công cụ khá linh hoạt, có thể lắp ráp giống như một công cụ xây dựng Lego để tùy biến tối đa cho các tác vụ khác nhau.

Và mọi thứ dường như vẫn ổn: ném máy chủ vào cụm, như củi vào hộp lửa và không biết đau buồn. Nhưng nếu bạn vì môi trường, thì bạn sẽ nghĩ: “Làm sao giữ lửa trong bếp mà tiếc rừng?”. Nói cách khác, làm thế nào để tìm cách cải thiện cơ sở hạ tầng và giảm chi phí.

1. Theo dõi tài nguyên nhóm và ứng dụng

Chín mẹo hiệu suất Kubernetes

Một trong những phương pháp tầm thường nhưng hiệu quả nhất là đưa ra các yêu cầu/giới hạn. Tách các ứng dụng theo không gian tên và không gian tên theo nhóm phát triển. Đặt ứng dụng trước khi triển khai các giá trị cho mức tiêu thụ thời gian của bộ xử lý, bộ nhớ, lưu trữ tạm thời.

resources:
   requests:
     memory: 2Gi
     cpu: 250m
   limits:
     memory: 4Gi
     cpu: 500m

Bằng kinh nghiệm, chúng tôi đã đi đến kết luận: không đáng để tăng các yêu cầu từ giới hạn hơn hai lần. Khối lượng của cụm được tính toán dựa trên các yêu cầu và nếu bạn đặt chênh lệch về tài nguyên cho các ứng dụng, chẳng hạn như 5-10 lần, thì hãy tưởng tượng điều gì sẽ xảy ra với nút của bạn khi nó được lấp đầy bởi các nhóm và đột nhiên nhận được tải . Chẳng có gì tốt đẹp cả. Ở mức tối thiểu, điều tiết và tối đa, nói lời tạm biệt với công nhân và nhận tải theo chu kỳ trên các nút còn lại sau khi các nhóm bắt đầu di chuyển.

Ngoài ra, với sự giúp đỡ limitranges bạn có thể đặt giá trị tài nguyên cho vùng chứa khi bắt đầu - tối thiểu, tối đa và mặc định:

➜  ~ kubectl describe limitranges --namespace ops
Name:       limit-range
Namespace:  ops
Type        Resource           Min   Max   Default Request  Default Limit  Max Limit/Request Ratio
----        --------           ---   ---   ---------------  -------------  -----------------------
Container   cpu                50m   10    100m             100m           2
Container   ephemeral-storage  12Mi  8Gi   128Mi            4Gi            -
Container   memory             64Mi  40Gi  128Mi            128Mi          2

Hãy nhớ giới hạn tài nguyên không gian tên để một lệnh không thể lấy hết tài nguyên của cụm:

➜  ~ kubectl describe resourcequotas --namespace ops
Name:                   resource-quota
Namespace:              ops
Resource                Used          Hard
--------                ----          ----
limits.cpu              77250m        80
limits.memory           124814367488  150Gi
pods                    31            45
requests.cpu            53850m        80
requests.memory         75613234944   150Gi
services                26            50
services.loadbalancers  0             0
services.nodeports      0             0

Như bạn có thể thấy từ mô tả resourcequotas, nếu lệnh ops muốn triển khai các nhóm sẽ tiêu tốn thêm 10 cpu, thì bộ lập lịch sẽ không cho phép thực hiện và sẽ báo lỗi:

Error creating: pods "nginx-proxy-9967d8d78-nh4fs" is forbidden: exceeded quota: resource-quota, requested: limits.cpu=5,requests.cpu=5, used: limits.cpu=77250m,requests.cpu=53850m, limited: limits.cpu=10,requests.cpu=10

Để giải quyết vấn đề tương tự, bạn có thể viết một công cụ, chẳng hạn như này, có thể lưu trữ và chuyển giao trạng thái của tài nguyên lệnh.

2. Chọn nơi lưu trữ tệp tốt nhất

Chín mẹo hiệu suất Kubernetes

Ở đây tôi muốn đề cập đến chủ đề về khối lượng liên tục và hệ thống con đĩa của các nút công nhân Kubernetes. Tôi hy vọng rằng không ai sử dụng "Cube" trên ổ cứng HDD trong quá trình sản xuất, nhưng đôi khi ngay cả một ổ SSD thông thường cũng không đủ. Chúng tôi đã gặp phải một vấn đề là các bản ghi đã giết chết đĩa bằng các thao tác I / O và không có nhiều giải pháp ở đây:

  • Sử dụng SSD hiệu suất cao hoặc chuyển sang NVMe (nếu bạn quản lý phần cứng của riêng mình).

  • Giảm mức độ đăng nhập.

  • Thực hiện cân bằng "thông minh" các nhóm ăn cắp đĩa (podAntiAffinity).

Ảnh chụp màn hình ở trên cho thấy những gì xảy ra trong nginx-ingress-controller với một đĩa khi access_logs được bật (~12k bản ghi/giây). Tất nhiên, trạng thái như vậy có thể dẫn đến sự xuống cấp của tất cả các ứng dụng trên nút này.

Đối với PV, than ôi, tôi đã không thử tất cả mọi thứ. các loại Khối lượng liên tục. Sử dụng tùy chọn tốt nhất phù hợp với bạn. Trong lịch sử, ở nước ta, một phần nhỏ các dịch vụ cần khối lượng RWX và từ lâu họ đã bắt đầu sử dụng bộ lưu trữ NFS cho nhiệm vụ này. Rẻ và... đủ dùng. Tất nhiên, chúng tôi đã ăn cứt với anh ấy - hãy khỏe mạnh, nhưng chúng tôi đã học được cách điều chỉnh anh ấy, và đầu anh ấy không còn đau nữa. Và nếu có thể, hãy chuyển sang lưu trữ đối tượng S3.

3. Xây dựng hình ảnh được tối ưu hóa

Chín mẹo hiệu suất Kubernetes

Tốt nhất là sử dụng hình ảnh được tối ưu hóa vùng chứa để Kubernetes có thể tìm nạp chúng nhanh hơn và thực thi chúng hiệu quả hơn. 

Tối ưu hóa có nghĩa là hình ảnh:

  • chỉ chứa một ứng dụng hoặc chỉ thực hiện một chức năng;

  • kích thước nhỏ, vì hình ảnh lớn được truyền qua mạng kém hơn;

  • có các điểm cuối về sức khỏe và sự sẵn sàng mà Kubernetes có thể sử dụng để thực hiện hành động trong trường hợp ngừng hoạt động;

  • sử dụng các hệ điều hành thân thiện với vùng chứa (như Alpine hoặc CoreOS) có khả năng chống lỗi cấu hình cao hơn;

  • sử dụng các bản dựng nhiều giai đoạn để bạn chỉ có thể triển khai các ứng dụng đã biên dịch chứ không phải các nguồn đi kèm.

Có nhiều công cụ và dịch vụ cho phép bạn kiểm tra và tối ưu hóa hình ảnh một cách nhanh chóng. Điều quan trọng là luôn giữ cho chúng được cập nhật và an toàn. Kết quả là, bạn nhận được:

  1. Giảm tải mạng trên toàn bộ cụm.

  2. Giảm thời gian khởi động container.

  3. Kích thước nhỏ hơn của toàn bộ sổ đăng ký Docker của bạn.

4. Sử dụng bộ đệm DNS

Chín mẹo hiệu suất Kubernetes

Nếu chúng ta nói về tải trọng cao, thì nếu không điều chỉnh hệ thống DNS của cụm, cuộc sống sẽ khá tệ hại. Ngày xửa ngày xưa, các nhà phát triển Kubernetes đã hỗ trợ giải pháp kube-dns của họ. Nó cũng đã được triển khai ở nước ta, nhưng phần mềm này không được điều chỉnh đặc biệt và không mang lại hiệu suất cần thiết, mặc dù có vẻ như nhiệm vụ này rất đơn giản. Sau đó, coredns xuất hiện, chúng tôi đã chuyển sang và không biết đau buồn, sau này nó trở thành dịch vụ DNS mặc định trong K8s. Tại một số thời điểm, chúng tôi đã tăng tới 40 nghìn rps cho hệ thống DNS và giải pháp này cũng không đủ. Nhưng, thật tình cờ, Nodelocaldns đã xuất hiện, hay còn gọi là node local cache, hay còn gọi là Bộ đệm DNS cục bộ của nút.

Tại sao chúng ta sử dụng nó? Có một lỗi trong nhân Linux, khi nhiều lần truy cập thông qua conntrack NAT qua UDP, dẫn đến tình trạng chạy đua để ghi vào các bảng conntrack và một phần lưu lượng thông qua NAT bị mất (mỗi chuyến đi qua Dịch vụ là NAT). Nodelocaldns giải quyết vấn đề này bằng cách loại bỏ NAT và nâng cấp lên kết nối TCP thành DNS ngược dòng, cũng như lưu cục bộ các truy vấn DNS ngược dòng vào bộ đệm (bao gồm cả bộ nhớ cache âm 5 giây ngắn).

5. Tự động chia tỷ lệ các nhóm theo chiều ngang và chiều dọc

Chín mẹo hiệu suất Kubernetes

Bạn có thể tự tin nói rằng tất cả các vi dịch vụ của bạn đã sẵn sàng để tải tăng gấp hai đến ba lần không? Làm cách nào để phân bổ tài nguyên hợp lý cho các ứng dụng của bạn? Việc duy trì một vài nhóm chạy vượt quá khối lượng công việc có thể là dư thừa và việc duy trì chúng liên tục có nguy cơ gây ra thời gian ngừng hoạt động do lưu lượng truy cập vào dịch vụ tăng đột ngột. Ý nghĩa vàng giúp đạt được phép nhân như các dịch vụ như Autoscaler Pod ngang и Bộ định vị tự động theo chiều dọc.

VPA cho phép bạn tự động tăng yêu cầu/giới hạn của vùng chứa trong nhóm dựa trên mức sử dụng thực tế. Làm thế nào nó có thể hữu ích? Nếu bạn có các Nhóm vì lý do nào đó không thể thu nhỏ theo chiều ngang (điều này không hoàn toàn đáng tin cậy), thì bạn có thể thử tin tưởng vào VPA để thay đổi tài nguyên của nó. Tính năng của nó là một hệ thống đề xuất dựa trên dữ liệu lịch sử và hiện tại từ máy chủ số liệu, vì vậy nếu bạn không muốn tự động thay đổi yêu cầu/giới hạn, bạn chỉ cần theo dõi các tài nguyên được đề xuất cho vùng chứa của mình và tối ưu hóa cài đặt để tiết kiệm CPU và bộ nhớ trong cụm.

Chín mẹo hiệu suất KubernetesHình ảnh được lấy từ https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Bộ lập lịch trong Kubernetes luôn dựa trên các yêu cầu. Bất kể giá trị nào bạn đặt ở đó, bộ lập lịch sẽ tìm một nút phù hợp dựa trên giá trị đó. Giá trị giới hạn là cần thiết cho kublet để biết khi nào nên tăng tốc hoặc tắt một nhóm. Và vì tham số quan trọng duy nhất là giá trị yêu cầu, VPA sẽ làm việc với nó. Bất cứ khi nào bạn mở rộng quy mô ứng dụng của mình theo chiều dọc, bạn sẽ xác định những yêu cầu sẽ là gì. Và điều gì sẽ xảy ra với các giới hạn sau đó? Tham số này cũng sẽ được chia tỷ lệ theo tỷ lệ.

Ví dụ: đây là các cài đặt nhóm điển hình:

resources:
   requests:
     memory: 250Mi
     cpu: 200m
   limits:
     memory: 500Mi
     cpu: 350m

Công cụ đề xuất xác định rằng ứng dụng của bạn cần 300m CPU và 500Mi để chạy đúng cách. Bạn sẽ nhận được các cài đặt này:

resources:
   requests:
     memory: 500Mi
     cpu: 300m
   limits:
     memory: 1000Mi
     cpu: 525m

Như đã đề cập ở trên, đây là tỷ lệ chia tỷ lệ dựa trên tỷ lệ yêu cầu/giới hạn trong tệp kê khai:

  • CPU: 200m → 300m: tỷ lệ 1:1.75;

  • Bộ nhớ: 250Mi → 500Mi: Tỷ lệ 1:2.

đối với HPA, thì cơ chế hoạt động minh bạch hơn. Ngưỡng được đặt cho các chỉ số như bộ xử lý và bộ nhớ và nếu mức trung bình của tất cả các bản sao vượt quá ngưỡng, thì ứng dụng sẽ chia tỷ lệ theo nhóm +1 cho đến khi giá trị giảm xuống dưới ngưỡng hoặc cho đến khi đạt đến số lượng bản sao tối đa.

Chín mẹo hiệu suất KubernetesHình ảnh được lấy từ https://levelup.gitconnected.com/kubernetes-autoscaling-101-cluster-autoscaler-horizontal-pod-autoscaler-and-vertical-pod-2a441d9ad231

Ngoài các chỉ số thông thường như CPU ​​và Bộ nhớ, bạn có thể đặt ngưỡng cho chỉ số Prometheus tùy chỉnh của mình và làm việc với chúng nếu bạn cảm thấy đây là cách chính xác nhất để xác định thời điểm mở rộng quy mô ứng dụng của mình. Sau khi ứng dụng ổn định dưới ngưỡng chỉ số đã chỉ định, HPA sẽ bắt đầu giảm quy mô nhóm xuống số lượng bản sao tối thiểu hoặc cho đến khi tải đáp ứng ngưỡng đã chỉ định.

6. Đừng quên Node Affinity và Pod Affinity

Chín mẹo hiệu suất Kubernetes

Không phải tất cả các nút đều chạy trên cùng một phần cứng và không phải tất cả các nhóm đều cần chạy các ứng dụng chuyên sâu về điện toán. Kubernetes cho phép bạn chỉ định chuyên môn hóa của các nút và nhóm bằng cách sử dụng Mối quan hệ nút и Mối quan hệ nhóm.

Nếu bạn có các nút phù hợp cho các hoạt động sử dụng nhiều điện toán, thì để đạt hiệu quả tối đa, tốt hơn là liên kết các ứng dụng với các nút thích hợp. Để làm điều này, sử dụng nodeSelector với nhãn nút.

Giả sử bạn có hai nút: một nút có CPUType=HIGHFREQ và một số lượng lớn các lõi nhanh, một lõi khác với MemoryType=HIGHMEMORY bộ nhớ nhiều hơn và hiệu suất nhanh hơn. Cách dễ nhất là chỉ định triển khai nhóm cho một nút HIGHFREQbằng cách thêm vào phần spec một bộ chọn như thế này:

…
nodeSelector:
	CPUType: HIGHFREQ

Một cách tốn kém và cụ thể hơn để làm điều này là sử dụng nodeAffinity trong lĩnh vực affinity razdela spec. Có hai lựa chọn:

  • requiredDuringSchedulingIgnoredDuringExecution: cài đặt cứng (trình lập lịch biểu sẽ chỉ triển khai các nhóm trên các nút cụ thể (và không nơi nào khác));

  • preferredDuringSchedulingIgnoredDuringExecution: cài đặt mềm (bộ lập lịch sẽ cố triển khai tới các nút cụ thể và nếu không thành công, nó sẽ cố triển khai tới nút khả dụng tiếp theo).

Bạn có thể chỉ định một cú pháp cụ thể để quản lý nhãn nút, ví dụ: In, NotIn, Exists, DoesNotExist, Gt hoặc Lt. Tuy nhiên, hãy nhớ rằng các phương pháp phức tạp trong danh sách nhãn dài sẽ làm chậm quá trình ra quyết định trong các tình huống quan trọng. Nói cách khác, đừng quá phức tạp.

Như đã đề cập ở trên, Kubernetes cho phép bạn thiết lập ràng buộc của các nhóm hiện tại. Nghĩa là, bạn có thể làm cho một số nhóm nhất định hoạt động cùng với các nhóm khác trong cùng vùng khả dụng (có liên quan đến đám mây) hoặc nút.

В podAffinity cánh đồng affinity razdela spec các trường tương tự có sẵn như trong trường hợp của nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution и preferredDuringSchedulingIgnoredDuringExecution. Sự khác biệt duy nhất là matchExpressions sẽ liên kết các nhóm với một nút đang chạy một nhóm có nhãn đó.

Kubernetes khác cung cấp một trường podAntiAffinity, ngược lại, không liên kết một nhóm với một nút có các nhóm cụ thể.

Về biểu thức nodeAffinity Có thể đưa ra lời khuyên tương tự: cố gắng giữ cho các quy tắc đơn giản và hợp lý, đừng cố làm quá tải đặc tả nhóm bằng một bộ quy tắc phức tạp. Rất dễ tạo quy tắc không phù hợp với các điều kiện của cụm, gây thêm tải cho bộ lập lịch và làm giảm hiệu suất tổng thể.

7. Vết nhơ & Dung sai

Có một cách khác để quản lý lịch trình. Nếu bạn có một cụm lớn với hàng trăm nút và hàng nghìn vi dịch vụ, thì rất khó để ngăn một số nhóm nhất định được lưu trữ bởi một số nút nhất định.

Cơ chế của các vết bẩn - các quy tắc cấm - giúp ích cho việc này. Ví dụ: bạn có thể ngăn các nút nhất định chạy nhóm trong các tình huống nhất định. Để áp dụng dấu vết cho một nút cụ thể, hãy sử dụng tùy chọn taint trong kubectl. Chỉ định khóa và giá trị rồi làm hỏng như NoSchedule hoặc NoExecute:

$ kubectl taint nodes node10 node-role.kubernetes.io/ingress=true:NoSchedule

Cũng cần lưu ý rằng cơ chế taint hỗ trợ ba hiệu ứng chính: NoSchedule, NoExecute и PreferNoSchedule.

  • NoSchedule có nghĩa là cho đến khi có một mục tương ứng trong đặc tả nhóm tolerations, nó không thể được triển khai tới nút (trong ví dụ này node10).

  • PreferNoSchedule - phiên bản đơn giản hóa NoSchedule. Trong trường hợp này, bộ lập lịch trình sẽ cố gắng không phân bổ các nhóm không có mục nhập phù hợp. tolerations mỗi nút, nhưng đây không phải là giới hạn cứng. Nếu không có tài nguyên nào trong cụm, thì các nhóm sẽ bắt đầu triển khai trên nút này.

  • NoExecute - hiệu ứng này kích hoạt sơ tán ngay lập tức các nhóm không có mục phù hợp tolerations.

Thật kỳ lạ, hành vi này có thể được hoàn tác bằng cơ chế dung sai. Điều này thuận tiện khi có một nút "bị cấm" và bạn chỉ cần đặt các dịch vụ cơ sở hạ tầng trên đó. Làm thế nào để làm nó? Chỉ cho phép những nhóm có dung sai phù hợp.

Đây là thông số kỹ thuật của nhóm sẽ như thế nào:

spec:
   tolerations:
     - key: "node-role.kubernetes.io/ingress"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"

Điều này không có nghĩa là trong lần triển khai lại tiếp theo, nhóm sẽ tấn công chính xác nút này, đây không phải là cơ chế Mối quan hệ của Nút và nodeSelector. Nhưng bằng cách kết hợp một số tính năng, bạn có thể đạt được thiết lập lịch trình rất linh hoạt.

8. Đặt mức độ ưu tiên triển khai Pod

Chỉ vì bạn đã định cấu hình các liên kết nhóm với nút không có nghĩa là tất cả các nhóm phải được xử lý với cùng mức độ ưu tiên. Ví dụ: bạn có thể muốn triển khai một số Nhóm trước các Nhóm khác.

Kubernetes cung cấp các cách khác nhau để đặt Ưu tiên và Ưu tiên Pod. Cài đặt bao gồm một số phần: đối tượng PriorityClass và mô tả trường priorityClassName trong đặc tả nhóm. Hãy xem xét một ví dụ:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 99999
globalDefault: false
description: "This priority class should be used for very important pods only"

Chúng tôi tạo ra PriorityClass, đặt tên, mô tả và giá trị cho nó. Cao hơn value, mức độ ưu tiên càng cao. Giá trị có thể là bất kỳ số nguyên 32 bit nào nhỏ hơn hoặc bằng 1. Các giá trị cao hơn được dành riêng cho các nhóm hệ thống quan trọng, thường không thể được ưu tiên. Việc trục xuất sẽ chỉ xảy ra nếu nhóm có mức độ ưu tiên cao không có nơi nào để quay lại, khi đó một số nhóm từ một nút cụ thể sẽ bị trục xuất. Nếu cơ chế này quá cứng nhắc đối với bạn, thì bạn có thể thêm tùy chọn preemptionPolicy: Never, và sau đó sẽ không có quyền ưu tiên, nhóm sẽ là nhóm đầu tiên trong hàng đợi và đợi bộ lập lịch trình tìm tài nguyên miễn phí cho nhóm đó.

Tiếp theo, chúng tôi tạo một nhóm, trong đó chúng tôi chỉ định tên priorityClassName:

apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    role: myrole
 spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
          protocol: TCP
  priorityClassName: high-priority
          

Bạn có thể tạo bao nhiêu lớp ưu tiên tùy thích, mặc dù bạn không nên quá chú trọng đến điều này (giả sử, hãy giới hạn bản thân ở mức ưu tiên thấp, trung bình và cao).

Do đó, nếu cần, bạn có thể tăng hiệu quả của việc triển khai các dịch vụ quan trọng, chẳng hạn như nginx-ingress-controller, coredns, v.v.

9. Tối ưu hóa cụm ETCD của bạn

Chín mẹo hiệu suất Kubernetes

ETCD có thể được gọi là bộ não của cả cụm. Điều rất quan trọng là duy trì hoạt động của cơ sở dữ liệu này ở mức cao, vì tốc độ hoạt động trong "Cube" phụ thuộc vào nó. Một giải pháp khá chuẩn và đồng thời, một giải pháp tốt sẽ là giữ một cụm ETCD trên các nút chính để có độ trễ tối thiểu đối với kube-apiserver. Nếu điều này là không thể, hãy đặt ETCD càng gần càng tốt, với băng thông tốt giữa những người tham gia. Ngoài ra, hãy chú ý đến việc có bao nhiêu nút từ ETCD có thể thoát ra mà không gây hại cho cụm.

Chín mẹo hiệu suất Kubernetes

Hãy nhớ rằng sự gia tăng quá mức số lượng người tham gia trong cụm có thể làm tăng khả năng chịu lỗi với chi phí là hiệu suất, mọi thứ nên ở mức độ vừa phải.

Nếu chúng ta nói về việc thiết lập dịch vụ, thì có một số khuyến nghị:

  1. Có phần cứng tốt, dựa trên kích thước của cụm (bạn có thể đọc đây).

  2. Tinh chỉnh một vài tham số nếu bạn đã trải rộng một cụm giữa một cặp DC hoặc mạng và đĩa của bạn còn nhiều điều mong muốn (bạn có thể đọc đây).

Kết luận

Bài viết này mô tả những điểm mà nhóm của chúng tôi cố gắng tuân thủ. Đây không phải là mô tả từng bước về các hành động, mà là các tùy chọn có thể hữu ích để tối ưu hóa chi phí hoạt động của một cụm. Rõ ràng là mỗi cụm là duy nhất theo cách riêng của nó và các giải pháp điều chỉnh có thể khác nhau rất nhiều, vì vậy sẽ rất thú vị nếu nhận được phản hồi từ bạn: cách bạn theo dõi cụm Kubernetes của mình, cách cải thiện hiệu suất của cụm. Chia sẻ kinh nghiệm của bạn trong phần bình luận, sẽ rất thú vị khi biết điều đó.

Nguồn: www.habr.com