Интеллектуальное планирование ресурсов GPU#

Данная ИИ-функция автоматизирует распределение ограниченных вычислительных ресурсов GPU между конкурирующими задачами, что имитирует когнитивные способности человека, связанные с принятием решений в условиях ограниченных ресурсов: она позволяет оптимально распределять GPU-ресурсы между задачами ИИ и машинного обучения, учитывая их приоритеты, гарантированные квоты и баланс между потребителями:

Сценарий позволяет пользователю:

  • проверять готовность планировщика KAI Scheduler;

  • управлять очередями планирования и их квотами на ресурсы GPU;

  • планировать GPU-нагрузки с назначением очереди и планировщика;

  • приоритизировать рабочие нагрузки и обеспечивать вытеснение низкоприоритетных задач;

  • обеспечивать одновременное планирование всех pod группы (gang scheduling);

  • эффективно разделять GPU между несколькими задачами.

Примечание

При использовании ИИ-функций DropApp соблюдайте правила работы пользователя с ИИ-функциями.

Предусловия#

Предварительными условиями выполнения сценария являются:

  • Развернутый кластер DropApp с установленным программным компонентом K8S Artificial Intelligence (K8SI).

  • Доступ к кластеру с правами, достаточными для просмотра состояния узлов, pod и ресурсов, а также для создания и удаления pod и пользовательских ресурсов планирования.

  • Наличие GPU-узлов и настроенного GPU-стека (драйверы NVIDIA, Container Toolkit, K8s-device-plugin, компонент GPU Operator), обеспечивающего доступ к ресурсу nvidia.com/gpu.

  • Установленный планировщик KAI Scheduler с созданными по умолчанию очередями default-parent-queue и default-queue.

Сведения о KAI Scheduler и его установке приведены в разделе «KAI Scheduler» Руководства администратора.

Проверка готовности планировщика KAI Scheduler#

Проверьте, что планировщик KAI Scheduler развернут в кластере и готов к планированию рабочих нагрузок. Планировщик обеспечивает интеллектуальное распределение ресурсов GPU между очередями и задачами.

Сценарий проверки готовности KAI Scheduler:

  1. Убедитесь, что pod планировщика в пространстве имен kai-scheduler находятся в состоянии Running:

    kubectl get pods -n kai-scheduler
    

    Пример вывода:

    NAME                            READY   STATUS    RESTARTS   AGE
    kai-scheduler-xxxxxxxxx-xxxxx   1/1     Running   0          10m
    
  2. Убедитесь, что пользовательский ресурс Queue зарегистрирован в кластере:

    kubectl get crd queues.scheduling.run.ai
    

    Если в выводе команды присутствует пользовательский ресурс queues.scheduling.run.ai, планировщик KAI Scheduler готов к управлению очередями и планированию рабочих нагрузок.

  3. Проверьте, что очередь по умолчанию доступна для планирования:

    kubectl get queues
    

    Пример вывода:

    NAME                     AGE
    default-parent-queue     10m
    default-queue            10m
    

    Очереди default-parent-queue (родительская) и default-queue (дочерняя) создаются автоматически при установке KAI Scheduler. Рабочие нагрузки по умолчанию планируются в очередь default-queue.

Управление очередями планирования#

Очередь планирования — пользовательский ресурс Kubernetes, представляющий группу задач с общими гарантиями ресурсов, квотами, лимитами и приоритетом. Очередь является основной базовой единицей управления ресурсами в KAI Scheduler. Рабочая нагрузка должна принадлежать какой-либо очереди, чтобы быть запланированной.

KAI Scheduler поддерживает иерархические очереди: планирование задач выполняется в дочерние (листовые) очереди, а родительские очереди служат организационными единицами распределения ресурсов между дочерними очередями.

