Тем, где именно запускается виртуальная машина (ВМ), управляют четыре механизма:
.spec.nodeSelector— самый простой способ, выбирает узлы с нужными лейблами;.spec.affinity.nodeAffinity— задаёт приоритетные узлы для размещения;.spec.affinity.virtualMachineAndPodAffinity— размещает машину рядом с другими машинами и рабочими нагрузками;.spec.affinity.virtualMachineAndPodAntiAffinity— наоборот, разводит их по разным узлам.
Условия бывают жёсткими и мягкими. Жёсткое условие requiredDuringSchedulingIgnoredDuringExecution обязательно к исполнению, и машина не запустится, если подходящего узла нет. Мягкое условие preferredDuringSchedulingIgnoredDuringExecution планировщик учитывает по возможности.
Все правила, включая .spec.nodeSelector из класса ВМ, применяются вместе. Если хотя бы одно жёсткое условие выполнить нельзя, машина остаётся в фазе Pending. Поэтому задавайте непротиворечивые правила, предпочитайте комбинации лейблов одиночным жёстким ограничениям и держите в запасе узлы для критичных нагрузок. Учитывайте и порядок запуска. Если одна машина обязана оказаться рядом с другой, сначала должна запуститься вторая. Если на нужных узлах стоят ограничения taints, добавьте машине соответствующие tolerations.
Когда вы меняете правила размещения у работающей машины, а её текущий узел новым требованиям больше не отвечает, в коммерческих редакциях Deckhouse Platform (DP) переносит машину живой миграцией, а в DP Open изменения применяются только после перезагрузки. Машина, которая новым требованиям и так отвечает, остаётся на месте.
Как задать правила размещения в веб-интерфейсе:
- Перейдите на вкладку «Проекты» и выберите нужный проект.
- Перейдите в раздел «Виртуализация» → «Виртуальные машины».
- Из списка выберите нужную ВМ и нажмите на её имя.
- На вкладке «Конфигурация» прокрутите страницу до переключателя «Размещение ВМ».
- Выберите режим заполнения. В режиме «Базовая настройка» правила задаются переключателями «Совместное размещение» и «Раздельное размещение», в режиме «Редактирование» блок размещения задаётся вручную в виде YAML.
- Включите нужный переключатель и заполните поля. В поле «Выберите режим правила» доступны «Принудительное» (
requiredDuringSchedulingIgnoredDuringExecution) и «Предпочтительное» (preferredDuringSchedulingIgnoredDuringExecution), а в поле «Правило размещения» — размещение относительно других ВМ или относительно лейблов узлов. - Нажмите появившуюся кнопку «Сохранить».
Толерантность к ограничениям узлов
Tolerations позволяют ВМ запускаться на узлах с ограничениями (taints), которые иначе блокируют планирование (scheduling). Это полезно, когда нужно запускать ВМ на специальных узлах (например, тестовых) или узлах с определёнными характеристиками.
Пример использования tolerations для разрешения запуска на узлах с taint node.deckhouse.io/group=:NoSchedule:
spec:
tolerations:
- key: "node.deckhouse.io/group"
operator: "Exists"
effect: "NoSchedule"
Каждый элемент списка tolerations должен соответствовать taint на узле, чтобы ВМ могла быть размещена на этом узле.
Для просмотра информации об узлах кластера (включая taints) требуется роль пользователя с правами доступа к ресурсам уровня кластера.
Чтобы посмотреть taints на узлах кластера, выполните команду:
d8 k get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
Чтобы посмотреть подробную информацию об узле, выполните команду:
d8 k describe node <NODE_NAME>
Простое связывание по меткам (nodeSelector)
nodeSelector — это простейший способ контролировать размещение виртуальных машин, используя набор меток. Он позволяет задать, на каких узлах могут запускаться виртуальные машины, выбирая узлы с необходимыми метками.
spec:
nodeSelector:
disktype: ssd

В этом примере в кластере три узла, два из них с быстрыми дисками (disktype=ssd) и один с медленными (disktype=hdd). Виртуальная машина будет размещена только на узлах, которые имеют метку disktype со значением ssd.
Как выполнить операцию в веб-интерфейсе в разделе «Размещение»:
- Включите переключатель «Совместное размещение».
- В поле «Выберите режим правила» выберите «Принудительное».
- В поле «Правило размещения» выберите «На выбранных узлах».
- В поле «Как определить группу узлов» выберите «По лейблам» и укажите лейблы узлов (например,
disktype: ssd); вариант «По имени» позволяет выбрать конкретные узлы. - Нажмите появившуюся кнопку «Сохранить».
Предпочтительное связывание (Affinity)
Affinity предоставляет более гибкие и мощные инструменты по сравнению с nodeSelector. Он позволяет задавать «предпочтения» и «обязательности» для размещения виртуальных машин. Affinity поддерживает два вида, nodeAffinity и virtualMachineAndPodAffinity.
nodeAffinity — определяет узлы для запуска ВМ с помощью выражений селекторов меток.
Пример использования nodeAffinity с жестким правилом:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd

