Cách truy cập tài nguyên Kubernetes Pod

Cách truy cập tài nguyên Kubernetes PodPhần thưởng của Tohad

Khi bắt đầu với Kubernetes, bạn thường quên thiết lập tài nguyên vùng chứa. Tại thời điểm này, chỉ cần đảm bảo rằng Docker image hoạt động và có thể được triển khai vào cụm Kubernetes là đủ.

Nhưng sau này ứng dụng cần được triển khai trong cụm sản xuất cùng với các ứng dụng khác. Để thực hiện việc này, bạn cần phân bổ tài nguyên cho vùng chứa và đảm bảo rằng có đủ tài nguyên để thiết lập và chạy ứng dụng, đồng thời các ứng dụng đang chạy khác sẽ không gặp sự cố.

Đội Kubernetes aaS từ Mail.ru đã dịch một bài viết về tài nguyên vùng chứa (CPU & MEM), các yêu cầu và giới hạn tài nguyên. Bạn sẽ tìm hiểu lợi ích của những cài đặt này và điều gì sẽ xảy ra nếu bạn không đặt chúng.

Tài nguyên máy tính

Chúng tôi có hai loại tài nguyên với các đơn vị sau:

  • Bộ xử lý trung tâm (CPU) - lõi;
  • Bộ nhớ (MEM) - byte.

Tài nguyên được chỉ định cho mỗi vùng chứa. Trong tệp Pod YAML sau đây, bạn sẽ thấy phần tài nguyên chứa các tài nguyên được yêu cầu và giới hạn:

  • Tài nguyên Pod được yêu cầu = tổng tài nguyên được yêu cầu của tất cả các vùng chứa;
  • Giới hạn tài nguyên nhóm = Tổng tất cả các giới hạn tài nguyên nhóm.

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

Ví dụ về nguồn lực được yêu cầu và có giới hạn

Lĩnh vực resources.requested từ đặc tả Pod là một trong những phần tử được sử dụng để tìm nút mong muốn. Bạn đã có thể lập kế hoạch triển khai Pod cho nó. Làm thế nào để bạn tìm thấy một nút phù hợp?

Kubernetes bao gồm một số thành phần, bao gồm nút chính hoặc nút chính (Mặt phẳng điều khiển Kubernetes). Nút chính có một số quy trình: kube-apiserver, kube-controller-manager và kube-scheduler.

Quy trình lập lịch kube chịu trách nhiệm xem xét các nhóm mới được tạo và tìm các nút công nhân phù hợp với tất cả các yêu cầu của nhóm, bao gồm cả số lượng tài nguyên được yêu cầu. Danh sách các nút được tìm thấy bởi kube-scheduler được xếp hạng. Nhóm được lên lịch trên nút có điểm số cao nhất.

Cách truy cập tài nguyên Kubernetes PodPod màu tím sẽ được đặt ở đâu?

Trong hình, bạn có thể thấy kube-scheduler sẽ lên lịch cho một Pod màu tím mới. Cụm Kubernetes chứa hai nút: A và B. Như bạn có thể thấy, kube-scheduler không thể lên lịch một Pod trên nút A - các tài nguyên có sẵn (không được yêu cầu) không khớp với yêu cầu của Pod màu tím. Vì vậy, 1 GB bộ nhớ mà Pod màu tím yêu cầu sẽ không vừa với nút A, vì bộ nhớ khả dụng là 0,5 GB. Nhưng nút B có đủ tài nguyên. Kết quả là kube-scheduler quyết định đích đến của Pod màu tím là nút B.

Bây giờ chúng ta đã biết các tài nguyên được yêu cầu ảnh hưởng như thế nào đến việc lựa chọn nút để chạy Pod. Nhưng tác động của nguồn lực cận biên là gì?

Giới hạn tài nguyên là ranh giới mà CPU/MEM không thể vượt qua. Tuy nhiên, tài nguyên CPU rất linh hoạt nên các container đạt đến giới hạn CPU sẽ không khiến Pod thoát ra. Thay vào đó, quá trình điều chỉnh CPU sẽ bắt đầu. Nếu đạt đến giới hạn sử dụng MEM, vùng chứa sẽ bị dừng do OOM-Killer và được khởi động lại nếu cài đặt Chính sách khởi động lại cho phép.

Chi tiết về tài nguyên được yêu cầu và tối đa

Cách truy cập tài nguyên Kubernetes PodGiao tiếp tài nguyên giữa Docker và Kubernetes

