Окружение в production

Окружение — запись каталога с именем и immutable digest образа ядра. Занятие сохраняет выбранную ревизию. Изменение окружения по умолчанию или выпуск нового образа не меняют Python уже созданного занятия.

Панель «Окружения» показывает доступные ревизии и позволяет выбрать окружение по умолчанию для новых занятий. Если закреплённая ревизия недоступна, запуск завершается ошибкой; сервер не заменяет её случайным текущим образом.

Добавьте библиотеки

  1. Измените требования окружения в kernel/environments/. Директива # colloq: from NAME задаёт наследование, # colloq: python 3.12 — версию Python: от 3.10 до 3.13; по умолчанию берётся версия из ARG PARENT в kernel/Dockerfile, сейчас 3.11. Версию задаёт корень цепочки наследования: слой поверх готового образа ставит колёса под тот интерпретатор, который пришёл из базы, и заменить его не может, поэтому окружение с from, просящее другую версию, к сборке не принимается. Директива # colloq: gpu делает окружение GPU-окружением, и окружения, унаследованные от него через from, получают этот признак автоматически. Если в выпуске есть такое окружение, параметры --gpu-toolkit-version и --gpu-device-plugin-image при сборке обязательны. Для pip все эти строки — комментарии.
  2. Зафиксируйте исходный коммит и подготовьте новый выпуск на доверенной машине сборки или через release CI.
  3. Опубликуйте образы и каталог с реальными digest.
  4. Установите выпуск и проверьте импорт и типовую задачу из занятия.

Production не собирает образ из веб-запроса и не получает Docker socket. Описание пакетов отражает запрошенные зависимости, а не полный pip lock: повторная сборка диапазонов версий может дать другой образ. Установленный digest при этом остаётся неизменным.

Сборка выпуска сопровождающим

Workflow Publish immutable release принимает тег версии и точный проверенный patch k3s, собирает выбранные окружения и прикладывает манифест, архив инструментов и суммы. Альтернатива — локальный scripts/release-build.py. Пример со значениями, которые нужно заменить:

python3 scripts/release-build.py --version YOUR_VERSION_TAG \
  --registry YOUR_REGISTRY_PREFIX --source-commit FULL_COMMIT_SHA \
  --k3s-version EXACT_TESTED_K3S_VERSION --environments base,cv

Для GPU дополнительно укажите --gpu-toolkit-version EXACT_NVIDIA_APT_VERSION и --gpu-device-plugin-image NVIDIA_PLUGIN_IMAGE_AT_SHA256. Авторизуйтесь в registry на машине сборки. Версия k3s нужна v1.33 или новее: память комнаты меняется во время занятия через подресурс pods/resize, и проверка манифеста отвергает более старую. Публикация артефактов сама по себе не является проверкой на целевой VM.

Память и процессор занятия

Раздел «Ресурсы» есть в форме нового занятия и в настройках существующего (меню занятия → «Настройки»). Поле «Память ядра комнаты, ГБ» меняется с шагом 0,5 ГБ: от 0,5 ГБ до памяти машины за вычетом 1 ГБ. Поле «Процессор, ядер» принимает целое число от 1 до числа ядер машины. Чтобы вернуть общее значение, очистите поле или нажмите «вернуть умолчание окружения» либо «вернуть умолчание инстанса».

Подсказка под полем показывает объём памяти, свободную память и умолчание выбранного окружения. Если Docker работает в собственной виртуальной машине, как Docker Desktop или Colima на macOS, подсказка начинается словами «Комнаты живут в Docker». Тогда объём, число ядер и верхнюю границу полей задаёт Docker, а не компьютер. Свободной считается память Docker за вычетом 1 ГБ и лимитов уже работающих комнат. Если свободную память узнать нельзя, подсказка её не показывает. Лимит больше свободной памяти форма не запрещает, но предупреждает, что ядро может не подняться. У работающей комнаты со свободной памятью сравнивается только прибавка к тому, что у неё уже есть. Если на машине есть видеокарта NVIDIA, раздел показывает её и то, использует ли карту выбранное окружение. Видеопамять не ограничивается: её делят все комнаты на карте.

