Мы с вами подобрались к заключительной части статьи-инструкции об организации распределённого инференса и шардирования LLM в домашних условиях. Мы уже запустили модель Gemma 3 и протестировали API, самое время настроить авторизацию и удобный веб-интерфейс для взаимодействия с нашей моделью. Им станет бесплатный Open WebUI. 

В конце статьи попросим домашнюю LLM подвести итоги всей проделанной работы, а также поговорим о планах по развитию проекта.

Если вы не читали прошлые части статьи, стоит начать с них. В первой части мы настраиваем GPU и проброс в Proxmox, развёртываем Kubernetes-кластер, устанавливаем GPU Operator и KubeRay Operator. Во второй — пишем скрипт для vLLM и обеспечиваем доступ к нему через Ray Serve, а также запускаем модель Gemma 3 в KubeRay.

Настройка авторизации и интеграция с Open WebUI

Давайте рассмотрим, как развернуть Open WebUI — бесплатный веб-интерфейс для взаимодействия с LLM. Я дам краткий обзор Open WebUI и покажу, как связать его с нашим Ray-кластером, чтобы общаться с моделью через OpenAI-совместимый API.

Краткий обзор Open WebUI

Open WebUI — это веб-приложение, которое упрощает работу с большими языковыми моделями. Проект распространяется бесплатно под лицензией MIT, его код открыт.  Благодаря Open WebUI пользователи могут:

  • отправлять сообщения к модели в формате диалога;

  • сохранять сессии диалога, чтобы возвращаться к ним и продолжать;

  • настраивать параметры инференса — температуру, длину вывода, top_k, top_p и другие;

  • управлять пользователями и ролями — регистрация, назначение роли admin/user.

Open WebUI поддерживает различные бэкенды для обработки запросов:

  • Ray Serve (через OpenAI-совместимый эндпойнт);

  • Ollama (локальные модели);

  • внешние OpenAI API (например, официальный OpenAI, Azure и Anthropic);

  • Pipelines (экспериментальные функции с LangChain и так далее).

Для дополнительного функционала можно активировать плагины, например Pipelines. Плагины позволяют загружать и обрабатывать документы в форматах PDF, DOCX и других с помощью тулкита Apache Tika. Также возможны интеграция с Langfuse и поддержка метода Retrieval Augmented Generation (RAG), что расширяет возможности работы с моделями. 

Open WebUI поддерживает двустороннюю коммуникацию в реальном времени через WebSocket, что нужно для реализации «стримингового» ответа модели. Кроме того, пользователи могут одновременно вести несколько диалогов с разными моделями благодаря поддержке мультисессий.

Развёртывание Open WebUI через Helm

Основной Helm-чарт

Open WebUI предлагает официальный Helm-чарт, позволяющий:

  • запускать StatefulSet или Deployment (на выбор) с несколькими репликами;

  • настраивать Ingress, Redis (для WebSocket), PVC (хранение данных), авторизацию и так далее.

Пример установки:

helm repo add open-webui https://helm.openwebui.io
helm install open-webui open-webui/open-webui -f ap-values.yaml

Здесь ap-values.yaml — пример моих настроек.

Основные параметры:

nameOverride: "web-ui"

# ollama, pipelines, tika — опциональные модули, обычно отключены, если не нужны.
ollama:
  enabled: false
pipelines:
  enabled: false
tika:
  enabled: false

# Может использоваться встроенный Redis для WebSocket.
websocket:
  enabled: true
  manager: redis
  redis:
    enabled: true

# Глобальный Redis-кластер (можно отключить или настроить внешний).
redis-cluster:
  enabled: true
  fullnameOverride: open-webui-redis
  auth:
    enabled: false
  replica:
    replicaCount: 3

# Настройки реплик Open WebUI.
replicaCount: 2
image:
  repository: ghcr.io/open-webui/open-webui
  tag: ""
  pullPolicy: "IfNotPresent"

# Ингресс, используемый для доступа извне.
ingress:
  enabled: true
  class: "external-ingress"
  annotations:
    cert-manager.io/cluster-issuer: regru-letsencrypt-prod
    nginx.ingress.kubernetes.io/websocket-services: "web-ui"
  host: "ai.example.com"
  tls: true
  existingSecret: "ai-example-com-https-cert"

# Хранилище.
persistence:
  enabled: true
  size: 10Gi
  accessModes:
    - ReadWriteMany
  storageClass: "ceph-fs-nvme-sc"

# Ключевая переменная — куда «проксировать» OpenAI API.
openaiBaseApiUrl: "https://openai-api.example.com/v1"
openaiBaseApiUrls:
  - "https://openai-api.example.com/v1"

