- Added support for balance tracking using `SELECTEL_API_TOKEN` in the configuration. - Introduced new balance notification logic in the local watchdog, alerting users on balance changes based on defined thresholds. - Updated documentation to include instructions for setting up balance notifications and the required environment variables. - Enhanced the `ready` and `session` modules to initialize balance state and handle notifications during GPU operations. - Refactored the CLI and related components to support the new balance monitoring features, ensuring a seamless user experience.
12 KiB
Контракт с Selectel
Ниже — то, на что опирается код. Не выдуманные URL и не «примерно OpenStack».
Иерархия размещения
| Термин | Пример | Смысл |
|---|---|---|
| Аккаунт | число в углу панели | Domain в Keystone (OS_USER_DOMAIN_NAME) |
| Проект | uuid / имя | Scope токена |
| Пул (region) | ru-7, ru-9 |
Куда ходит compute API: https://<pool>.cloud.api.selcloud.ru/compute/v2.1/ |
| Сегмент пула (AZ) | ru-7a, ru-9a |
Куда ставятся VM и диски. Должны совпадать |
SELECTEL_REGION=ru-1 из старого черновика недостаточно. Flavor, image, volume type (fast.ru-7a) и availability zone берутся из одного сегмента. Диск из ru-7a нельзя приаттачить к VM в ru-9a.
GPU есть не во всех сегментах. Перед create — матрица доступности GPU и живой flavor list в выбранном AZ.
Авторизация
Статический API-ключ панели (X-Token) не управляет объектами OpenStack (серверы, диски, сети).
Исключение: баланс аккаунта (GET https://api.selectel.ru/v3/balances) — как раз через X-Token. Для уведомлений о списании положи SELECTEL_API_TOKEN в .env и поставь gpu-rent watchdog install (см. cli.md).
Нужен сервисный пользователь с правом на проект.
- CLI хранит: account id, username, password, project id/name, pool, pool segment.
- Запрос токена:
POST https://cloud.api.selcloud.ru/identity/v3/auth/tokens(password + project scope). - Заголовок ответа
X-Subject-Token— IAM-токен. TTL 24 часа. - Дальнейшие вызовы:
X-Auth-Tokenна endpoints из service catalog (compute, volume, network, image).
Токен нельзя один раз прописать в .env и забыть. Клиент обновляет его до истечения. Совпадение «24 часа токена» и «24 часа preemptible» легко пропустить: длинная сессия умрёт с 401, VM при этом останется.
Учётные данные сервисного пользователя — секрет. Роль — только нужный проект (compute + block storage + networking), не владелец аккаунта.
Практичный клиент: openstacksdk.Connection с теми же полями, что в RC-файле панели (OS_AUTH_URL, OS_PROJECT_ID, OS_USERNAME, OS_PASSWORD, OS_USER_DOMAIN_NAME, OS_REGION_NAME).
GPU
Актуальный список в панели и в документации Selectel. Для генерации картинок из черновика плана:
| В старом плане | В облаке Selectel |
|---|---|
| RTX 3090 | нет |
| RTX 4090 | 24 GB и 48 GB |
| A100 40 GB | есть |
Ближайшие бытовые аналоги 3090: A5000 (как 3080, 24 GB) или RTX 4090 24 GB.
Фиксированный flavor связывает GPU + vCPU + RAM. Три независимых вопроса «какая карта / сколько RAM / сколько CPU» допустимы только если CLI создаёт custom GPU flavor через Compute API (gpu: "4090:1" и т.п.). Для MVP — живой список фиксированных flavors в сегменте.
Custom GPU flavor создаётся только через API, не через openstack flavor create в CLI, и живёт в конкретном пуле/проекте.
Фоллбек, если предпочтительный GPU занят
Квота «есть GPU» ≠ flavor свободен в сегменте. up идёт по списку предпочтений (FLAVOR_PREFERENCE), не падает на первом disabled / нет capacity.
Дефолт (подстроки в имени или extra spec, живые id — из flavor list на spike):
- RTX 4090 24 GB
- RTX 4090 48 GB
- A5000
- A100 40 GB
Поведение:
- Предпочтительный доступен — берём его, печатаем ₽/час.
- Нет — показать следующий доступный из списка с ценой и отличием (VRAM / ₽). Интерактив: подтвердить.
--yes— взять первый доступный из списка без вопроса, цену всё равно напечатать. - Ни один из списка не доступен — стоп с текстом «нет GPU в сегменте», не молчаливый CPU-flavor.
- Явный
--flavor <id>бьёт список: нет этого id → ошибка, без автофоллбека.
Образы
Не ставить драйверы NVIDIA руками на каждом boot и не брать Windows.
Канонический boot-образ:
Ubuntu 24.04 LTS 64-bit GPU Driver 580
Без слова Docker в имени. SwarmUI и Comfy крутятся на хосте (launch-linux.sh, systemd), не в контейнере.
| Вариант | Почему нет |
|---|---|
| Тот же образ с Docker | Лишний слой, nvidia-ctk, docker build на первом bootstrap. Для одной VM не нужен |
| Windows Server | Лицензия, хуже стек под SwarmUI/Comfy |
| Ubuntu без «GPU optimized» | Сами ставите драйвер + kernel pin — съедает preempt-часы |
| Ubuntu 22.04 GPU | Работает, но старше ядро |
| Driver 535 | Для 4090/свежего PyTorch лучше host driver 580 |
| Data Science / Analytics VM | Jupyter/conda, 22.04, ядро не так же pinned |
Фоллбек, если в Glance пула нет 580: Ubuntu 24.04 LTS 64-bit GPU Driver 535 (тоже без Docker). Образ «… Docker» — только если не-Docker GPU-образа в пуле нет; doctor предупредит.
Имена уточнять через Glance (image list) — id плавают, в git не класть. Ядро уже pinned: apt upgrade ядра ломает nvidia-smi. Не трогать linux-image-* / nvidia-* в unattended-upgrades.
Образ без GPU optimization = сами ставите драйверы, это не наш путь.
Прерываемые серверы
Документация: preemptible servers, create, restore.
- Создаются тегом
preemptibleи микроверсией compute 2.72 (openstack server create --tag preemptible --os-compute-api-version 2.72). - Могут быть остановлены в любой момент в пределах 24 часов после create или restore.
- При прерывании сервер не удаляется, статус
EXPIRED. - Restore:
openstack server unshelve <server>. После restore снова preemptible, снова 24 часа. - Сетевой boot-диск: VM поднимается в том состоянии, в каком остановилась.
- Локальный диск: данные ОС/локали теряются, создаётся новая VM из исходного образа.
- SLA облака на preemptible не действует.
- После остановки GPU/CPU/RAM не тарифицируются со следующего часа; сетевые диски и публичные IP — тарифицируются.
Watchdog, который ждёт SHUTOFF_BY_HOST и делает delete+create, к Selectel не применим.
Сеть
Минимальный набор, которого не было в черновике:
- Приватная сеть + subnet.
- Router с gateway на внешнюю сеть.
- Port VM в приватной сети.
- Security group (если на сети включён port security: без группы трафик запрещён).
- Floating IP (или порт в public subnet) + association.
- Keypair (публичный ключ пользователя), заведённый на того же сервисного пользователя / проекта.
Сеть и router создаются один раз и переиспользуются. Floating IP либо переиспользовать (платим между сессиями), либо выделять на up и удалять на stop.
Ingress SG: TCP/22 с адреса оператора. 7801 снаружи не открывать.
Диски
- Сетевой диск создаётся в том же сегменте, тип вида
fast.ru-9a(точное имя —volume type list). - Boot: из GPU-образа,
delete_on_termination=false. - Data: пустой, подключается вторым блочным устройством в том же
server create, не отдельным attach после ACTIVE (гонка с cloud-init). - Удалить VM с приаттаченным диском в OpenStack часто нельзя: detach → wait → delete, либо delete server с корректным BDM.
- Online resize вверх у Selectel есть; вниз — нет. Заложить команду увеличения data-диска, не «создать новый на 100 GB и надеяться».
- После первого удачного bootstrap (backend Idle) — один snapshot boot volume
gpu-rent-boot-ok, если его ещё нет. Следующий create может идти из snapshot, не из сырого GPU-образа. Каждыйupновый snapshot не плодит. Attached snapshot в OpenStack допустим для v1 (без fsfreeze).
Путь устройства в Linux: чаще virtio (/dev/vdb), не scsi-0Selectel_Volume_<uuid>. Определять по serial/by-id после проверки, не хардкодить SCSI-имя из другого провайдера.
Квоты и лимиты
На новых аккаунтах квота GPU часто 0. Preflight до create:
- квота compute/GPU;
- наличие flavor в сегменте (
OS-FLV-DISABLED:disabled, extra specs); - баланс / возможность создать ресурс (ошибка 402/403 — понятное сообщение, не traceback).
Письмо в поддержку — ручной шаг один раз, не часть CLI.
Теги и имена ресурсов
Чтобы reconcile нашёл сирот без локального state:
- сервер: имя
gpu-rent(илиgpu-rent-<short>), тегиgpu-rent,preemptible; - диски:
gpu-rent-boot,gpu-rent-data; - snapshot boot:
gpu-rent-boot-ok(один, не на каждыйup); - SG / сеть:
gpu-rent, если создаём сами.
Не плодить вторую сеть на каждый up.