Використання ресурсів на рівні подів з менеджерами ресурсів kubelet

Стан функціоналу: Beta починаючи з Kubernetes v1.37; стандартно вимкнено
Докладніше про цей функціонал

Щоб скористатися цією функцією, вам (або адміністратору кластера) потрібно увімкнути функціональну можливість PodLevelResourceManagers для всіх відповідних компонентів у вашому кластері.

Перегляньте Увімкнення або вимкнення функціональних можливостей для отримання додаткової інформації.

Цей посібник демонструє, як налаштувати менеджери ресурсів kubelet (topology, CPU та memory) для підтримки специфікацій ресурсів на рівні подів. Ви можете визначити гібридні моделі розподілу, де деякі контейнери отримують ексклюзивні, вирівняні за NUMA інфраструктурні ресурси, тоді як інші спільно використовують решту ресурсів із спільного пулу на рівні пода.

Щоб дізнатися більше про концепції, що стоять за цією функціональною можливістю, прочитайте сторінку концепцій Менеджери ресурсів на рівні Podʼа.

Цілі

  • Налаштувати менеджери ресурсів kubelet (CPU, memory та topology) для підтримки ресурсів на рівні подів.
  • Розгорнути робочі навантаження, використовуючи область дії pod менеджера Topology Manager, щоб досягти вирівнювання за одним NUMA-вузлом зі змішаними ексклюзивними та спільними контейнерами.
  • Перевірити та підтвердити, як ресурси CPU та памʼяті розподіляються між ексклюзивними контейнерами та спільним пулом пода.
  • Зрозуміти правила відхилення при допуску, коли спільний пул на рівні пода був би порожнім.
  • Розгорнути робочі навантаження, використовуючи область дії container менеджера Topology Manager зі змішаними розподілами контейнерів.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Версія вашого Kubernetes сервера має бути не старішою ніж v1.36.

Для перевірки версії введіть kubectl version.

Для виконання цього посібника вам потрібно:

  • Кластер Kubernetes з робочими вузлами Linux (менеджери ресурсів на рівні подів не підтримуються на вузлах Windows).
  • Принаймні один робочий вузол з топологією NUMA (бажано кілька NUMA-вузлів, щоб спостерігати вирівнювання).
  • Адміністративний доступ (root або sudo) на робочому(их) вузлі(ах) для зміни конфігурації kubelet та перезапуску служби kubelet.
  • Доступ до kubectl з дозволом створювати простори імен та поди.

Переконайтеся, що наступні функціональні можливості увімкнені для вашої панелі управління та для робочих вузлів:

  • PodLevelResources
  • PodLevelResourceManagers

Створення простору імен

Створіть простір імен, щоб ресурси, створені в цьому посібнику, були ізольовані від решти вашого кластера:

kubectl create namespace plrm-tutorial

Використання області дії pod зі змішаним розподілом

Коли область дії менеджера Topology Manager встановлено у pod, kubelet виконує єдине вирівнювання NUMA для всього Podʼа на основі .spec.resources. Отриманий бюджет ресурсів потім розподіляється: контейнери, які запитують ресурси Guaranteed, отримують ексклюзивні частки, тоді як контейнери, які не отримують ексклюзивного розподілу, спільно використовують решту бюджету у спільному пулі на рівні пода.

Крок 1: Налаштування kubelet для області дії pod

Щоб увімкнути цю поведінку, налаштуйте kubelet на цільовому(их) робочому(их) вузлі(ах), де ви хочете запускати ці робочі навантаження, з необхідними політиками. Ви можете оновити конфігурацію kubelet для цих вузлів наступним чином:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cpuManagerPolicy: "static"
memoryManagerPolicy: "Static"
topologyManagerScope: "pod"
topologyManagerPolicy: "single-numa-node"
  • Для topologyManagerPolicy допустимими значеннями є single-numa-node, restricted або best-effort. Ви не можете вказати жодне інше значення під час використання управління ресурсами на рівні podʼа.

Перезапустіть kubelet, щоб застосувати конфігурацію. Наприклад, на Linux з systemd: systemctl restart kubelet.service.

Крок 2: Розгортання пода зі змішаним розподілом

