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 днів. Отримайте консультацію, зв'язавшись з нами.







