После установки плоскости управления, кластерного компонента и Knative Serving стек готов принимать нагрузки. Приведённые ниже тесты сквозным образом проверяют три типа нагрузок (инференс, рабочая среда, обучение) с помощью CLI runai версии 2 и подтверждают, что планирование GPU, автомасштабирование Knative и внешняя связность работают. Каждый тест содержит явные шаги проверки, чтобы оператор понимал, что тест пройден. Все три теста самодостаточны и после проверки могут быть свёрнуты.
Вход в CLI и настройка проекта
Вход в плоскость управления с указанием целевого кластера и проекта. CLI принимает локальные учётные данные напрямую либо может открыть браузер для OIDC:
runai login user -u admin@<corp-domain> -p '<admin-password>'
runai cluster set <cluster-name>
runai project set <project-name>
NVIDIA Run:ai создаёт в кластере пространство имён runai-<project-name>. На кластерах VKS с PSA уровня restricted его нужно пометить как привилегированное, иначе поды нагрузок будут отклонены:
Планировщик дробных GPU в NVIDIA Run:ai создаёт короткоживущие поды резервирования в пространстве имён runai-reservation. На кластерах VKS этому пространству имён также требуется привилегированная метка, иначе поды резервирования будут отклонены PSA и дробные нагрузки не смогут запуститься:
Наконец, проверяется видимость ёмкости GPU кластера:
runai node list
runai nodepool list
# The node pool should show the expected GPU count under Allocated/Total GPUs
Дробные GPU в NVIDIA Run:ai
NVIDIA Run:ai позволяет нескольким нагрузкам делить один физический GPU, запрашивая долю вместо целого устройства. Ниже отправляются две задачи, каждая из которых запрашивает 50% GPU:
Проверка, что обе нагрузки перешли в Running и каждой выделено по 0,50 GPU:
runai training standard list -p <project-name>
# Workload Type Status Running/Req. Pods GPU Alloc.
# frac-half-1 Training Running 1/1 0.50
# frac-half-2 Training Running 1/1 0.50
Проверка того, что оба пода попали на один и тот же физический GPU, выполняется сравнением UUID устройства:
Совпадающие UUID подтверждают, что обе нагрузки используют одно и то же физическое устройство. Планировщик разместил их вместе, потому что каждая запросила лишь половину GPU, оставив остальные ускорители свободными для других задач.
Очистка:
runai training standard delete frac-half-1 -p <project-name>
runai training standard delete frac-half-2 -p <project-name>
Заимствование сверх квоты и справедливое распределение между департаментами
NVIDIA Run:ai организует ёмкость GPU в департаменты и проекты. У каждого департамента есть гарантированная квота GPU (deserved) и предел (limit). Deserved представляет гарантированный минимальный объём ресурсов, на который департамент или проект имеет право внутри пула узлов. Limit задаёт верхнюю границу для суммы гарантированной квоты и ресурсов сверх квоты. Когда GPU одного департамента простаивают, другие департаменты могут занимать их вплоть до своего предела (over-quota). Когда департамент-владелец отправляет работу, планировщик возвращает ёмкость через механизм справедливого распределения. В приведённом тесте создаются два департамента на одном кластере и демонстрируется заимствование сверх квоты.
Два департамента создаются через интерфейс NVIDIA Run:ai (Settings > Departments > New Department) либо через REST API. Каждый получает гарантированную квоту в 2 GPU и предел в 4:
Шаг 1: team-a отправляет четыре задачи, выходя за пределы своей квоты. Пока team-b простаивает, в кластере есть свободные GPU. Предел team-a, равный 4, позволяет занять вдвое больше её гарантированной квоты. В примере используется простая команда sleep 600, имитирующая занятие GPU нагрузками team-a на 10 минут, но в реальности это были бы настоящие обучающие скрипты команды или интерактивные сессии.
for i in 1 2 3 4; do
runai training standard submit overquota-a-$i \
-p team-a \
-i nvcr.io/nvidia/cuda:12.4.1-base-ubuntu22.04 \
-g 1 \
--command -- bash -c "nvidia-smi -L; sleep 600"
done
Шаг 2: team-b отправляет две задачи, забирая свою справедливую долю.
for i in 1 2; do
runai training standard submit fairshare-b-$i \
-p team-b \
-i nvcr.io/nvidia/cuda:12.4.1-base-ubuntu22.04 \
-g 1 \
--command -- bash -c "nvidia-smi -L; sleep 600"
done
Проверка распределения по проектам и департаментам:
runai project list
# Name Status Department GPU Quota Allocated GPUs GPU Allocation Ratio
# team-a Ready engineering 2.00 4.00 200.00%
# team-b Ready research 2.00 2.00 100.00%
runai department list
# Name GPU Quota Allocated GPUs GPU Allocation Ratio
# engineering 2.00 4.00 200.00%
# research 2.00 2.00 100.00%
Команда team-a находится на уровне 200% своей гарантированной квоты: она заняла два простаивающих GPU из общекластерного пула. Team-b находится на 100%, работая ровно в рамках своих прав. Задачи обоих департаментов выполняются одновременно, поскольку суммарной ёмкости кластера достаточно. Если бы team-b отправила дополнительные задачи, превышающие ёмкость кластера, планировщик вытеснил бы сверхквотные (вытесняемые) нагрузки team-a, чтобы вернуть GPU под гарантированную долю team-b.
Очистка:
for i in 1 2 3 4; do runai training standard delete overquota-a-$i -p team-a; done
for i in 1 2; do runai training standard delete fairshare-b-$i -p team-b; done
Тест инференса: небольшая языковая модель на vLLM
Небольшая модель с HuggingFace разворачивается через vllm/vllm-openai как нагрузка инференса NVIDIA Run:ai. Задача попадает в Knative Serving, получает стабильную конечную точку HTTPS и поддерживает масштабирование до нуля. В тесте используется Qwen/Qwen3-0.6B (открытая модель объёмом около 1,5 ГБ); её можно заменить любой моделью, помещающейся в память GPU.
Если узлы кластера не могут напрямую обращаться к huggingface.co (обычная ситуация в средах с межсетевым экраном), модель следует заранее загрузить на PVC и указать vLLM локальный путь через --existing-pvc и --model /models/<model-dir>. Если узлы имеют доступ к HuggingFace, аргумент --model принимает идентификатор модели HuggingFace напрямую, и vLLM загружает её при запуске.
Параметр --initialization-timeout-seconds 600 даёт vLLM время загрузить веса модели и скомпилировать графы CUDA при первом запуске. Значение --min-replicas 1 удерживает под «горячим»; после проверки его можно выставить в 0 для масштабирования до нуля.
Проверка того, что нагрузка достигла состояния Running с 1/1 подов:
runai inference list -p <project-name>
# Workload Type Status Running/Req. Pods GPU Alloc.
# qwen3-06b Inference Running 1/1-1 1.00
Проверка того, что модель загружена и обслуживает запросы:
Отправка запроса на завершение чата к конечной точке:
curl -sk https://qwen3-06b-runai-<project>.inference.<corp-domain>/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3-0.6B",
"messages": [{"role":"user","content":"What is VMware Cloud Foundation?"}],
"max_tokens": 64
}'
# A JSON response with "choices":[{"message":{"content":"..."}}] confirms the full
# inference path: Run:ai scheduling, GPU allocation, Knative Serving, Kourier
# routing through HAProxy, and TLS termination on the wildcard certificate.
Ответ в формате JSON с полем "choices":[{"message":{"content":"..."}}] подтверждает работу всего пути инференса: планирование Run:ai, выделение GPU, Knative Serving, маршрутизацию Kourier через HAProxy и терминацию TLS на wildcard-сертификате.
Можно также проверить конечную точку со списком моделей:
Тест рабочей среды: интерактивный JupyterLab на GPU
Отправляется рабочая среда JupyterLab с одним GPU. Флаг --external-url публикует порт 8888 через ingress NVIDIA Run:ai, благодаря чему блокнот доступен из браузера. NVIDIA Run:ai закрывает рабочую среду своим oauth2-proxy, поэтому доступ требует аутентификацAI через интерфейс NVIDIA Run:ai.
Отправляется настоящая задача обучения: небольшая свёрточная сеть обучается на наборе рукописных цифр MNIST в течение трёх эпох и выводит точность на тестовой выборке. В качестве базового образа используется контейнер NVIDIA PyTorch из NGC. Флаг --large-shm монтирует увеличенный /dev/shm, необходимый рабочим процессам DataLoader в PyTorch для межпроцессного взаимодействия через разделяемую память.
runai training standard submit mnist-train \
-p <project-name> \
-i nvcr.io/nvidia/pytorch:24.05-py3 \
-g 1 \
--large-shm \
--command -- python -c "
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import time
device = torch.device('cuda')
print(f'GPU: {torch.cuda.get_device_name(0)}')
print(f'CUDA version: {torch.version.cuda}')
print(f'PyTorch version: {torch.__version__}')
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
])
train_ds = datasets.MNIST('/tmp/data', train=True, download=True, transform=transform)
test_ds = datasets.MNIST('/tmp/data', train=False, transform=transform)
train_loader = DataLoader(train_ds, batch_size=256, shuffle=True, num_workers=2)
test_loader = DataLoader(test_ds, batch_size=1000, num_workers=2)
class Net(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.fc1 = nn.Linear(9216, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = torch.relu(self.conv1(x))
x = torch.relu(self.conv2(x))
x = torch.max_pool2d(x, 2)
x = torch.flatten(x, 1)
x = torch.relu(self.fc1(x))
return self.fc2(x)
model = Net().to(device)
optimizer = optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()
epochs = 3
for epoch in range(1, epochs + 1):
model.train()
t0 = time.time()
running_loss = 0.0
for data, target in train_loader:
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
loss = criterion(model(data), target)
loss.backward()
optimizer.step()
running_loss += loss.item()
elapsed = time.time() - t0
avg_loss = running_loss / len(train_loader)
print(f'Epoch {epoch}/{epochs} loss={avg_loss:.4f} time={elapsed:.1f}s')
model.eval()
correct = 0
total = 0
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
pred = model(data).argmax(dim=1)
correct += pred.eq(target).sum().item()
total += target.size(0)
accuracy = 100.0 * correct / total
print(f'Test accuracy: {correct}/{total} ({accuracy:.1f}%)')
print('MNIST training completed successfully')
"
Задача загружает набор данных MNIST (около 11 МБ, при недоступности yann.lecun.com используются зеркала на S3), обучает двухслойную свёрточную сеть оптимизатором Adam в течение трёх эпох, а затем оценивает результат на тестовой выборке из 10 тысяч примеров.
Проверка перехода задачи в состояние Completed:
runai training standard list -p <project-name>
# Workload Type Status Running/Req. Pods GPU Alloc.
# mnist-train Training Completed 0/1 0.00
Проверка того, что в журналах видны потери по эпохам, точность на тесте и успешное завершение:
Точность выше 98% после трёх эпох подтверждает корректную работу GPU, среды выполнения CUDA, фреймворка PyTorch и планировщика NVIDIA Run:ai. Если задача остаётся в состоянии Pending, следует проверить, есть ли у проекта свободная квота GPU (runai project list) и не заняты ли все GPU кластера другими нагрузками.
Очистка:
runai training standard delete mnist-train -p <project-name>
Мониторинг
После запуска платформы доступны три поверхности мониторинга, рассчитанные на разные аудитории и сценарии: интерфейс Run:ai для платформенных команд и исследователей, CLI runai для быстрых проверок в терминале и VCF Operations для инфраструктурных команд, управляющих ёмкостью GPU наряду с остальной средой VCF.
Дашборды интерфейса NVIDIA Run:ai
Интерфейс плоскости управления NVIDIA Run:ai — основной инструмент наблюдения за GPU-нагрузками. Он доступен по адресу https://runai.<corp-domain>/ и требует входа в NVIDIA Run:ai. Дашборды обновляются практически в реальном времени по данным DCGM и телеметрии планировщика, собираемым кластерным компонентом.
Обзорный дашборд. Обзорный дашборд открывается сразу после входа. Он показывает выделение GPU, утилизацию и количество нагрузок в масштабе всего кластера — по всем зарегистрированным кластерам, департаментам и проектам в одном представленAI. С его помощью можно с одного взгляда убедиться, что ёмкость GPU используется и ни один кластер не отключён.
Представление кластеров. Здесь перечислены все зарегистрированные кластеры со статусом подключения, количеством GPU и версией. Переход внутрь кластера показывает распределение GPU и состояние по каждому узлу.
Представление узлов. Это разбивка по узлам с типом GPU, распределением и утилизацией. Видно, какие GPU простаивают, какие заняты частично (дробно), а какие израсходованы полностью.
Представление нагрузок. Центральная таблица всех активных, ожидающих и завершённых нагрузок по всем проектам. В каждой строке отображаются тип нагрузки (Training, Inference, Workspace), статус, выделение GPU, проект и время отправки. Клик по нагрузке открывает её поды, события, потребление ресурсов и журналы.
Департаменты и проекты. Представление Departments показывает квоту GPU, выделение и коэффициент утилизацAI по каждому департаменту. Представление Projects раскрывает отдельные проекты внутри департамента. Эти представления служат эксплуатационным подтверждением поведения сверх квоты и справедливого распределения, проверенного в соответствующем тесте.
Метрики утилизации GPU. Это представление позволяет перейти к любому узлу или нагрузке и увидеть метрики DCGM по каждому GPU: утилизацию вычислений, утилизацию памяти, использованную и свободную память, температуру, частоту SM, а также утилизацию кодировщика и декодировщика. Это те же метрики DCGM Exporter, которые собирает кластерный Prometheus NVIDIA Run:ai, отрисованные в интерфейсе без дополнительной настройки.
Метрики уровня нагрузки. Достаточно выбрать любую нагрузку в представлении Workloads и открыть вкладку Metrics в боковой панели. Для задач обучения и рабочих сред интерфейс показывает утилизацию GPU, использование памяти GPU, загрузку CPU и потребление оперативной памяти во времени для каждого пода. Для нагрузок инференса вкладка Metrics дополнительно отображает пропускную способность (запросов в секунду) и перцентили задержки на основе телеметрии Knative и vLLM.
Журналы нагрузок в интерфейсе. Выбрав нагрузку и открыв вкладку Logs в боковой панели, можно в реальном времени читать журналы контейнеров её подов. Выпадающий список контейнеров позволяет переключаться между ними (user-container для основной нагрузки, sidecar-контейнеры для агентов NVIDIA Run:ai). Журналы доступны для работающих, завершённых и завершившихся с ошибкой нагрузок, пока под не удалён сборщиком мусора.
CLI NVIDIA Run:ai
CLI runai предоставляет ту же информацию, что и интерфейс, но в удобном для терминала виде. Эти команды полезны для скриптов, быстрых проверок и сред, где доступ через браузер отсутствует.
Состояние кластера и узлов:
runai node list
# Name Status GPU Type Allocated/Total GPUs Free GPUs Nodepool
# runai-vks-runai-vks-np-cwc8-2fhqw-z4hj7-772gs Ready NVIDIA-H100XM-80C 4/4 0 default
# runai-vks-runai-vks-np-cwc8-2fhqw-z4hj7-f2b8w Ready NVIDIA-H100XM-80C 4/4 0 default
# runai-vks-zfbzr-qqwhq Ready N/A N/A N/A default
# runai-vks-zfbzr-sbv5s Ready N/A N/A N/A default
# runai-vks-zfbzr-wpnzg Ready N/A N/A N/A default
runai nodepool list
# Name Status Allocated/Total GPUs Nodes MNNVL detection Network Topology
# default Ready 8/8 5 Not Detected
Распределение по департаментам и проектам:
runai department list
# Name GPU Quota Allocated GPUs GPU Allocation Ratio
# research 2.00 3.00 150.00%
# engineering 2.00 4.00 200.00%
# default -1.00 1.00 0.00%
runai project list
# Name Status Department GPU Quota Allocated GPUs GPU Allocation Ratio
# team-a Ready engineering 2.00 4.00 200.00%
# team-b Ready research 2.00 3.00 150.00%
# test Ready default 2.00 1.00 50.00%
И engineering, и research превышают свои гарантированные квоты (200% и 150% соответственно), заимствуя простаивающие GPU из общекластерного пула. Департамент default показывает неограниченную квоту (-1.00), а проект test выполняет нагрузку инференса.
Состояние нагрузок:
runai training standard list -p team-a
# Workload Type Status Running/Req. Pods GPU Alloc.
# overquota-a-1 Training Running 1/1 1.00
# overquota-a-2 Training Running 1/1 1.00
# overquota-a-3 Training Running 1/1 1.00
# overquota-a-4 Training Running 1/1 1.00
runai training standard list -p team-b
# Workload Type Status Running/Req. Pods GPU Alloc.
# fairshare-b-1 Training Running 1/1 1.00
# fairshare-b-2 Training Running 1/1 1.00
# frac-half-1 Training Running 1/1 0.50
# frac-half-2 Training Running 1/1 0.50
runai inference list -p test
# Workload Type Status Running/Req. Pods GPU Alloc.
# qwen3-06b Inference Running 1/1-1 1.00
runai inference describe qwen3-06b -p test
# Name: qwen3-06b
# Type: Inference
# Phase: Running
# Project: test
# Department: default
# Image: vllm/vllm-openai:latest
# ...
# Serving
# Minimum Replicas: 1
# Maximum Replicas: 1
# ...
# Network
# URL: https://qwen3-06b-runai-test.runai-inference.<corp-domain>
# ...
# Pods
# Running Pods: 1/1
Журналы нагрузок из CLI. CLI runai поддерживает подкоманду logs для каждого типа нагрузок, однако в средах, где TLS-сертификат cluster-api подписан частным УЦ, CLI может отклонить соединение. В таком случае следует обратиться напрямую к поду нагрузки через kubectl logs:
Журналы обучающих нагрузок показывают вывод цикла нагрузки GPU со счётчиком итераций и потреблением памяти. Журналы инференса демонстрируют, как vLLM обрабатывает входящие запросы с ответами HTTP 200. Это те же самые журналы, что видны на вкладке Logs в интерфейсе.
VCF Operations
VCF Operations может наблюдать за кластерами VKS, на которых работают нагрузки NVIDIA Run:ai, показывая метрики уровня Kubernetes (состояние узлов, количество подов, потребление ресурсов контейнерами) рядом с существующей телеметрией vSphere, NSX и vSAN. Инфраструктурные команды получают единое представление о состоянии GPU-кластера без входа в интерфейс NVIDIA Run:ai.
Настройка требует трёх компонентов:
Сервис Supervisor Management Proxy на Supervisor.
Стандартные пакеты Telegraf и Prometheus для VKS на каждом кластере VKS.
Включённый переключатель Pod And Container Monitoring в VCF Operations.
Пакет Telegraf содержит встроенный входной плагин DCGM Exporter, который можно включить в его data values, чтобы передавать метрики GPU через конвейер прокси Supervisor. Полная процедура установки описана в следующих материалах:
Дашборд кластера VKS. После включения мониторинга и начала поступления метрик (нужно подождать 10–15 минут) встроенный дашборд Kubernetes VKS Cluster в VCF Operations показывает состояние узлов, количество подов, утилизацию ресурсов контейнерами и статус нагрузок для каждого отслеживаемого кластера VKS.
Дашборды Private AI. VCF Operations включает набор встроенных дашбордов Private AI в разделе Dashboards > Private AI, которые дают ориентированные на GPU представления инфраструктуры без какой-либо дополнительной настройки, кроме адаптера vSphere Supervisor:
GPU Overview: сводное представление всех ресурсов GPU в среде VCF, включая общее количество GPU, состояние распределения и тренды утилизации.
GPU Providers: разбивка оборудования GPU по хостам — какие хосты ESXi оснащены GPU, модель GPU, версия драйвера и текущее назначение (проброс, профиль vGPU или свободно).
GPU Consumers: сопоставление назначений GPU с виртуальными машинами и рабочими узлами VKS, которые их потребляют, со связкой профилей vGPU или проброшенных устройств с конкретными нагрузками.
GPU Equipped Clusters: показывает, в каких кластерах vSphere есть хосты с GPU, и их совокупную ёмкость GPU.
Эти дашборды работают на уровне vSphere и отражают инвентарь GPU-оборудования, назначение профилей vGPU и утилизацию на уровне хостов. Они дополняют метрики GPU уровня нагрузок в NVIDIA Run:ai, давая инфраструктурным командам видимость физической топологAI GPU, состояния драйверов и данных для планирования ёмкости — того слоя, что лежит ниже Kubernetes и NVIDIA Run:ai.
Заключение
Рассмотренное сквозное развёртывание NVIDIA Run:ai на VCF с Private AI Foundation with NVIDIA свелось к следующему порядку действий:
Установить self-hosted плоскость управления на кластере VKS.
Подключить один или несколько кластеров AI Kubernetes Cluster с GPU, созданных из каталога VCF Automation.
Настроить Knative Serving для инференса.
Проверить работоспособность на реальных нагрузках.
Интегрировать мониторинг между поверхностями NVIDIA Run:ai и VCF Operations.
NVIDIA Run:ai включён в каждый набор прав NVIDIA AI Enterprise. Для заказчиков VCF, которые уже используют Private AI Foundation with NVIDIA, это означает, что слой планирования GPU и оркестрации нагрузок перестаёт быть отдельным решением о закупке: он поставляется вместе со стеком, которым они уже владеют.