Розглянемо наступний приклад маніфесту пода. Под запитує загальний бюджет 4 CPU на рівні пода (.spec.resources). Усередині пода:

  • контейнер main-app запитує ексклюзивний розподіл 2 цілих ядер CPU (requests = limits = 2 CPU).
  • оскільки metrics-sidecar та logging-sidecar не вказують запити на рівні контейнера, ці два контейнери sidecar спільно використовують ядра CPU, що залишилися зі спільного пулу на рівні пода: 2 ядра CPU.
apiVersion: v1
kind: Pod
metadata:
  name: pod-scope-mixed
  annotations:
    kubernetes.io/description: "A pod demonstrating pod-level scope where one container gets exclusive resources and others share the remaining pod resources in a shared pool."
spec:
  # На рівні Podʼа, Pod має запит на CPU, рівний лімітам, і запит на памʼять також
  # рівний лімітам памʼяті. Контейнер main-app відповідає вимогам для класу QoS
  # Guaranteed на рівні контейнера, а sidecar контейнери не вказують жодного
  # запиту на ресурси. У межах масштабу Podʼа kubelet може статично призначити
  # 4 CPU для всього Podʼа, з яких 2 призначені ексклюзивно для контейнера
  # main-app, а решта 2 спільно використовуються sidecar контейнерами.
  resources:
    requests:
      cpu: "4"
      memory: "4Gi"
    limits:
      cpu: "4"
      memory: "4Gi"
  initContainers:
  - name: metrics-sidecar
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей, а не
    # справжнім допоміжним елементом метрик.
    image: registry.k8s.io/pause:3.9
    restartPolicy: Always
  - name: logging-sidecar
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей, а не
    # справжнім агентом ведення журналів.
    image: registry.k8s.io/pause:3.9
    restartPolicy: Always
  containers:
  - name: main-app
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей.
    image: registry.k8s.io/pause:3.9
    resources:
      requests:
        cpu: "2"
        memory: "2Gi"
      limits:
        cpu: "2"
        memory: "2Gi"

Застосуйте маніфест до вашого кластера:

kubectl apply -f https://k8s.io/examples/pods/resource/pod-level-resource-managers-pod-scope-mixed.yaml --namespace=plrm-tutorial

Крок 3: Перевірка та дослідження розподілу ресурсів

  1. Перевірте, що Pod успішно працює:

    kubectl get pod pod-scope-mixed --namespace=plrm-tutorial
    
  2. Зрозумійте, що відбулося за лаштунками:

    flowchart TD
      subgraph Pod["Pod-Level Budget: 4 CPUs, 4Gi Memory"]
          direction TB
          C1["main-app<br/>(Exclusive: 2 CPUs, 2Gi Memory)"]
          subgraph Pool["Pod Shared Pool: 2 CPUs, 2Gi Memory"]
              C2["metrics-sidecar"]
              C3["logging-sidecar"]
          end
      end
    • Вирівнювання Podʼа: Topology Manager оцінив запит Podʼа на 4 CPU (spec.resources) та призначив весь Pod одному NUMA-вузлу.
    • Ексклюзивний розподіл: Менеджер CPU виділив призначену частку у 2 CPU для main-app. Обмеження квоти CFS CPU вимкнено для main-app, що надає йому необмежений доступ до цих ексклюзивних ядер.
    • Спільний пул Podʼа: Решта 2 CPU утворюють спільний пул на рівні пода. metrics-sidecar та logging-sidecar не вказують ресурсів на рівні контейнера (resources: {}), тому вони працюють у цьому ізольованому для пода спільному пулі з увімкненим застосуванням квоти CFS. Хоча пул є спільним між цими двома контейнерами sidecar, він ізольований від зовнішніх робочих навантажень на вузлі, що надає контейнерам sidecar виділену локальність NUMA та захист від конкуренції за ресурси на рівні вузла.

Спостереження за обмеженнями допуску при порожньому спільному пулі

Під час використання області дії pod контроль допуску kubelet відхиляє специфікації подів, які призвели б до порожнього спільного пулу Podʼа, коли є контейнери, які потребують його.