extraEnvVars:
  - name: ENABLE_OPENAI_API
    value: "True"
  - name: DEFAULT_MODELS
    value: "Gemma-3-12b"
  - name: WEBUI_NAME
    value: "AI.example.com"
  - name: WEBUI_URL
    value: "https://ai.example.com"
  - name: DEFAULT_LOCALE
    value: "ru"
  - name: RAG_EMBEDDING_ENGINE
    value: "openai"
  - name: ENABLE_LOGIN_FORM
    value: "True"
  - name: OPENAI_API_KEY
    valueFrom:
      secretKeyRef:
        name: openai-api-key
        key: api-key

Настройки Ingress

  • host: ai.example.com — имя домена, с которого будет доступен интерфейс;

  • annotations — можно указать аннотации для автоматического получения TLS-сертификата через cert-manager (например, cert-manager.io/cluster-issuer: regru-letsencrypt-prod);

  • class — external-ingress, если используете свой внешний Ingress.

Провайдер Let's Encrypt для reg.ru

У меня хостинг reg.ru и для Let's Encrypt-сертификатов я использую DNS01-Challenge. Помогает мне в этом вебхук для certmanager’а от ребят из «Фланта» regru-letsencrypt-prod. Для его работы необходимо добавить соответствующие аннотации и создать ClusterIssuer, который будет взаимодействовать с reg.ru API для получения сертификатов.

Параметры окружения (extraEnvVars)

  • ENABLE_OPENAI_API: True — чтобы включить работу Open WebUI с OpenAI-протоколами.

  • DEFAULT_MODELS:  — указываем «Gemma-3-12b» как модель «по умолчанию» на интерфейсе.

  • WEBUI_URL:  — внешний URL, чтобы ссылки и формы корректно формировались.

  • OPENAI_API_KEY:  — если требуется ключ, который Open WebUI будет передавать при работе с внешним OpenAI API или вашим Ray API.

Полный список переменных окружения. 

Интерфейс и основные блоки

Настройки модели