Сценарий управления очередями:

  1. Создайте очередь с гарантированной квотой и лимитом на ресурсы GPU, а также на CPU и память:

    apiVersion: scheduling.run.ai/v2
    kind: Queue
    metadata:
      name: ml-team
    spec:
      displayName: "ML Team"
      parentQueue: "default-parent-queue"
      resources:
        cpu:
          quota: 1000
          limit: 2000
        memory:
          quota: 4096
          limit: 8192
        gpu:
          quota: 1
          limit: 2
    

    Где:

    • parentQueue — родительская очередь, в которую входит создаваемая очередь (опционально);

    • quota — гарантированный объем ресурса, выделяемый очереди;

    • limit — максимальный объем ресурса, который может потребить очередь;

    • priority — приоритет очереди при распределении ресурсов, превышающих квоту (опционально).

  2. Примените манифест:

    kubectl apply -f - <<EOF
    apiVersion: scheduling.run.ai/v2
    kind: Queue
    metadata:
      name: ml-team
    spec:
      displayName: "ML Team"
      parentQueue: "default-parent-queue"
      resources:
        cpu:
          quota: 1000
          limit: 2000
        memory:
          quota: 4096
          limit: 8192
        gpu:
          quota: 1
          limit: 2
    EOF
    
  3. Убедитесь, что очередь создана и доступна для планирования:

    kubectl get queue ml-team
    

    Очередь ml-team готова к планированию рабочих нагрузок с гарантированной квотой и лимитом ресурсов GPU.

Планирование GPU-нагрузки с назначением очереди#

Планируйте рабочие нагрузки с использованием KAI Scheduler, назначая им очередь планирования и планировщик. Для планирования задачи средствами KAI Scheduler необходимо указать в ее спецификации имя очереди в метке kai.scheduler/queue и имя планировщика kai-scheduler в поле schedulerName.

Важно

Для отправки рабочих нагрузок используйте выделенное пространство имен. Не используйте пространство имен kai-scheduler для отправки рабочих нагрузок.

Сценарий планирования GPU-нагрузки:

  1. Создайте pod, запрашивающий ресурс GPU nvidia.com/gpu и назначенный в очередь default-queue:

    apiVersion: v1
    kind: Pod
    metadata:
      name: gpu-pod
      labels:
        kai.scheduler/queue: default-queue
    spec:
      schedulerName: kai-scheduler
      containers:
        - name: main
          image: sberlinux
          command: ["bash", "-c"]
          args: ["nvidia-smi; trap 'exit 0' TERM; sleep infinity & wait"]
          resources:
            limits:
              nvidia.com/gpu: "1"
    

    Где:

    • kai.scheduler/queue — метка, указывающая очередь планирования, в которую помещается pod;

    • schedulerName — имя планировщика, управляющего размещением pod (kai-scheduler);

    • nvidia.com/gpu — количество физических GPU, необходимых для pod.

  2. Примените манифест:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: gpu-pod
      labels:
        kai.scheduler/queue: default-queue
    spec:
      schedulerName: kai-scheduler
      containers:
        - name: main
          image: sberlinux
          command: ["bash", "-c"]
          args: ["nvidia-smi; trap 'exit 0' TERM; sleep infinity & wait"]
          resources:
            limits:
              nvidia.com/gpu: "1"
    EOF
    
  3. Убедитесь, что pod запланирован и находится в состоянии Running:

    kubectl get pod gpu-pod -o wide
    

    Pod успешно размещен на GPU-узле планировщиком KAI Scheduler, что подтверждает корректность назначения очереди и планирования GPU-ресурса.

  4. Проверьте, что внутри pod доступен GPU-ускоритель:

    kubectl logs gpu-pod | head -n 5
    

    Вывод команды nvidia-smi содержит сведения о GPU-ускорителе, выделенном pod.

  5. После завершения проверки удалите тестовый pod:

    kubectl delete pod gpu-pod
    

Приоритизация рабочих нагрузок#

KAI Scheduler классифицирует рабочие нагрузки по приоритету и планирует их в порядке убывания приоритета. При нехватке ресурсов в кластере планировщик вытесняет низкоприоритетные задачи, освобождая ресурсы для высокоприоритетных. Это обеспечивает первоочередное выделение ресурсов критичным сервисам и соблюдение SLA (Service Level Agreement, соглашение об уровне предоставления услуги).

KAI Scheduler поставляется с предопределенными классами приоритетов:

Классы приоритетов KAI Scheduler#

Класс приоритета

Значение

Назначение

train

50

Предвытесняемые обучающие рабочие нагрузки

build-preemptible

75

Предвытесняемые задачи сборки и интерактивные задачи

build

100

Задачи сборки и интерактивные задачи (не подлежат вытеснению)

inference

125