Якщо сума ексклюзивних запитів ресурсів від контейнерів Guaranteed дорівнює загальному бюджету на рівні пода, і принаймні один інший контейнер потребує спільного пулу, kubelet відхиляє Pod.

Крок 4: Розгляд недійсного маніфесту пода

Розглянемо наступний маніфест. Pod запитує загальний бюджет 4 CPU. container-a запитує ексклюзивний 1 CPU, а container-b запитує ексклюзивні 3 CPU (разом 4 CPU). container-c не запитує ексклюзивних ресурсів і потребує спільного пулу, але 0 CPU залишається:

apiVersion: v1
kind: Pod
metadata:
  name: empty-shared-pool
  annotations:
    kubernetes.io/description: "A pod demonstrating a configuration that is rejected because exclusive containers consume the entire pod resource budget, leaving no resources for the remaining container in the shared pool."
spec:
  # На рівні Podʼа, Pod має запит на CPU, рівний лімітам, і запит на памʼять також
  # рівний лімітам памʼяті. Контейнер main-app і metrics-sidecar відповідають вимогам для
  # класу QoS Guaranteed на рівні контейнера, а контейнер logging-sidecar не вказує
  # жодного запиту на ресурси. Оскільки контейнери Guaranteed споживають весь ресурсний
  # бюджет Podʼа, залишаючи 0 CPU для спільного пулу, необхідного для logging-sidecar,
  # цей Pod буде відхилено при допуску.
  resources:
    requests:
      cpu: "4"
      memory: "4Gi"
    limits:
      cpu: "4"
      memory: "4Gi"
  initContainers:
  - name: metrics-sidecar
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей, а не
    # справжнім допоміжним елементом метрик.
    image: registry.k8s.io/pause:3.9
    restartPolicy: Always
    resources:
      requests:
        cpu: "1"
        memory: "1Gi"
      limits:
        cpu: "1"
        memory: "1Gi"
  - name: logging-sidecar
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей, а не
    # справжнім агентом ведення журналів.
    image: registry.k8s.io/pause:3.9
    restartPolicy: Always
  containers:
  - name: main-app
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей.
    image: registry.k8s.io/pause:3.9
    resources:
      requests:
        cpu: "3"
        memory: "3Gi"
      limits:
        cpu: "3"
        memory: "3Gi"

Крок 5: Спроба розгортання та спостереження за відхиленням

  1. Застосуйте маніфест:

    kubectl apply -f https://k8s.io/examples/pods/resource/pod-level-resource-managers-empty-shared-pool.yaml --namespace=plrm-tutorial
    
  2. Перегляньте події Podʼа, щоб побачити помилку допуску:

    kubectl describe pod empty-shared-pool --namespace=plrm-tutorial
    

    Зверніть увагу на повідомлення події, яке пояснює, що kubelet відхилив Pod, оскільки спільний пул на рівні podʼа був би порожнім для контейнерів, які потребують спільних ресурсів:

    Status:           Failed
    Reason:           TopologyAffinityError
    Message:          Pod was rejected: Pod Scope pod with pod-level resources failed admission under pod-scope topology manager
    
    flowchart TD
      subgraph Pod["Pod-Level Budget: 4 CPUs, 4Gi Memory"]
          direction TB
          C1["container-a<br/>(Exclusive: 1 CPU, 1Gi Memory)"]
          C2["container-b<br/>(Exclusive: 3 CPUs, 3Gi Memory)"]
          subgraph Pool["Pod Shared Pool: 0 CPUs, 0Gi Memory"]
              C3["container-c<br/>(Requires shared pool)"]
          end
      end
      Pool --> Rejection["Admission Error: Pod Rejected!"]
      style Rejection fill:#ffcccc,stroke:#ff0000,stroke-width:2px

Використання області дії container зі змішаним розподілом

Ви також можете налаштувати область дії Topology Manager на container. У цьому режимі kubelet оцінює кожен контейнер окремо для ексклюзивного розподілу, тоді як загальний бюджет Podʼа у .spec.resources все ще забезпечує межі QoS та cgroup лімітів.

Крок 6: Налаштування kubelet для області дії container