При первом запуске Open WebUI (допустим, https://ai.example.com) вы увидите главный экран со списком чатов и настройки. В настройках задаются:

  • Base URL для OpenAI-протокола (openaiBaseApiUrl или несколько URL в openaiBaseApiUrls);

  • модель по умолчанию;

  • API-ключ, если требуется. 

Вот экран с настройками модели, где мы задаём URL до нашего API и ключ к нему: 

Создание диалога и сохранение истории

Пользователь кликает «New Chat», выбирает модель, задаёт системное сообщение (System Prompt), после чего общается с LLM в режиме реального времени. Open WebUI в свою очередь отправляет запрос на POST /v1/chat/completions и получает стриминг-ответ, если включена функция stream.

Диалоги Open WebUI хранит в своей базе данных. По умолчанию это SQLite внутри контейнера или на PVC. Пользователи могут переключаться между чатами, а также возвращаться к старым чатам, продолжать или просматривать их.

Управление пользователями и ролями

Роль Admin

При развёртывании можно назначить — либо создать при первом запуске — учётную запись администратора. Администратор имеет право:

  • подтверждать регистрацию других пользователей;

  • назначать им роли — user, admin, guest;

  • настраивать общие параметры приложения.

Регистрация

Если ENABLE_LOGIN_FORM=true, тогда гости могут зайти на страницу /login и зарегистрироваться. Для этого понадобится ввести email и пароль. После гость попадёт в статус Pending, и админ сможет его активировать. 

Это позволяет разграничить доступ к инференсу, так как LLM-вычисления дорого обходятся по ресурсам.

Пример инференса

1. Open WebUI развёрнут с ingress.host=ai.example.com.

2. Ray Serve с моделью Gemma-3-12b доступен по https://openai-api.example.com/v1.

3. В настройках Open WebUI или в ap-values.yaml прописали:

openaiBaseApiUrl: "https://openai-api.example.com/v1"
extraEnvVars:
  - name: DEFAULT_MODELS
    value: "Gemma-3-12b"

4. Авторизация: проходим логин в Open WebUI как админ или обычный пользователь.

5. Выбираем модель Gemma-3-12b, задаём вопрос и получаем ответ, который приходит из Ray Serve (vLLM):

Дополнительные возможности:

  1. LangChain Pipelines — можно активировать pipelines.enabled=true и подключать LangChain, Tika, инструменты для анализа документов.

  2. Ollama — если требуется локальный бэкенд Ollama, можно включить ollama.enabled=true. Но в нашем случае используется Ray Serve.

  3. Redis Cluster — при больших нагрузках лучше включить Redis Cluster (replicaCount > 3), чтобы WebSocket-соединения хранились надёжно.

Вывод приложения в интернет и защита с помощью CDN

Content Delivery Network (CDN) располагает точками присутствия (POP) по всему миру, что позволяет ей эффективно обрабатывать запросы пользователей к вашему домену, например ai.example.com.

При обращении пользователя запрос проходит через CDN, которая может арендовать каналы связи и направлять трафик по оптимальным маршрутам. Также CDN помогает защищаться от DDoS-атак, особенно на уровнях L3 и L4, и может выступать в роли прокси-сервера, скрывая реальный IP-адрес вашего кластера. В функционал CDN также входит поддержка WebSocket, что важно для работы Open WebUI, где чат может работать в режиме реального времени.

Пример сервиса CDN EdgeCenter предоставляет следующие возможности:

  • Роутинг трафика и кэш, что пригодится, если есть статические компоненты.

  • Вариант WAF-модуля, защищающего от классических веб-атак (OWASP Top 10).

  • Настройки геоблокировки. Например, можно запретить доступ из конкретных регионов.

Как это работает

Настраиваем DNS:

  • Доменное имя ai.example.com указывает на CDN (A/CNAME-запись).

Настраиваем CDN-конфигурацию:

  • Указываем backend-адрес — <LoadBalancer IP> или <Ingress IP> вашего кластера.

  • Включаем WebSocket pass-through, чтобы чат работал.

  • Активируем WAF, чтобы фильтровать вредоносные запросы.

CDN + TLS:

  • CDN может взять на себя создание TLS-сертификатов.

  • При этом внешний мир видит IP CDN, а не ваш кластер.

Преимущества

  1. Сокрытие реального IP: усложняет атаки на прямой адрес.

  2. Защита от DDoS: CDN-провайдер может отсеивать интенсивный нежелательный трафик.

  3. WAF: блокирует SQL-инъекции, XSS и другие угрозы из топ-10 OWASP.

  4. Контроль: некоторые CDN/WAF-решения дают гибкие правила (Rate Limiting, геоблок, ограничения по User-Agent).

Промежуточные итоги

  1. Open WebUI даёт удобный UI для GPT-подобных моделей, поддерживает OpenAI-стиль запросов, сохраняет чаты, имеет встроенную авторизацию.

  2. Настройки через Helm позволяют масштабировать количество реплик, подключать разные модули, настраивать TLS и persistence.

  3. Гибкая авторизация (роль admin, pending users) и возможность дополнительно использовать JWT на стороне Ray Serve (двойная защита).

  4. CDN и WAF помогают безопасно публиковать интерфейс наружу, скрывая IP-адрес кластера, фильтруя вредоносные запросы.

Заключение, сгенерированное домашней LLM

В трёх частях статьи мы с вами совершили настоящее путешествие в мир распределённого инференса, начиная с настройки GPU на Proxmox и заканчивая развёртыванием удобного веб-интерфейса для работы с большими языковыми моделями. Мы продемонстрировали, как можно создать гибкую, масштабируемую и безопасную инфраструктуру даже в домашних условиях.

Настройка GPU и проброс через Proxmox

Мы подробно разобрали, как правильно настроить Proxmox для проброса GPU в виртуальные машины. Это позволило объединить ресурсы нескольких видеокарт, обходя ограничения одной карты, и заложило основу для дальнейших вычислений.

Развёртывание Kubernetes-кластера с Deckhouse Kubernetes Platform

С помощью DKP мы создали Kubernetes-кластер, добавили GPU-узлы и интегрировали инструменты, такие как NVIDIA GPU Operator и KubeRay Operator, для эффективного управления вычислительными ресурсами.

Использование vLLM и Ray Serve

Благодаря vLLM мы смогли шардировать и распределить вычисления между несколькими GPU, а Ray Serve обеспечил масштабируемый HTTP API, совместимый с OpenAI-стилем, для общения с моделью. Это дало возможность работать с крупными языковыми моделями, не ограничиваясь одной видеокартой.

Подготовка Docker-образа и настройка KubeRay Cluster

Мы подробно описали процесс сборки Docker-образа на основе официального Ray-образа, добавления наших скриптов и необходимых зависимостей, а затем развёртывание Ray-кластера с помощью Helm-чарта. Это позволило создать оптимизированное окружение для инференса.

Интеграция с Open WebUI и вывод в интернет

Open WebUI был развёрнут как бесплатный и удобный интерфейс для взаимодействия с LLM, позволяя управлять пользователями, настраивать API и использовать расширенные опции через Helm-чарт. Кроме того, применение CDN и WAF гарантирует защиту и высокую скорость доступа, скрывая реальный IP-адрес кластера и обеспечивая базовую защиту от DDoS и других угроз.

В итоге статья демонстрирует, как можно собрать платформу для распределённого инференса, которая не только эффективно использует аппаратные ресурсы, но и обеспечивает безопасный, масштабируемый и удобный доступ к языковым моделям через веб-интерфейс. Это решение открывает широкие возможности для дальнейших экспериментов, разработки и внедрения в различных масштабах — от домашних лабораторий до крупных корпоративных инфраструктур.

Я надеюсь, что мой проект вдохновит вас на новые идеи и эксперименты, а полученная платформа станет отличной отправной точкой для реализации самых смелых задумок в области искусственного интеллекта и распределённых вычислений.

P. S. Что успело измениться, пока статья готовилась к выходу

Пока текст проходил редактуру, мой домашний кластер не стоял на месте. Я успел добавить несколько новых сервисов и начать эксперименты, которые делают инфраструктуру куда полезнее:

  • Stable Diffusion уже встроен в Open WebUI, поэтому теперь к каждому ответу LLM при желании можно получить мгновенную иллюстрацию или схему.

  • Whisper обрабатывает голосовые запросы: надиктовал вопрос — сразу получил текст. В связке с TTS (Microsoft Speech) это даёт режим «расскажи сказку вслух» — ребёнок формулирует тему голосом, модель сочиняет историю и тут же её озвучивает.

  • Тестирую мультимодальность: доработал serve.py, чтобы Gemma 3 принимала не только текст, но и изображения.

  • Подключаюсь как бэкенд к различным Copilot-подобным ассистентам и AI-агентам (MCP): OpenAI-совместимый эндпойнт позволяет VS Code, JetBrains AI и другим инструментам «думать» силами домашнего кластера.

  • В плане доработок — режим RAG: загрузка PDF, DOCX и прочих документов, чтобы модель отвечала с цитатами и ссылками на конкретные страницы, а также AI-SRE-помощник для k8s: он будет на лету анализировать метрики и логи, предлагать и по одобрению применять исправления в пару кликов, непрерывно учиться на runbook’ах и отзывах, делать бэкапы и восстанавливаться из них — надеюсь, это позволит забыть про рутину и сосредоточиться на действительно крутых задачах.

Если у вас есть идеи, что ещё можно запустить на таком кластере, — пишите в комментариях, будем экспериментировать вместе!

P. P. S. Минутка рекламы

20 мая в 19:35 я выступаю на первом митапе Deckhouse User Community с докладом по теме этой статьи. Места на офлайн в Москве закончились, но можно посмотреть выступление в онлайн-трансляции и задать мне вопросы в чате. Зарегистрироваться можно на TimePad

Комментарии (9)


  1. project_delta
    16.05.2025 08:05

    очень крутые статьи! в какой бюджет обошлась ваша домашняя лаборатория?


    1. Myskat_90 Автор
      16.05.2025 08:05

      Большое спасибо за отзыв! Для меня очень важна обратная связь.

      Вопрос про бюджет провокационный конечно) Поэтому отвечу так - точно дешевле, чем одна Tesla H100 80Gb, если смотреть объявления на авито.


      1. project_delta
        16.05.2025 08:05

        на самом деле никакой провокации, сам занимаюсь посторойкой homelab, но без видеокарт)


        1. Myskat_90 Автор
          16.05.2025 08:05

          Это другой разговор - написал в ЛС более подробно)


          1. project_delta
            16.05.2025 08:05

            Спасибо за список. К сожалению, у вас выключены входящие сообщения на Хабре, поэтому отпишусь тут)
            Список ваш впечатляет, у меня просто NAS и 2 ПК на инженерных intel i9 1200 сокета (описывал в своих статьях сборку)


  1. Kamil_GR
    16.05.2025 08:05

    Добрый день! Прекрасная статья!

    Подскажите, есть ли возможность протестировать мой промпт на вашей модели (я интересуюсь его применимостью на разных LLM и влиянием фильтров разработчиков)?


    1. Myskat_90 Автор
      16.05.2025 08:05

      Конечно, написал детали в ЛС)


  1. DimanODG
    16.05.2025 08:05

    Здравствуйте! Спасибо за такое подробное описание работы распределенных вычислений.

    Скажите, возможно мне провести этот эксперимент на моих домашних ноутбуках? Всего 3 ноутбука. У одного (13900hx) дискретная 4080 (12gb). У 2-х других (12700h и 13500h) есть внешние видеокарты через TB4: 2080ti и 3090.


    1. Myskat_90 Автор
      16.05.2025 08:05

      Здравствуйте!

      Да, провести возможно, но надо подумать как лучше объединить ваше оборудование в единый ray кластер с проброшенными GPU - на это может потребоваться много времени)

      Плюс надо понимать, что при разнородной инфраструктуре, распределение будет ограничено по самой наименьшей по видеопамяти карте (особенности vLLM)

      Мне кажется проще будет в вашем случае использовать решение Exo https://github.com/exo-explore/exo

      Достаточно будет поставить docker и прокинуть в контейнер GPU и в этой среде поставить exo