В Docker новый лимит памяти применяется к работающему ядру сразу, без перезапуска; возврат к умолчанию окружения вступит в силу при следующем запуске контейнера комнаты. Новое число ядер тоже применяется к работающему ядру сразу, без перезапуска, — и возврат к умолчанию инстанса тоже. Число потоков numpy и torch (OMP_NUM_THREADS и соседние переменные) задаётся при создании контейнера комнаты и живому контейнеру уже не меняется, даже перезапуском ядра: перезапущенное ядро наследует окружение того же контейнера. Новое число потоков получит следующий контейнер комнаты — например, когда комната простоит пустой два часа и её откроют снова. До тех пор число потоков можно поднять прямо в тетради: threadpoolctl.threadpool_limits(n) для numpy и scikit-learn, torch.set_num_threads(n) для torch. Без KERNEL_MEM умолчание — 4 ГБ, для GPU-окружения — 16 ГБ. KERNEL_MEM задаёт умолчание для всех окружений, KERNEL_MEM_<ОКРУЖЕНИЕ> — для одного (например, KERNEL_MEM_BASE_GPU=16g), KERNEL_CPUS — число ядер (по умолчанию 2). Файл .env, который создаёт colloq start, уже содержит KERNEL_MEM=4g. Как это устроено в k3s-установке, описано ниже.

Ресурсы комнаты

В k3s-установке Pod комнаты по умолчанию получает 2Gi памяти, 2 CPU и 2Gi ephemeral storage; requests равны limits. Память и число CPU из раздела «Ресурсы» занятия доходят до Pod, и их можно поднять или опустить во время занятия: брокер меняет их работающему Pod на месте, ядро не перезапускается, переменные остаются. Кнопки «вернуть умолчание окружения» и «вернуть умолчание инстанса» тоже действуют сразу. Число потоков numpy и torch Pod получает от своего лимита CPU при запуске и, как в Docker, живому ядру его уже не меняет — ни после изменения на месте, ни после перезапуска ядра; новое число получит следующий Pod комнаты. Умолчание брокера одно для всех окружений, включая GPU, — его и показывает подсказка формы. Верхняя граница поля — память узла за вычетом 1 ГБ. Умолчание и потолок задают переменные брокера RUNTIME_KERNEL_MEMORY и RUNTIME_KERNEL_MEMORY_MAX: их пишут в тот же instance.env, что и настройки приложения (см. конфигурацию установки), например RUNTIME_KERNEL_MEMORY=4Gi. Значения — целые Mi или Gi от 64Mi до 256Gi, потолок не ниже умолчания; установщик проверяет их до остановки комнат и сохраняет при обновлениях. Изменение на месте требует Kubernetes 1.33 или новее, и выпуск с более старым k3s не проходит проверку. Это пределы ресурсов, а не обещание определённого числа студентов или скорости обучения модели.

Память и ядра комнаты резервируются целиком, даже если Python их не трогает. Поэтому свободной подсказка считает память узла за вычетом 1 ГБ и памяти, уже отданной работающим комнатам. Если узлу сейчас нечем покрыть прибавку памяти или ядер, новое значение сохраняется и ждёт: Kubernetes применит его сам, когда ресурс освободится, например когда остановится соседняя комната. Больше, чем узел может дать вообще, брокер не выставляет: работающий Pod остаётся с прежним значением. Новой комнате ждать негде: если узлу нечем покрыть её память, процессор или видеокарту, через 20 секунд подъём останавливается. Преподаватель видит в комнате, сколько она просила и что уменьшить или закрыть; студенты — короткое сообщение, что Python сейчас не запускается и преподаватель видит причину. Если коду не хватило памяти, в k3s завершается весь Pod комнаты, а не только ядро, как в Docker; следующий запуск кода поднимает новый Pod, уже с новым значением памяти.

Память /dev/shm входит в лимит Pod: по умолчанию 64 MiB у CPU-окружения и 1 GiB у GPU. Установщик задаёт лимит 256 PID на Pod. Namespace ResourceQuota и дополнительные правила допуска нагрузки оператор настраивает отдельно; готовой ResourceQuota в комплекте нет. Для workspace нет принудительной покомнатной файловой квоты; следите за отдельным файловым разделом и свободным местом.

GPU-окружения

Каждая GPU-комната запрашивает один nvidia.com/gpu и RuntimeClass nvidia. Совместное использование устройства не включается автоматически. Несколько одновременных GPU-комнат требуют соответствующего числа доступных устройств либо отдельно спроектированной и проверенной политики sharing.

Установщик сохраняет драйвер хоста, ставит закреплённые NVIDIA Container Toolkit и device plugin и проверяет реальную PyTorch CUDA-операцию. Для проверки нужен свободный GPU; занятая карта не отбирается у действующего занятия.

sudo scripts/cluster.sh gpu-preflight
sudo k3s kubectl get nodes \
  -o "custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu"

Обычная доступность приложения не доказывает GPU-готовность. Если карта не выделяется или CUDA не работает, разберите причину до начала занятия.

Сохраняйте старые образы

Исторические ревизии каталога сохраняются, пока на них ссылаются комнаты. Не удаляйте соответствующие образы из registry. Резервная копия приложения содержит каталог и digest, но не слои образов.