Оновіть конфігурацію kubelet на цільовому(их) робочому(их) вузлі(ах) для області дії container:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cpuManagerPolicy: "static"
memoryManagerPolicy: "Static"
topologyManagerScope: "container"
topologyManagerPolicy: "single-numa-node"

Перезапустіть kubelet, щоб застосувати конфігурацію. Наприклад, на Linux з systemd: systemctl restart kubelet.service.

Крок 7: Розгортання змішаного робочого навантаження з областю дії container

Розглянемо наступний приклад маніфесту Podʼа. Pod має загальний бюджет 4 CPU:

  • infrastructure-sidecar запитує ексклюзивну частку у 2 CPU (requests = limits = 2 CPU).
  • worker-1 та worker-2 не вказують запитів на рівні контейнера та працюють у загальному, спільному для всього вузла пулі.
apiVersion: v1
kind: Pod
metadata:
  name: container-scope-mixed
  annotations:
    kubernetes.io/description: "A pod demonstrating container-level scope where one container gets exclusive resources and others run in the node's shared pool."
spec:
  # На рівні Podʼа, Pod має запит на CPU, рівний лімітам, і запит на памʼять також
  # рівний лімітам памʼяті. Контейнер infrastructure-sidecar відповідає вимогам для
  # класу QoS Guaranteed на рівні контейнера, а робочі контейнери не вказують
  # жодного запиту на ресурси. У межах контейнерного масштабу kubelet оцінює
  # контейнери індивідуально для ексклюзивного виділення. Це означає, що
  # infrastructure-sidecar отримує ексклюзивний фрагмент CPU на 2 ядра, тоді як
  # робочі контейнери працюють у загальному пулі вузла, все це обмежено загальними
  # лімітами Podʼа.
  resources:
    requests:
      cpu: "4"
      memory: "4Gi"
    limits:
      cpu: "4"
      memory: "4Gi"
  initContainers:
  - name: infrastructure-sidecar
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей, а не
    # справжнім допоміжним елементом інфраструктури.
    image: registry.k8s.io/pause:3.9
    restartPolicy: Always
    resources:
      requests:
        cpu: "2"
        memory: "2Gi"
      limits:
        cpu: "2"
        memory: "2Gi"
  containers:
  - name: worker-1
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей.
    image: registry.k8s.io/pause:3.9
  - name: worker-2
    # Примітка: Тут поле image є заповнювачем для демонстраційних цілей.
    image: registry.k8s.io/pause:3.9

Застосуйте маніфест:

kubectl apply -f https://k8s.io/examples/pods/resource/pod-level-resource-managers-container-scope-mixed.yaml --namespace=plrm-tutorial

Крок 8: Перевірка розгортання

  1. Перевірте, що Pod працює:

    kubectl get pod container-scope-mixed --namespace=plrm-tutorial
    
  2. Зрозумійте, що відбулося за лаштунками:

    flowchart TD
      subgraph Pod["Pod-Level Budget: 4 CPUs, 4Gi Memory"]
          direction TB
          C1["infrastructure-sidecar<br/>(Exclusive NUMA Slice: 2 CPUs, 2Gi Memory)"]
          subgraph NodePool["Node Shared Pool: Pod-level limit"]
              C3["worker-2"]
              C2["worker-1"]
          end
      end
    • Вирівнювання з областю дії container: За області дії container kubelet оцінює контейнери окремо. infrastructure-sidecar отримує ексклюзивну, вирівняну за NUMA частку у 2 CPU безпосередньо з пулу розподілюваних ресурсів вузла.
    • Спільний пул вузла: worker-1 та worker-2 не вказують запитів ресурсів на рівні контейнера (resources: {}), тому за області дії container вони працюють у загальному спільному пулі вузла (а не в ізольованому для podʼа пулі).
    • Застосування ліміту Podʼа: Загальне споживання CPU всіма контейнерами залишається обмеженим 4 CPU лімітом на рівні podʼа (spec.resources.limits).

Очищення

Видаліть простір імен та всі приклади подів, створені під час цього посібника:

kubectl delete namespace plrm-tutorial

Що далі

Востаннє змінено August 30, 2026 at 10:31 AM PST: [uk] Ukrainian translation (all-in-one) (ac41b20ac1)