Files
gpu-rent/docs/selectel.md
T
Leonid PershinandCursor 789fa26918 Pick cheapest GPU SKU and pin the VM to an existing disk AZ.
Scan ru-6 by Nova availability zones (a/b/c). First boot uses FLAVOR_SIZE_PRESET=cheap; reruns stay on the disk segment.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-22 00:06:44 +03:00

159 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Контракт с 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](https://docs.selectel.ru/en/cloud-servers/create/gpus/) и живой `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.md)).
Нужен **сервисный пользователь** с правом на проект.
1. CLI хранит: account id, username, password, project id/name, pool, pool segment.
2. Запрос токена: `POST https://cloud.api.selcloud.ru/identity/v3/auth/tokens` (password + project scope).
3. Заголовок ответа `X-Subject-Token` — IAM-токен. TTL **24 часа**.
4. Дальнейшие вызовы: `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):
1. RTX 4090 24 GB
2. RTX 4090 48 GB
3. A5000
4. A100 40 GB
Поведение:
- Предпочтительный доступен — берём самый дешёвый SKU этого типа (`FLAVOR_SIZE_PRESET=cheap`: 1×GPU, min vCPU/RAM, без локального диска). Печатаем ₽/час из панели (в API нет).
- Диски уже есть — сегмент зафиксирован (диск из `ru-6a` нельзя прицепить к VM в `ru-6b`). Flavor только из этого AZ.
- Первый запуск (дисков нет) — сегмент, где есть карта из `FLAVOR_PREFERENCE` (4090 ≈ `ru-6a` / `ru-7b`, не `ru-6b/c`).
- Нет — показать следующий доступный из списка с отличием (VRAM / размер). Интерактив: пресет размера + номер flavor. `--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](https://docs.selectel.ru/en/cloud-servers/about/preemptible-servers/), [create](https://docs.selectel.ru/en/cloud-servers/create/create-preemptible-server/), [restore](https://docs.selectel.ru/en/cloud-servers/manage/restore-preemptible-server/).
- Создаются тегом `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 не применим.
## Сеть
Минимальный набор, которого не было в черновике:
1. Приватная сеть + subnet.
2. Router с gateway на внешнюю сеть.
3. Port VM в приватной сети.
4. Security group (если на сети включён port security: без группы трафик **запрещён**).
5. Floating IP (или порт в public subnet) + association.
6. 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`.