Cách tốt nhất để giải thích cách hoạt động của yêu cầu tài nguyên và giới hạn tài nguyên là giới thiệu mối quan hệ giữa Kubernetes và Docker. Trong hình trên, bạn có thể thấy các trường Kubernetes và cờ khởi động Docker có liên quan như thế nào.

Bộ nhớ: yêu cầu và giới hạn

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

Như đã đề cập ở trên, bộ nhớ được đo bằng byte. Dựa trên Tài liệu Kubernetes, chúng ta có thể chỉ định bộ nhớ dưới dạng số. Thông thường nó là một số nguyên, ví dụ 2678 - nghĩa là 2678 byte. Bạn cũng có thể sử dụng hậu tố G и Gi, điều chính là phải nhớ rằng chúng không tương đương. Đầu tiên là số thập phân và thứ hai là nhị phân. Giống như ví dụ được đề cập trong tài liệu k8s: 128974848, 129e6, 129M, 123Mi - thực tế chúng tương đương nhau.

Tùy chọn Kubernetes limits.memory phù hợp với lá cờ --memory từ Docker. Trong trường hợp request.memory Không có mũi tên cho Docker vì Docker không sử dụng trường này. Bạn có thể hỏi, điều này có cần thiết không? Có cần. Như tôi đã nói trước đây, lĩnh vực này rất quan trọng đối với Kubernetes. Dựa trên thông tin từ đó, kube-scheduler quyết định nút nào sẽ lên lịch cho Pod.

Điều gì xảy ra nếu bạn đặt không đủ bộ nhớ cho một yêu cầu?

Nếu vùng chứa đã đạt đến giới hạn của bộ nhớ được yêu cầu thì Pod sẽ được đặt vào một nhóm Pod sẽ dừng khi không có đủ bộ nhớ trong nút.

Điều gì xảy ra nếu bạn đặt giới hạn bộ nhớ quá thấp?

Nếu vùng chứa vượt quá giới hạn bộ nhớ, nó sẽ bị chấm dứt do OOM-Killed. Và sẽ khởi động lại nếu có thể dựa trên Chính sách khởi động lại trong đó giá trị mặc định là Always.

Điều gì xảy ra nếu bạn không chỉ định bộ nhớ được yêu cầu?

Kubernetes sẽ lấy giá trị giới hạn và đặt nó làm giá trị mặc định.

Điều gì có thể xảy ra nếu bạn không chỉ định giới hạn bộ nhớ?

Vùng chứa không có hạn chế; nó có thể sử dụng bao nhiêu bộ nhớ tùy thích. Nếu anh ta bắt đầu sử dụng tất cả bộ nhớ có sẵn của nút thì OOM sẽ giết anh ta. Vùng chứa sau đó sẽ được khởi động lại nếu có thể dựa trên Chính sách khởi động lại.

Điều gì xảy ra nếu bạn không chỉ định giới hạn bộ nhớ?

Đây là trường hợp xấu nhất: bộ lập lịch không biết vùng chứa yêu cầu bao nhiêu tài nguyên và điều này có thể gây ra sự cố nghiêm trọng trên nút. Trong trường hợp này, sẽ rất tốt nếu có các giới hạn mặc định trên không gian tên (do LimitRange đặt). Không có giới hạn mặc định - Pod không có giới hạn, nó có thể sử dụng bao nhiêu bộ nhớ tùy thích.

Nếu bộ nhớ được yêu cầu nhiều hơn mức mà nút có thể cung cấp thì Pod sẽ không được lên lịch. Điều quan trọng cần nhớ là Requests.memory - không phải là giá trị tối thiểu. Đây là mô tả về dung lượng bộ nhớ đủ để giữ cho vùng chứa chạy liên tục.

Thông thường nên đặt cùng một giá trị cho request.memory и limit.memory. Điều này đảm bảo rằng Kubernetes sẽ không lên lịch Pod trên nút có đủ bộ nhớ để chạy Pod nhưng không đủ để chạy nó. Hãy ghi nhớ: Việc lập kế hoạch Kubernetes Pod chỉ tính đến requests.memorylimits.memory không tính đến.

CPU: yêu cầu và giới hạn

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

Với CPU, mọi thứ phức tạp hơn một chút. Quay lại bức tranh về mối quan hệ giữa Kubernetes và Docker, bạn có thể thấy rằng request.cpu phù hợp với --cpu-shares, trong khi limit.cpu phù hợp với lá cờ cpus trong Docker.

CPU mà Kubernetes yêu cầu được nhân với 1024, tỷ lệ với chu kỳ CPU. Muốn request 1 full core thì phải thêm cpu: 1như được trình bày ở trên.

