Настройка деревьев пулов

В данном разделе описывается настройка вычислительных пулов и деревьев пулов в контексте распределения вычислительных ресурсов кластера.

Конфигурация дерева пулов

Дерево представляет собой объект scheduler_pool_tree на первом уровне узла //sys/pool_trees в Кипарисе. Дочерними узлами дерева пулов могут быть только вычислительные пулы. Конфигурация дерева задаётся через атрибут config.

Также у узла //sys/pool_trees имеется атрибут default_tree, в котором можно указать дерево по умолчанию, которое будет использоваться для операций, у которых не указана опция pool_trees.

В конфигурации дерева представлены следующие опции:

  • node_tag_filter — (прежнее название nodes_filter) фильтр для выбора узлов кластера, принадлежащих дереву (подробнее читайте в разделе Тегирование нод кластера);
  • main_resource — основной ресурс дерева; если у пула заданы гарантии, то в них обязан присутствовать данный ресурс. Гарантии по неуказанным ресурсам вычисляются пропорционально основному ресурсу;
  • max_operation_count — значение по умолчанию для максимального числа одновременно запущенных (running + pending) операций в дереве;
  • max_operation_count_per_pool — значение по умолчанию для максимального числа одновременно запущенных операций в пуле, если max_operation_count не задан на самом пуле;
  • max_running_operation_count — значение по умолчанию для максимального числа одновременно выполняющихся (running) операций в дереве;
  • max_running_operation_count_per_pool — значение по умолчанию для максимального числа одновременно выполняющихся операций в пуле, если max_running_operation_count не задан на самом пуле;
  • default_parent_pool — пул по умолчанию, в котором будут запускаться операции, в спецификации которых пул не указан явно;
  • forbid_immediate_operations_in_root — запрещает запуск операций в корневом пуле дерева;
  • max_ephemeral_pool_per_user — максимальное количество эфемерных пулов для каждого пользователя. Эфемерный пул — это пул, который был указан в спецификации, но для которого нет явно заведённого узла в Кипарисе;
  • infer_weight_from_guarantees_share_multiplier — указание данного множителя включает автовыведение веса пула пропорционально гарантии пула по main_resource (точнее, пропорционально strong guarantee share). Автовыведение применяется только к пулам, у которых вес не задан явно;
  • integral_guarantees — настройки управления интегральными гарантиями в данном дереве;
  • pool_config_presets — описание пресетов конфигураций пулов.
  • preemptive_scheduling_backoff — ограничение на частоту планирования аллокаций с вытеснением на одной ноде;
  • fair_share_starvation_timeout — после заданного периода времени, если операция недополучает положенные ресурсы, она становится страдающей (starving), и для планирования её аллокаций используется механизм вытеснения;
  • fair_share_starvation_tolerance — пороговое значение, определяющее, что операция считается недополучающей ресурсы. Операция считается недополучающей ресурсы (статус below_fair_share), если usage_share < fair_share * tolerance по доминантному ресурсу;
  • preemption_satisfaction_threshold — пороговое значение, разделяющее аллокации на невытесняемые (а также агрессивно вытесняемые) и вытесняемые. Аллокации, у которых кумулятивный usage_share превосходит fair_share * threshold, считаются вытесняемыми, а все остальные — невытесняемыми (или агрессивно вытесняемыми);
  • non_preemptible_resource_usage_threshold — операция не будет участвовать в вытеснении, если её потребление ресурсов меньше данного значения;
  • allocation_preemption_timeout — таймаут на вытеснение аллокации. Если джоб в заданной аллокации поддерживает interruption, то, прежде чем джоб будет прерван, ему будет дано указанное время, чтобы успешно завершиться;
  • aggressive_preemption_satisfaction_threshold — пороговое значение для разделения аллокаций на невытесняемые и агрессивно вытесняемые (а также просто вытесняемые). Аллокации, у которых кумулятивный usage_share превосходит fair_share * threshold, считаются агрессивно вытесняемыми и просто вытесняемыми. Значение данного порога не должно превышать preemption_satisfaction_threshold.

Конфигурация пула

Пул (pool) является объектом типа scheduler_pool. Каждый пул принадлежит конкретному дереву пулов. Иерархия пулов естественным образом является частью Кипариса и расположена по пути //sys/pool_trees/<tree_name>. При создании пула необходимо указать дерево пулов и родительский пул в рамках дерева. Опции пула задаются с помощью атрибутов.