Задачи инференса (не подлежат вытеснению)

Класс приоритета указывается в поле priorityClassName спецификации pod или рабочей нагрузки. Класс приоритета со значением 100 и выше считается не подлежащим вытеснению.

Сценарий приоритизации рабочих нагрузок:

  1. Создайте очередь с лимитом в один GPU:

    apiVersion: scheduling.run.ai/v2
    kind: Queue
    metadata:
      name: test
    spec:
      resources:
        gpu:
          quota: 0
          limit: 1
    

    Очередь test ограничивает потребление ресурсов GPU одним устройством (limit: 1), что позволяет продемонстрировать вытеснение задач.

  2. Примените манифест:

    kubectl apply -f - <<EOF
    apiVersion: scheduling.run.ai/v2
    kind: Queue
    metadata:
      name: test
    spec:
      resources:
        gpu:
          quota: 0
          limit: 1
    EOF
    
  3. Создайте pod с приоритетом train (значение 50), запрашивающий один GPU:

    apiVersion: v1
    kind: Pod
    metadata:
      name: train-pod
      labels:
        kai.scheduler/queue: test
    spec:
      schedulerName: kai-scheduler
      priorityClassName: train
      containers:
        - name: main
          image: sberlinux
          command: ["bash", "-c"]
          args: ["sleep infinity"]
          resources:
            limits:
              nvidia.com/gpu: "1"
    

    Примените манифест pod train-pod.

  4. Дождитесь, пока pod train-pod перейдет в состояние Running:

    kubectl get pod train-pod
    
  5. Создайте pod с приоритетом build (значение 100), запрашивающий один GPU в ту же очередь test:

    apiVersion: v1
    kind: Pod
    metadata:
      name: build-pod
      labels:
        kai.scheduler/queue: test
    spec:
      schedulerName: kai-scheduler
      priorityClassName: build
      containers:
        - name: main
          image: sberlinux
          command: ["bash", "-c"]
          args: ["sleep infinity"]
          resources:
            limits:
              nvidia.com/gpu: "1"
    

    Примените манифест pod build-pod.

  6. Проверьте состояние обоих pod:

    kubectl get pods | grep -E "train-pod|build-pod"
    

    Поскольку оба pod запрашивают один GPU, который является лимитом очереди test, планировщик вытеснит низкоприоритетный pod train-pod и запланирует высокоприоритетный pod build-pod вместо него. Это подтверждает приоритизацию рабочих нагрузок средствами KAI Scheduler.

  7. После завершения проверки удалите тестовые pod и очередь:

    kubectl delete pod train-pod build-pod
    
    kubectl delete queue test
    

Одновременное планирование группы pod#

KAI Scheduler поддерживает одновременное (gang) планирование группы pod: либо все pod группы планируются одновременно, либо ни один из них не получает ресурсы до появления достаточных ресурсов в кластере. Это необходимо для распределенных задач обучения и инференса, в которых все pod должны запускаться совместно.

Сценарий одновременного планирования группы pod:

  1. Зарегистрируйте пользовательский ресурс PodGroup и убедитесь в его доступности:

    kubectl get crd podgroups.scheduling.run.ai
    

    Если в выводе команды присутствует пользовательский ресурс podgroups.scheduling.run.ai, планировщик KAI Scheduler готов к управлению группами pod.

  2. Создайте PodGroup, объединяющий группу pod с минимальным количеством участников:

    apiVersion: scheduling.run.ai/v2
    kind: PodGroup
    metadata:
      name: ai-training
      labels:
        kai.scheduler/queue: default-queue
    spec:
      minMember: 3
    

    Где minMember — минимальное количество pod, которые должны быть запланированы совместно, прежде чем запустится любой из них.

  3. Примените манифест:

    kubectl apply -f - <<EOF
    apiVersion: scheduling.run.ai/v2
    kind: PodGroup
    metadata:
      name: ai-training
      labels:
        kai.scheduler/queue: default-queue
    spec:
      minMember: 3
    EOF
    
  4. Создайте pod, входящие в группу ai-training:

    apiVersion: v1
    kind: Pod
    metadata:
      name: ai-training-0
      labels:
        kai.scheduler/queue: default-queue
        pod-group.scheduling.run.ai/name: ai-training
    spec:
      schedulerName: kai-scheduler
      containers:
        - name: main
          image: sberlinux
          command: ["bash", "-c"]
          args: ["sleep infinity"]
          resources:
            limits:
              nvidia.com/gpu: "1"
    

    Аналогичным образом создайте pod ai-training-1 и ai-training-2, указав в каждом метку очереди kai.scheduler/queue: default-queue и принадлежность к группе pod-group.scheduling.run.ai/name: ai-training.

  5. Примените манифесты pod группы.

  6. Убедитесь, что все pod группы запущены совместно:

    kubectl get pods | grep ai-training
    

    Если все pod группы ai-training находятся в состоянии Running, одновременное планирование группы настроено корректно.

  7. После завершения проверки удалите группу и тестовые pod:

    kubectl delete podgroup ai-training
    
    kubectl delete pod ai-training-0 ai-training-1 ai-training-2
    