Yêu cầu kernel đầy đủ (tỷ lệ = 1024) không có nghĩa là vùng chứa của bạn sẽ nhận được nó. Nếu máy chủ của bạn chỉ có một lõi và bạn đang chạy nhiều hơn một bộ chứa thì tất cả các bộ chứa phải chia sẻ CPU có sẵn giữa chúng. Làm thế nào điều này xảy ra? Chúng ta hãy nhìn vào bức tranh.

Cách truy cập tài nguyên Kubernetes Pod
Yêu cầu CPU - Hệ thống lõi đơn

Hãy tưởng tượng rằng bạn có một hệ thống máy chủ lõi đơn đang chạy các container. Mẹ (Kubernetes) nướng một chiếc bánh (CPU) và muốn chia nó cho các con (hộp đựng). Ba em muốn một cái bánh nguyên (tỷ lệ = 1024), một em khác muốn một nửa cái bánh (512). Mẹ muốn công bằng và làm một phép tính đơn giản.

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

Theo tính toán, ba đứa trẻ sẽ nhận được 28% lõi chứ không phải toàn bộ lõi. Con thứ 14 sẽ được hưởng XNUMX% hạt nguyên chứ không phải một nửa. Nhưng mọi thứ sẽ khác nếu bạn có một hệ thống đa lõi.

Cách truy cập tài nguyên Kubernetes Pod
Yêu cầu CPU - Hệ thống đa lõi (4)

Trong hình trên, bạn có thể thấy ba đứa trẻ muốn một chiếc bánh nguyên và một đứa muốn một nửa. Vì mẹ đã nướng bốn chiếc bánh nên mỗi đứa con của mẹ sẽ nhận được bao nhiêu tùy thích. Trong hệ thống đa lõi, tài nguyên bộ xử lý được phân phối trên tất cả các lõi bộ xử lý có sẵn. Nếu một thùng chứa bị giới hạn ở ít hơn một lõi CPU đầy đủ, nó vẫn có thể sử dụng nó ở mức 100%.

Các phép tính trên được đơn giản hóa để hiểu cách CPU được phân bổ giữa các container. Tất nhiên, bên cạnh các thùng chứa, còn có các quy trình khác cũng sử dụng tài nguyên CPU. Khi các tiến trình trong một vùng chứa không hoạt động, các tiến trình khác có thể sử dụng tài nguyên của nó. CPU: "200m" phù hợp với CPU: 0,2, có nghĩa là khoảng 20% ​​của một lõi.

Bây giờ chúng ta hãy nói về limit.cpu. CPU mà Kubernetes giới hạn được nhân với 100. Kết quả là lượng thời gian mà container có thể sử dụng sau mỗi 100 µs (cpu-period).

limit.cpu khớp với cờ Docker --cpus. Đây là sự kết hợp mới của cái cũ --cpu-period и --cpu-quota. Bằng cách đặt nó, chúng tôi cho biết số lượng tài nguyên CPU có sẵn mà vùng chứa có thể sử dụng tối đa trước khi bắt đầu điều chỉnh:

  • cổ phiếu - sự kết hợp cpu-period и cpu-quota. cpus = 1.5 tương đương với việc thiết lập cpu-period = 100000 и cpu-quota = 150000;
  • thời kỳ CPU - Giai đoạn Bộ lập lịch CFS CPU, mặc định là 100 micro giây;
  • hạn ngạch cpu - số micro giây bên trong cpu-period, được giới hạn bởi container.

Điều gì xảy ra nếu bạn cài đặt không đủ CPU yêu cầu?

Nếu container cần nhiều hơn mức nó đã cài đặt, nó sẽ lấy cắp CPU từ các tiến trình khác.

Điều gì xảy ra nếu bạn đặt giới hạn CPU quá thấp?

Vì tài nguyên CPU có thể điều chỉnh được nên tính năng điều tiết sẽ được bật.

Điều gì xảy ra nếu bạn không chỉ định yêu cầu CPU?

Giống như bộ nhớ, giá trị yêu cầu bằng với giới hạn.

Điều gì xảy ra nếu bạn không chỉ định giới hạn CPU?

Vùng chứa sẽ sử dụng nhiều CPU như nó cần. Nếu chính sách CPU mặc định (LimitRange) được xác định trong không gian tên thì giới hạn này cũng được sử dụng cho vùng chứa.

Điều gì xảy ra nếu bạn không chỉ định yêu cầu hoặc giới hạn CPU?