Ниже перечислены доступные опции в конфигурации пула; в скобках указаны значения по умолчанию.

  • weight (none) — действительное неотрицательное число, определяющее, в какой пропорции данному поддереву необходимо предоставлять ресурсы родительского пула. Например, если у пула есть два дочерних пула с весами 2 и 1, ресурсы родителя будут делиться между ними в пропорции 2:1;
  • strong_guarantee_resources — словарь, в котором указаны гарантированные ресурсы для данного пула (user_slots, cpu, memory, gpu);

Примечание

Следует понимать, что гарантии будут выполнены только в том случае, если доминантный ресурс операции совпадает с гарантированным ресурсом.

  • resource_limits — словарь, в котором описаны ограничения на различные ресурсы данного пула (user_slots, cpu, memory);
  • mode (fair_share) — режим планирования, может принимать значения fair_share или fifo. В режиме fifo джобы выдаются дочерним операциям в порядке лексикографической сортировки по значениям параметров, указанных в атрибуте fifo_sort_parameters для данного пула. Например, если значение атрибута равно [start_time], джобы будут выдаваться операциям с наименьшим временем старта;
  • max_running_operation_count (8) — ограничение на число одновременно выполняющихся (running) операций в пуле. Операции сверх этого лимита будут вставать в очередь и находиться в состоянии pending;
  • max_operation_count (50) — ограничение на число одновременно запущенных (running + pending) операций в пуле. При достижении указанного ограничения запуск новых операций в пуле будет завершаться с ошибкой;
  • fifo_sort_parameters ([weight, start_time]) — порядок запуска операций в FIFO-пуле. По умолчанию операции сортируются сначала по весу, а затем по времени запуска. Данный параметр позволяет изменять порядок операций в очереди. Поддерживаемые значения: start_time, weight, pending_job_count. По параметру weight сортировка выполняется в обратном порядке, то есть операции с большим весом будут идти раньше и иметь больший приоритет. Значение pending_job_count позволяет приоритизировать небольшие операции (с малым количеством джобов);
  • forbid_immediate_operations — запрещает запуск операций непосредственно в данном пуле. На запуск операций в подпулах это ограничение не распространяется;
  • create_ephemeral_subpools (false) — активирует режим, в котором для операций создаётся эфемерный подпул в данном пуле с именем poolname$username, где poolname — имя текущего пула. Операция запускается в созданном эфемерном подпуле;
  • ephemeral_subpool_config — вложенная конфигурация эфемерных подпулов, создаваемых в текущем пуле. Имеет смысл только если задана опция create_ephemeral_subpools. В конфигурации можно указать mode, max_running_operation_count, max_operation_count, resource_limits;
  • offloading_settings — настройка, отвечающая за переселение части джобов пула в другое дерево наряду с тем, в котором находится пул. Переселение джобов работает для операций, запущенных после установки настройки. Пример настройки: yt set //sys/pool_trees/<pool_tree>/<pool>/@offloading_settings '{<pool_tree_X>={pool=<pool_name_Y>}}';
  • config_presets — список пресетов, применяемых к данному пулу.

У каждого пула имеется своё уникальное (в рамках одного дерева) название. Имя выбранного для запуска операции пула отражается в настройках операции.

Внимание

Параметры max_running_operation_count и max_operation_count задаются (явно или неявно) на всех уровнях иерархии пулов и проверяются также на всех уровнях. В частности, запуск новой операции в пуле P возможен, если и только если как в P, так и во всех его родителях (вплоть до корня) количество запущенных операций меньше заданного ограничения. Аналогично для ограничения max_running_operation_count: операция в пуле P будет оставаться в состоянии pending до тех пор, пока в данном пуле или в каком-либо из его родителей количество выполняющихся (running) операций больше либо равно ограничению max_running_operation_count. На каждом уровне иерархии возможна переопределённая настройка указанных ограничений. Это обстоятельство нужно учитывать при заказах и изменениях ограничений пользовательских пулов. Чтобы гарантировать пулу определённое количество операций, необходимо убедиться, что на всех уровнях вплоть до корня переопределения отсутствуют.

Конфигурация вычислительных ресурсов операции