Совместное использование GPU#

KAI Scheduler позволяет эффективно разделять один или несколько GPU между несколькими pod, максимизируя использование ресурсов. Pod может запросить часть GPU-устройства, указав долю памяти устройства или конкретный объем памяти GPU.

Примечание

Совместное использование GPU (GPU Sharing) отключено по умолчанию и включается параметром global.gpuSharing=true при установке KAI Scheduler (подробнее — в разделе «KAI Scheduler» Руководства администратора).

Сценарий совместного использования GPU:

  1. Создайте pod, запрашивающий долю GPU-устройства 0.5 (половину памяти устройства):

    apiVersion: v1
    kind: Pod
    metadata:
      name: gpu-sharing-pod
      labels:
        kai.scheduler/queue: default-queue
      annotations:
        gpu-fraction: "0.5"
    spec:
      schedulerName: kai-scheduler
      containers:
        - name: main
          image: sberlinux
          command: ["bash", "-c"]
          args: ["sleep infinity"]
          resources:
            limits:
              nvidia.com/gpu: "1"
    

    Где аннотация gpu-fraction со значением 0.5 разрешает pod потреблять до половины памяти GPU-устройства, оставляя остальную память для совместного использования другими pod.

  2. Примените манифест:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: gpu-sharing-pod
      labels:
        kai.scheduler/queue: default-queue
      annotations:
        gpu-fraction: "0.5"
    spec:
      schedulerName: kai-scheduler
      containers:
        - name: main
          image: sberlinux
          command: ["bash", "-c"]
          args: ["sleep infinity"]
          resources:
            limits:
              nvidia.com/gpu: "1"
    EOF
    
  3. Убедитесь, что pod gpu-sharing-pod находится в состоянии Running:

    kubectl get pod gpu-sharing-pod
    
  4. Создайте второй pod с аннотацией gpu-memory, запрашивающий конкретный объем памяти GPU-устройства (в МиБ):

    apiVersion: v1
    kind: Pod
    metadata:
      name: gpu-memory-pod
      labels:
        kai.scheduler/queue: default-queue
      annotations:
        gpu-memory: "2000"
    spec:
      schedulerName: kai-scheduler
      containers:
        - name: main
          image: sberlinux
          command: ["bash", "-c"]
          args: ["sleep infinity"]
          resources:
            limits:
              nvidia.com/gpu: "1"
    

    Аннотация gpu-memory со значением 2000 разрешает pod потреблять до 2000 МиБ памяти GPU-устройства, оставляя остальную память для других pod.

  5. Примените манифест pod gpu-memory-pod.

  6. Убедитесь, что оба pod совместно используют одно GPU-устройство:

    kubectl get pods | grep gpu
    

    Если pod gpu-sharing-pod и gpu-memory-pod находятся в состоянии Running и размещены на одном GPU-узле, совместное использование GPU настроено корректно.

  7. После завершения проверки удалите тестовые pod:

    kubectl delete pod gpu-sharing-pod gpu-memory-pod
    

Результат#

Ожидаемым результатом являются:

  • готовность планировщика KAI Scheduler к планированию;

  • успешная настройка очередей и их квот на ресурсы GPU;

  • запланированность GPU-нагрузки с назначением очереди;

  • приоритезация рабочих нагрузок с вытеснением низкоприоритетных задач;

  • одновременная запланированность группы pod и эффективное совместное использование GPU несколькими задачами.