В этом примере в кластере три узла, два из них с быстрыми дисками (disktype=ssd) и один с медленными (disktype=hdd). Виртуальная машина будет размещена только на узлах, которые имеют метку disktype со значением ssd.
Если использовать мягкое требование (preferredDuringSchedulingIgnoredDuringExecution), то при отсутствии ресурсов для запуска ВМ на узлах с дисками disktype=ssd она будет запланирована на узле с дисками disktype=hdd.
virtualMachineAndPodAffinity управляет размещением виртуальных машин относительно других виртуальных машин. Он позволяет задавать предпочтение размещения виртуальных машин на тех же узлах, где уже запущены определенные виртуальные машины.
Пример мягкого правила:
spec:
affinity:
virtualMachineAndPodAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchLabels:
server: database
topologyKey: "kubernetes.io/hostname"

В этом примере виртуальная машина размещается только на узлах, где уже работает виртуальная машина с лейблом server: database. Правило мягкое (preferred), поэтому при отсутствии таких узлов машина запустится на любом подходящем.
Чтобы размещать ВМ по зонам доступности (а не привязывать к конкретным узлам), задайте topologyKey: topology.kubernetes.io/zone (раздел «Размещение ВМ по зонам доступности»).
Как задавать «предпочтения» и «обязательности» для размещения виртуальных машин в веб-интерфейсе в разделе «Размещение»:
- Включите переключатель «Совместное размещение» — он соответствует настройкам
spec.affinity.virtualMachineAndPodAffinity. - В поле «Выберите режим правила» выберите «Принудительное» или «Предпочтительное».
- В поле «Правило размещения» выберите «На узлах с выбранными ВМ».
- В поле «Выберите лейблы» выберите лейблы нужных ВМ из списка или введите свой в формате
key: value. - Нажмите появившуюся кнопку «Сохранить».
Избежание совместного размещения (AntiAffinity)
AntiAffinity используется для предотвращения совместного размещения ВМ на узлах. Полезно для обеспечения отказоустойчивости или балансировки нагрузки.
Будьте осторожны при использовании жестких требований в небольших кластерах, где мало узлов для запуска виртуальных машин. Если используется параметр virtualMachineAndPodAntiAffinity с типом requiredDuringSchedulingIgnoredDuringExecution для виртуальных машин, это означает, что каждая копия ВМ должна размещаться на отдельном узле. В условиях ограниченного количества узлов в кластере это может привести к ситуации, когда некоторые ВМ не смогут быть запущены из-за недостатка доступных узлов.
Термины Affinity и AntiAffinity описывают отношения между виртуальными машинами. Для узлов такого антонима нет, но того же результата можно добиться через nodeAffinity с оператором NotIn, исключив нужные узлы.
Пример использования virtualMachineAndPodAntiAffinity:
spec:
affinity:
virtualMachineAndPodAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
server: database
topologyKey: "kubernetes.io/hostname"

В данном примере создаваемая виртуальная машина не будет размещена на одном узле с виртуальной машиной с меткой server: database.
Чтобы размещать ВМ по зонам доступности (а не привязывать к конкретным узлам), задайте topologyKey: topology.kubernetes.io/zone (раздел «Размещение ВМ по зонам доступности»).
Как настроить предотвращение совместного размещения ВМ на узлах в веб-интерфейсе в разделе «Размещение»:
- Включите переключатель «Раздельное размещение» — он соответствует настройкам
spec.affinity.virtualMachineAndPodAntiAffinity. - В поле «Выберите режим правила» выберите «Принудительное» или «Предпочтительное».
- В поле «Правило размещения» выберите «На узлах с выбранными ВМ».
- В поле «Выберите лейблы» выберите лейблы ВМ, рядом с которыми размещать машину не нужно, или введите свой лейбл в формате
key: value. - Нажмите появившуюся кнопку «Сохранить».
Размещение ВМ по зонам доступности
Правила размещения работают не только на уровне узлов, но и на уровне зон доступности.
Зоны доступности должны быть предварительно настроены на узлах кластера. Для этого на узлах должна быть установлена метка topology.kubernetes.io/zone с указанием зоны доступности.
В примерах выше используется topologyKey: "kubernetes.io/hostname", что размещает ВМ на одном узле. Для размещения ВМ по зонам доступности вместо узлов используйте topologyKey: "topology.kubernetes.io/zone".
При использовании Affinity с topologyKey: "topology.kubernetes.io/zone" ВМ будут размещаться в той же зоне доступности, где присутствует виртуальная машина с указанными метками.
При использовании AntiAffinity с topologyKey: "topology.kubernetes.io/zone" ВМ не будут размещаться в той же зоне доступности, что и виртуальная машина с указанными метками. Это полезно для обеспечения отказоустойчивости при распределении ВМ по разным зонам доступности.
Чтобы посмотреть зоны доступности на узлах кластера (если эти зоны заданы), выполните команду:
d8 k get nodes -o custom-columns=NAME:.metadata.name,ZONE:.metadata.labels.topology\.kubernetes\.io/zone