Giống như bộ nhớ, đây là trường hợp xấu nhất. Bộ lập lịch không biết vùng chứa của bạn cần bao nhiêu tài nguyên và điều này có thể gây ra sự cố nghiêm trọng trên nút. Để tránh điều này, bạn cần đặt giới hạn mặc định cho các không gian tên (LimitRange).

Hãy nhớ: nếu bạn yêu cầu nhiều CPU hơn mức các nút có thể cung cấp, Pod sẽ không được lên lịch. Requests.cpu - không phải là giá trị tối thiểu mà là giá trị đủ để khởi động Pod và hoạt động mà không gặp lỗi. Nếu ứng dụng không thực hiện được các phép tính phức tạp thì lựa chọn tốt nhất là cài đặt request.cpu <= 1 và khởi chạy bao nhiêu bản sao nếu cần.

Lượng tài nguyên được yêu cầu hoặc giới hạn tài nguyên lý tưởng

Chúng tôi đã tìm hiểu về giới hạn của tài nguyên máy tính. Bây giờ là lúc trả lời câu hỏi: “Pod của tôi cần bao nhiêu tài nguyên để chạy ứng dụng mà không gặp vấn đề gì? Số tiền lý tưởng là bao nhiêu?

Thật không may, không có câu trả lời rõ ràng cho những câu hỏi này. Nếu bạn không biết ứng dụng của mình hoạt động như thế nào hoặc nó cần bao nhiêu CPU hoặc bộ nhớ, thì tùy chọn tốt nhất là cung cấp cho ứng dụng nhiều bộ nhớ và CPU rồi chạy kiểm tra hiệu năng.

Ngoài các bài kiểm tra hiệu suất, hãy theo dõi hành vi của ứng dụng trong quá trình giám sát trong một tuần. Nếu biểu đồ cho thấy ứng dụng của bạn đang tiêu thụ ít tài nguyên hơn mức bạn yêu cầu, bạn có thể giảm lượng CPU hoặc bộ nhớ được yêu cầu.

Như một ví dụ xem cái này Trang tổng quan Grafana. Nó hiển thị sự khác biệt giữa tài nguyên được yêu cầu hoặc giới hạn tài nguyên và mức sử dụng tài nguyên hiện tại.

Kết luận

Yêu cầu và giới hạn tài nguyên giúp cụm Kubernetes của bạn luôn hoạt động tốt. Cấu hình giới hạn phù hợp sẽ giảm thiểu chi phí và giúp ứng dụng luôn chạy.

Tóm lại có vài điều cần lưu ý:

  1. Tài nguyên được yêu cầu là cấu hình được tính đến khi khởi động (khi Kubernetes có kế hoạch lưu trữ ứng dụng). Ngược lại, việc giới hạn tài nguyên là điều quan trọng trong thời gian chạy—khi ứng dụng đang chạy trên nút.
  2. So với bộ nhớ, CPU là tài nguyên được quy định. Nếu không có đủ CPU, Pod của bạn sẽ không tắt và cơ chế điều tiết sẽ bật.
  3. Tài nguyên được yêu cầu và giới hạn tài nguyên không phải là giá trị tối thiểu và tối đa! Bằng cách xác định các tài nguyên được yêu cầu, bạn đảm bảo rằng ứng dụng sẽ chạy mà không gặp sự cố.
  4. Một cách thực hành tốt là đặt yêu cầu bộ nhớ bằng giới hạn bộ nhớ.
  5. Được yêu cầu cài đặt CPU <=1, nếu ứng dụng không thực hiện các phép tính phức tạp.
  6. Nếu bạn yêu cầu nhiều tài nguyên hơn mức có sẵn trên một nút, Pod sẽ không bao giờ được lên lịch cho nút đó.
  7. Để xác định chính xác số lượng tài nguyên/giới hạn tài nguyên được yêu cầu, hãy sử dụng tính năng giám sát và kiểm tra tải.

Tôi hy vọng bài viết này giúp bạn hiểu khái niệm cơ bản về giới hạn tài nguyên. Và bạn sẽ có thể áp dụng kiến ​​thức này vào công việc của mình.

Chúc may mắn!

Những gì khác để đọc:

  1. Khả năng quan sát SRE: Không gian tên và cấu trúc số liệu.
  2. Hơn 90 công cụ hữu ích cho Kubernetes: Triển khai, quản lý, giám sát, bảo mật và hơn thế nữa.
  3. Kênh của chúng tôi Xung quanh Kubernetes trong Telegram.

Nguồn: www.habr.com

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