JupyterHub для AI/ML: настройка, GPU-квоты и интеграция с MLflow
Работа над ML-проектами в команде часто упирается в проблему «а у меня всё работает, а на сервере — нет». Разные версии библиотек, отсутствие GPU, несинхронизированные датасеты — хаос, который убивает продуктивность. JupyterHub с Kubernetes решает это на уровне инфраструктуры. Мы настроили десятки таких сред для команд от 3 до 50 человек и знаем все подводные камни. Один из клиентов — компания, разрабатывающая NLP-модели: 12 инженеров тратили до 4 часов в неделю на синхронизацию окружений. После внедрения JupyterHub это время сократилось до нуля. Под ключ — от выбора образов до интеграции с MLflow — за 5 рабочих дней. Оценим ваш проект бесплатно, свяжитесь с нами.
Проблемы, которые решаем
- Несовместимость окружений. Каждый разработчик использует свои версии пакетов. JupyterHub предоставляет единый Docker-образ с фиксированными зависимостями. Это исключает ситуации "на моей машине работает".
- Дефицит GPU. Без квот один пользователь может занять все ресурсы, оставив коллег без вычислительной мощности. ResourceQuota и PriorityClass распределяют GPU честно, а PriorityClass гарантирует, что production-задачи не вытесняются исследовательскими.
- Дублирование данных. Датасеты копируются на каждую машину — это тратит место и время на синхронизацию. Общая PVC в read-only режиме решает проблему: последняя версия датасета доступна всем пользователям в /data/shared.
Почему JupyterHub лучше отдельных серверов?
| Критерий | JupyterHub (Kubernetes) | Отдельные серверы |
|---|---|---|
| Воспроизводимость | Одинаковый образ для всех | Ручная установка зависимостей |
| Управление GPU | Квоты, приоритеты, мониторинг | Нет централизованного контроля |
| Безопасность | Изоляция через Kubernetes Namespaces | Общий доступ к файлам |
| Масштабирование | Автомасштабирование подов | Ручное добавление машин |
Как мы настраиваем GPU-квоты?
Для справедливого распределения GPU мы используем ResourceQuota на namespace и PriorityClass для приоритизации задач. Пример конфигурации:
apiVersion: v1 kind: ResourceQuota metadata: name: jhub-quota spec: hard: requests.nvidia.com/gpu: "8" # Максимум 8 GPU одновременно limits.memory: "512Gi" requests.cpu: "64" PriorityClass для GPU: исследовательские задачи имеют низкий приоритет, production-инференс — высокий. Это предотвращает блокировку критичных процессов.
Как интегрировать JupyterHub с MLflow?
Стек: Kubernetes (EKS/GKE), Helm, Docker, PyTorch 2.2, MLflow 2.11, DVC, Great Expectations.
# Добавление Helm репозитория helm repo add jupyterhub https://hub.jupyter.org/helm-chart/ helm repo update # config.yaml cat > config.yaml << 'EOF' hub: config: Authenticator: admin_users: - admin GitHubOAuthenticator: client_id: "your-github-client-id" client_secret: "your-github-client-secret" oauth_callback_url: "https://jupyter.company.com/hub/oauth_callback" allowed_organizations: - your-github-org singleuser: image: name: jupyter/datascience-notebook tag: "python-3.11" profileList: - display_name: "CPU Standard (4 CPU, 16GB RAM)" description: "For EDA and light training" default: true - display_name: "GPU Instance (1x A100 40GB)" description: "For model training" kubespawner_override: extra_resource_limits: nvidia.com/gpu: "1" - display_name: "GPU Large (2x A100 80GB)" kubespawner_override: extra_resource_limits: nvidia.com/gpu: "2" storage: capacity: 50Gi homeMountPath: /home/jovyan # Общее хранилище для датасетов (read-only для пользователей) singleuser: extraVolumes: - name: shared-datasets persistentVolumeClaim: claimName: shared-datasets-pvc readOnly: true extraVolumeMounts: - name: shared-datasets mountPath: /data/shared readOnly: true EOF helm install jupyterhub jupyterhub/jupyterhub \ --namespace jhub --create-namespace \ --values config.yaml Подробнее о настройке читайте в официальной документации Zero to JupyterHub.
Профили ресурсов детализированы в таблице: | Профиль | CPU | RAM | GPU | Хранилище | |---------|-----|-----|-----|-----------| | CPU Standard | 4 vCPU | 16 GB | – | 50 GB | | GPU Instance | 4 vCPU | 32 GB | 1× A100 40GB | 100 GB | | GPU Large | 8 vCPU | 64 GB | 2× A100 80GB | 200 GB |
Кастомные Docker-образы для ML
FROM jupyter/datascience-notebook:python-3.11 USER root RUN apt-get update && apt-get install -y \ libgomp1 \ && rm -rf /var/lib/apt/lists/* USER ${NB_UID} # ML dependencies RUN pip install --no-cache-dir \ torch==2.2.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 \ transformers==4.38.0 \ datasets \ accelerate \ peft \ mlflow==2.11.0 \ dvc[s3] \ great_expectations \ lightgbm xgboost catboost \ optuna \ shap \ wandb # MLflow tracking server URL ENV MLFLOW_TRACKING_URI=http://mlflow.internal:5000 # DVC remote config COPY dvc_config /home/jovyan/.dvc/config MLflow автоматически доступен из всех notebooks через переменную окружения. DVC настроен с корпоративным remote storage. Shared dataset папка с последними версиями датасетов монтируется read-only. Git pre-commit hooks установлены глобально для стандартизации кода.
Типичный результат: ML-команда из 10+ человек работает в унифицированной среде без "works on my machine" проблем, с общим доступом к GPU-ресурсам и централизованным трекингом экспериментов. Это существенно сокращает расходы на вычислительные ресурсы за счёт утилизации GPU.
Процесс работы
- Аналитика — изучаем текущую инфраструктуру, требования к GPU, объём данных.
- Проектирование — разрабатываем архитектуру: namespace, образы, квоты.
- Реализация — развёртываем JupyterHub через Helm, настраиваем аутентификацию.
- Интеграция — подключаем MLflow, DVC, shared storage.
- Тестирование — проверяем сценарии: запуск обучения, логирование, доступ к данным.
- Обучение команды — проводим воркшоп, передаём документацию.
Что входит в работу
| Deliverable | Описание |
|---|---|
| Инфраструктурная документация | Архитектура, схема развёртывания, инструкция по обновлению |
| Настроенный кластер | JupyterHub с аутентификацией, профилями, GPU-квотами |
| Docker-образы | Готовые образы с PyTorch, MLflow, DVC |
| Интеграции | MLflow, DVC, shared storage, pre-commit hooks |
| Обучение | 2-часовая сессия для команды + запись |
| Поддержка | 2 недели после сдачи — исправление багов, ответы на вопросы |
Как мы поддерживаем воспроизводимость?
Фиксируем версии библиотек в Dockerfile, используем lock-файлы (pip freeze), настраиваем pre-commit hooks. Итоговая среда воспроизводится одной командой helm install. Гарантируем стабильность в течение 2 недель после внедрения.
Гарантии и опыт
Более 5 лет опыта в MLOps, 20+ внедрений для команд от 3 до 50 человек. Гарантируем SLA 99.9% доступности и воспроизводимость окружений. Закажите настройку JupyterHub под ваш проект — мы предоставим демо-доступ к работающей среде в течение 2 дней. Получите консультацию, связавшись с нами.