Часть настроек, свойственных пулу, также доступна для операций и указывается в корне спецификации операции при запуске. К таким настройкам относятся weight и resource_limits.

Например, можно указать в спецификации resource_limits={user_slots=200} — в этом случае у операции будет запущено не более 200 джобов одновременно в каждом дереве.

Настройка resource_limits, а также другие параметры могут быть заданы независимо для различных деревьев пулов.

Пример настройки пулов

Рассмотрим структуру пулов проекта, операции которого можно разделить на три класса: ручные запросы (adhoc), пакетная обработка и резервное копирование. В распоряжении проекта имеется квота в 100 вычислительных ядер и стандартные ограничения на количество операций.

Требуется настроить пулы таким образом, чтобы:

  • Adhoc-операции выполнялись как можно быстрее и меньше ждали очереди на запуск.
  • Для пакетной обработки необходимо использовать все свободные ресурсы, когда adhoc-задач мало или они отсутствуют.
  • Для операций резервного копирования требуется небольшая гарантия по ресурсам, чтобы процесс укладывался в отведённое время.

Для этого нужно создать отдельные пулы для каждого типа нагрузки и поместить их в общий корневой пул проекта (project-root). Настройки пулов приведены в таблице.

pool_name strong_guarantee_resources/cpu weight max_running_operation_count max_operation_count
project-root 100 1 10 50
project-root/project-adhoc 80 1 10 50
project-root/project-batch 0 10 4 50
project-root/project-backup 20 1 2 50

Отметим, что сумма гарантированных ресурсов в потомкам не может превышать гарантию родительского пула. При этом для лимитов на количество операций такого ограничения нет, но должно быть выполнено естественное условие: значение max_running_operation_count каждого пула не может быть больше его max_operation_count.

Если сумма ограничений max_running_operation_count подпулов превышает аналогичное ограничение родительского пула, то может возникнуть ситуация, когда операция в каком-либо подпуле не сможет выполняться, даже если число выполняющихся операций в пуле не достигло ограничения. Это может произойти из-за того, что в других подпулах запущено и выполняется слишком много операций, и их количество сравнялось с ограничением max_running_operation_count родительского пула. Даже наличие гарантии у подпула в таком случае не приведёт к вытеснению уже работающих операций в других пулах. Вытесняться могут только джобы (если их более одной в операции), но не сами операции.

В структуре пулов, приведённой в таблице, все гарантированные вычислительные ресурсы достаются пулам project-adhoc и project-backup в случае их полной загрузки, а джобы операций, запущенных в project-batch, вытесняются. Однако если операции хотя бы в одном из пулов с гарантиями не могут полностью утилизировать свой пул, невостребованные ресурсы могут быть переданы пулу project-batch, который имеет больший приоритет.

Динамические характеристики операций и пулов

В результате работы алгоритма планирования ресурсы кластера распределяются между вычислительными пулами и операциями.

Для конкретного дерева пулов текущие значения различных характеристик можно узнать через орхидею планировщика:

  • Для пула данная информация доступна по пути //sys/scheduler/orchid/scheduler/pool_trees/<pool-tree>/pools/<pool>;
  • Для операций — по пути //sys/scheduler/orchid/scheduler/pool_trees/<pool-tree>/operations/<operation-id>.

Также данная информация доступна в UI на странице Scheduling и на странице операции. Например, там отображаются следующие характеристики:

  • Fair share — доля ресурсов кластера, которая гарантирована операции (или пулу) в данный момент;
  • Usage share — доля ресурсов кластера, которую сейчас потребляет операция или пул — все аллокации операции или всех операций в поддереве пула;
  • Demand share — доля ресурсов кластера, которая требуется операции или пулу для запуска всех аллокаций;
  • Starvation status — флаг, указывающий, страдает ли операция. При наличии страдающей операции планировщик попытается прервать джобы нестрадающих операций (выполнить вытеснение), чтобы запустить аллокации страдающей операции;
  • Dominant resource — доминантный ресурс операции или пула — тот ресурс, доля которого от ресурсов всего кластера наибольшая.

Все описанные выше доли представляют собой вектор долей по каждому из ресурсов кластера. В случае, если доля представлена одним числом — это доля по доминантному ресурсу.

Динамические характеристики операций рассчитываются для каждого дерева отдельно. Соответственно, операция может иметь несколько значений Fair share, Usage share и других параметров.

Предыдущая