# Контракт с Selectel Ниже — то, на что опирается код. Не выдуманные URL и не «примерно OpenStack». ## Иерархия размещения | Термин | Пример | Смысл | | --- | --- | --- | | Аккаунт | число в углу панели | Domain в Keystone (`OS_USER_DOMAIN_NAME`) | | Проект | uuid / имя | Scope токена | | Пул (region) | `ru-7`, `ru-9` | Куда ходит compute API: `https://.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 (серверы, диски, сети). Нужен **сервисный пользователь** с правом на проект. 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 Поведение: - Предпочтительный доступен — берём его, печатаем ₽/час. - Нет — показать следующий доступный из списка с ценой и отличием (VRAM / ₽). Интерактив: подтвердить. `--yes` — взять первый доступный из списка без вопроса, цену всё равно напечатать. - Ни один из списка не доступен — стоп с текстом «нет GPU в сегменте», не молчаливый CPU-flavor. - Явный `--flavor ` бьёт список: нет этого 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 `. После 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_`. Определять по 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-`), теги `gpu-rent`, `preemptible`; - диски: `gpu-rent-boot`, `gpu-rent-data`; - snapshot boot: `gpu-rent-boot-ok` (один, не на каждый `up`); - SG / сеть: `gpu-rent`, если создаём сами. Не плодить вторую сеть на каждый `up`.