Оригинал: https://timofei-ermolaev.ru/courses/open-webui/drugie-sposoby/open-webui-v-managed-kubernetes-yandeks-cloud/

# Open WebUI в Managed Kubernetes Яндекс Cloud

Установим Open WebUI в готовый кластер Яндекс Cloud через Helm: отдельный kubeconfig, PVC, личный доступ, проверка данных и облачные расходы.

[![Тимофей Ермолаев](https://timofei-ermolaev.ru/_astro/timofei-ermolaev-portrait.s0mCFw-J_Z1x8STQ.webp)](<https://timofei-ermolaev.ru/ob-avtore/>)

[Тимофей Ермолаев](<https://timofei-ermolaev.ru/ob-avtore/>) Директор по информационным технологиям (CIO)

**Опубликовано**

19 октября 2026 г.

**Обновлено**

19 октября 2026 г.

**На урок**

40 мин

**Тема**

[Другие способы развёртывания](<https://timofei-ermolaev.ru/courses/open-webui/drugie-sposoby/>)

## После урока вы сможете

- Проверить доступ к готовому кластеру через отдельный kubeconfig и различать IAM и RBAC
- Подготовить одиночный Helm-релиз с постоянным диском yc-network-ssd
- Открыть личный интерфейс и проверить вход после штатной замены Pod с прежним PVC/PV
- Отдельно проверить внешний API модели и определить сохраняющиеся облачные расходы

**Проверяемый результат:** Читатель умеет установить новый частный Open WebUI в разрешённом готовом кластере, проверить вход с прежним томом после замены Pod и определить статус внешнего API и оплачиваемых ресурсов. Фактическое выполнение требует отдельной проверки в своём облаке.

У вас уже есть работающий кластер Managed Service for Kubernetes в Яндекс Cloud и разрешение развернуть в нём отдельное приложение. Перенесём знакомую конфигурацию из материала [«Open WebUI в Kubernetes через Helm»](<https://timofei-ermolaev.ru/courses/open-webui/drugie-sposoby/open-webui-v-kubernetes/>) в облачную среду. Подключимся через изолированный файл `kubeconfig`, установим новый частный экземпляр [Open WebUI чарта `17.0.0` с приложением `v0.12.0`](<https://github.com/open-webui/helm-charts/blob/b30ba72cecd81c90b629d18dadae00bd14a9930b/charts/open-webui/Chart.yaml>) и откроем веб-интерфейс в браузере на своём компьютере по адресу `http://127.0.0.1:13000`.

После запуска создадим первого администратора и проверим сохранение данных на облачном диске после замены Pod. Отдельно определим статус подключения внешнего API языковой модели и разберём, какие ресурсы продолжают расходовать бюджет после закрытия локального туннеля.

Этот маршрут опирается на документацию Яндекс Cloud и проверенный офлайн-рендер шаблонов в `Helm v3.14.2+gc309b6f`. При подготовке урока реальный облачный кластер, выделение дисков CSI, скачивание образов и вызовы внешних моделей не запускались. Поэтому все состояния живой инфраструктуры вам предстоит последовательно подтвердить в своей среде.

## Проверим, подходит ли нам этот маршрут

Создавать кластер специально ради одного интерфейса не нужно. Мы устанавливаем один новый частный экземпляр Open WebUI в уже работающий разрешённый кластер Яндекс Cloud. Предполагается, что вы умеете работать с `kubectl`, `Helm`, `namespace`, `PersistentVolumeClaim` (`PVC`) и `Service`, а особенности облачных прав, сети и дисков мы разберём по ходу действий. Если же готового кластера у вас нет, создавать его ради одного личного веб-интерфейса избыточно: проще выбрать маршрут из уроков [«Выбираем схему установки»](<https://timofei-ermolaev.ru/courses/open-webui/install/choose/>) и [«Open WebUI на виртуальной машине Яндекс Cloud»](<https://timofei-ermolaev.ru/courses/open-webui/drugie-sposoby/open-webui-v-yandeks-cloud/>) .

Мы выполняем чистую установку в отдельном пространстве имён `open-webui-yc-course` с новым релизом `open-webui-yc-course`. Данные с домашнего компьютера, виртуальной машины или прежних релизов сюда автоматически не переносятся. Публиковать сервис через публичный `Ingress` или облачный `LoadBalancer` мы не будем. Локальный сервер моделей Ollama и видеокарты (GPU) тоже не понадобятся, поскольку генерацию текста обеспечит внешний серверный API.

Прежде чем вводить команды, проверьте вместе с оператором кластера стартовые условия:

1. В целевом каталоге Яндекс Cloud работает мастер кластера и есть минимум один рабочий узел (`worker node`) в состоянии `Ready` с запасом доступных (`allocatable`) ресурсов процессора и памяти.
2. С оператором согласованы свободные имена пространства имён `open-webui-yc-course` и релиза `open-webui-yc-course`, а также ваши права в облаке и внутри Kubernetes.
3. Согласно [правилам управления доступом Managed Service for Kubernetes](<https://yandex.cloud/en/docs/managed-kubernetes/security/>) , у самого кластера и группы узлов уже настроены штатные сервисные аккаунты облака. Сервисный аккаунт кластера управляет узлами, подсетями и дисками, а сервисный аккаунт узлов отвечает за доступ к реестрам Яндекса. В этом уроке мы эти аккаунты не создаём и роли им не назначаем.
4. В кластере работает драйвер CSI, доступен класс хранилища [`yc-network-ssd`](<https://yandex.cloud/ru/docs/managed-kubernetes/operations/volumes/manage-storage-class>) и есть квота на SSD-диски в той зоне доступности, где работает ваш узел.
5. У рабочих узлов настроен [исходящий доступ в интернет](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/network>) и работает DNS для скачивания образов и обращения к внешнему API модели.
6. Оператор подготовил или готов создать в целевом пространстве имён стабильный секрет `open-webui-auth` с ключом подписи сессий `WEBUI_SECRET_KEY`.
7. Подтверждён бюджет на оплату ресурсов по [правилам тарификации Managed Service for Kubernetes](<https://yandex.cloud/ru/docs/managed-kubernetes/pricing>) и выбранного поставщика API модели.

Чтобы не смешивать разные уровни инфраструктуры, разделим движение сетевых запросов и хранение данных на три независимых пути:

| Путь в системе | Как проходит соединение или запись | Что требуется от среды |
| --- | --- | --- |
| Доступ пользователя к веб-интерфейсу | Браузер (`127.0.0.1:13000`) → локальный `kubectl port-forward` → достижимый API кластера → выбранный `Pod` (порт `8080`). В [команде по имени Service](<https://kubernetes.io/docs/reference/kubectl/generated/kubectl_port-forward/>) его порт `80` указывает на `targetPort` приложения; Service используется для выбора Pod, а не как промежуточный адрес передачи данных | Компьютер с браузером имеет сетевой доступ к выбранному API endpoint кластера и право `pods/portforward` |
| Сохранение базы данных и настроек | `Pod` (`/app/backend/data`) → `PVC` → `PersistentVolume` (`PV`) → зональный блочный диск Compute Cloud (`yc-network-ssd`); плюс чтение `WEBUI_SECRET_KEY` из `Secret` | Рабочий драйвер CSI, квота на диск и доступный узел в той же зоне доступности |
| Запросы к внешней языковой модели | `Pod` на рабочем узле → DNS и исходящий HTTPS → внешний серверный API провайдера модели | Публичный IP на узле или настроенный оператором NAT в подсети узлов |

У этой схемы есть ограничения, которые нужно учесть до установки:

- По [официальному руководству Kubernetes для Open WebUI](<https://docs.openwebui.com/deployment/kubernetes/>) , конфигурация с одной репликой (`replicaCount: 1`), одним рабочим процессом (`UVICORN_WORKERS=1`) и встроенной базой SQLite на блочном диске подходит для одиночного экземпляра, но не обеспечивает высокую доступность (HA). Даже если мастер вашего кластера региональный (распределён по трём зонам), один Pod на одном рабочем узле с зональным диском временно остановится при перезапуске контейнера или выходе узла из строя.
- Заданные в примере ресурсы Pod (`requests: 500m CPU, 1Gi RAM` и `limits: 2 CPU, 4Gi RAM`) взяты из [документации Open WebUI](<https://docs.openwebui.com/deployment/kubernetes/>) как отправная точка. Они не гарантируют скорость отклика и не равны размеру виртуальной машины рабочего узла: на самом узле часть ресурсов всегда занята системными компонентами Kubernetes (см. также общие ориентиры в уроке [«Требования к Open WebUI»](<https://timofei-ermolaev.ru/courses/open-webui/start/trebovaniya/>) ).
- Приведённый в уроке файл настроек проверен офлайн командами `helm lint` и `helm template` в `Helm v3.14.2` с параметром рендера `Capabilities.KubeVersion = 1.34.0`. Это значение описывает только локальную среду шаблонизатора и не является проверенной версией сервера Яндекс Cloud или минимальным требованием совместимости.

Подключимся к нужному кластеру через отдельную конфигурацию, чтобы команды не затронули соседние рабочие окружения.

## Подключимся через отдельный kubeconfig

Чтобы команды установки не попали в другой кластер из вашего списка контекстов, создадим на компьютере отдельную рабочую папку и запишем данные подключения в новый изолированный файл `kubeconfig-yc-course.yaml`. Во всех кластерных командах `kubectl` и `Helm` мы будем явно передавать путь к этому файлу и точное имя контекста. Основной файл `~/.kube/config` при этом останется нетронутым.

На компьютере, где вы откроете браузер и будете запускать команды, проверьте наличие и версии установленных утилит:

```
yc  version  
kubectl  version  --client  
helm  version  --short  
```

Утилита `yc` должна быть заранее инициализирована и привязана к вашему рабочему профилю Яндекс Cloud. Как поясняют [обзор подключения к кластеру](<https://yandex.cloud/ru/docs/managed-kubernetes/operations/connect/>) и [справочник команды `get-credentials`](<https://yandex.cloud/en/docs/cli/cli-ref/managed-kubernetes/cli-ref/cluster/get-credentials>) , подключение `kubectl` опирается на аутентификацию Yandex IAM и назначенные роли. Мы не будем вручную копировать IAM-токены в файлы настроек или выводить на экран сырое содержимое конфигурации (`kubectl config view --raw` или `yc config list`), чтобы не раскрыть учётные данные в терминале.

В Яндекс Cloud права управления облачными ресурсами и права внутри самого Kubernetes разделены. Согласно [документации по управлению доступом](<https://yandex.cloud/en/docs/managed-kubernetes/security/>) , сервисная роль `k8s.viewer` позволяет прочитать метаданные кластера в облаке и сформировать `kubeconfig`, но сама по себе не даёт прав создавать объекты внутри Kubernetes. Для работы через Kubernetes API назначаются либо облачные роли (`k8s.cluster-api.editor` даёт права редактирования во всех пространствах имён, а `k8s.cluster-api.cluster-admin` соответствует полным правам `cluster-admin`), либо более узкие привязки ролей напрямую через Kubernetes RBAC в конкретном `namespace`. Выдавать себе полный административный доступ на весь кластер ради этого урока не нужно: операции уровня кластера может выполнить или подтвердить оператор.

Создайте новую пустую папку на своём компьютере, перейдите в неё и задайте переменные с путём к новому файлу `kubeconfig`, идентификатором согласованного каталога (`FOLDER_ID`), идентификатором целевого кластера (`CLUSTER_ID`) и именем контекста (`CTX`). Перед запросом учётных данных убедитесь, что файла `kubeconfig-yc-course.yaml` в этой папке ещё нет:

```
COURSE_KUBECONFIG = " $PWD /kubeconfig-yc-course.yaml"  
FOLDER_ID = "REPLACE_WITH_APPROVED_FOLDER_ID"  
CLUSTER_ID = "REPLACE_WITH_APPROVED_CLUSTER_ID"  
CTX = "open-webui-yc-course"  
yc  managed-kubernetes  cluster  list  --folder-id  " $FOLDER_ID "  
yc  managed-kubernetes  cluster  get  --id  " $CLUSTER_ID "  
```

Команды `cluster list` и `cluster get` должны вернуть метаданные вашего согласованного кластера в статусе `RUNNING`. Обратите внимание на блок сетевых адресов API в выводе `cluster get`.

Как отмечено в [правилах подключения](<https://yandex.cloud/ru/docs/managed-kubernetes/operations/connect/>) и [описании сети кластера](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/network>) , флаги `--external` и `--internal` в команде `get-credentials` лишь выбирают, какой адрес API записать в `kubeconfig`, но сами по себе не прокладывают сетевой маршрут и не открывают файрвол. По [документации групп безопасности](<https://github.com/yandex-cloud/docs/blob/master/ru/managed-kubernetes/operations/connect/security-groups.md>) , доступ к портам API (`443` и `6443`) ограничивается разрешёнными диапазонами IP-адресов (CIDR).

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

**Основная ветка: у кластера есть внешний адрес API (`--external`), открытый для вашего IP-адреса.** Запишем конфигурацию в новый файл (без флага `--force`, чтобы случайно не перезаписать существующие данные) и проверим связь с API:

```
yc  managed-kubernetes  cluster  get-credentials  --id  " $CLUSTER_ID "  --external  --context-name  " $CTX "  --kubeconfig  " $COURSE_KUBECONFIG "  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  cluster-info  
```

> **Альтернативная ветка: у кластера есть только внутренний адрес API (`--internal`).** Выполняйте этот вариант *вместо* предыдущего только в том случае, если на вашем компьютере с браузером уже работает согласованный корпоративный VPN или маршрутизируемое соединение с облачной сетью Яндекса. Учтите, что запуск `kubectl port-forward` на удалённом бастион-хосте откроет порт `127.0.0.1` самого бастиона, а не вашего ноутбука. Если прямой маршрут с компьютера с браузером до внутреннего API уже есть, выполните:
>
> ```
> yc  managed-kubernetes  cluster  get-credentials  --id  " $CLUSTER_ID "  --internal  --context-name  " $CTX "  --kubeconfig  " $COURSE_KUBECONFIG "  
> kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  cluster-info  
> ```

Если `cluster-info` возвращает адрес Kubernetes control plane, связь и базовая аутентификация работают. Если команда завершается по тайм-ауту, возвращает `Forbidden` или показывает чужой кластер, остановитесь и уточните у оператора идентификатор кластера, ваш внешний IP в группе безопасности и назначенные роли.

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

## Проверим права, сеть и хранилище

Даже в исправном кластере Pod с Open WebUI может оставаться в статусе `Pending` или завершаться с ошибкой скачивания образа. YAML-манифест приложения сам по себе не создаёт сетевой маршрут в интернет, не выдаёт облачные квоты и не гарантирует наличие рабочего узла в нужной зоне. Проверим эти зависимости до установки.

В том же терминале зададим переменные с согласованным именем пространства имён (`NS`), именем будущего релиза (`RELEASE`) и селектором меток (`SELECTOR`), а затем выполним предпусковую проверку узлов, класса хранилища, свободных имён и наших прав RBAC:

```
NS = "open-webui-yc-course"  
RELEASE = "open-webui-yc-course"  
SELECTOR = "app.kubernetes.io/instance= $RELEASE ,app.kubernetes.io/component=open-webui"  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  get  nodes  -o  wide  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  get  storageclass  yc-network-ssd  -o  yaml  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  get  namespace  " $NS "  
helm  list  --kube-context  " $CTX "  -n  " $NS "  --all  --kubeconfig  " $COURSE_KUBECONFIG "  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  auth  can-i  create  namespaces  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  auth  can-i  create  deployments.apps  -n  " $NS "  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  auth  can-i  create  persistentvolumeclaims  -n  " $NS "  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  auth  can-i  create  secrets  -n  " $NS "  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  auth  can-i  create  pods/portforward  -n  " $NS "  
```

Разберём, что означают результаты этих команд и что делать, если ваших прав хватает не на все проверки:

- **Узлы и класс хранилища (`get nodes`, `get storageclass`).** Чтение узлов и `StorageClass` требует прав на уровне всего кластера. Если у вас настроены права только внутри одного `namespace` и команды вернули отказ в доступе, попросите оператора подтвердить наличие `Ready`-узла с достаточным запасом CPU/RAM и присутствие класса `yc-network-ssd`. Если же вывод открылся, проверьте в описании `yc-network-ssd` три ключевых поля из [документации по классам хранилищ Яндекс Cloud](<https://yandex.cloud/ru/docs/managed-kubernetes/operations/volumes/manage-storage-class>) :

  - `provisioner: disk-csi-driver.mks.ycloud.io` указывает, что класс использует драйвер дисков Compute Cloud. Это поле не доказывает исправность CSI: её подтверждает оператор, а результат создания и подключения диска мы проверим по состоянию и событиям `PVC` и Pod;
  - `volumeBindingMode: WaitForFirstConsumer` означает, что облачный диск не будет создан в момент появления `PVC`, а подождёт, пока планировщик выберет конкретный узел для вашего Pod;
  - `reclaimPolicy: Delete` предупреждает, что при удалении объекта `PVC` из Kubernetes связанный с ним `PV` и сам облачный SSD-диск будут автоматически удалены.
- **Свободные имена (`get namespace`, `helm list`).** Для совершенно новой установки команда `get namespace "$NS"` обычно возвращает `NotFound`, а список `helm list` должен быть пустым. Если пространство имён уже существует, потому что оператор заранее подготовил его специально для вас вместе со стабильным секретом, убедитесь, что `helm list` в нём пуст и внутри нет чужих рабочих объектов. Если же вы обнаружили незнакомый существующий релиз, остановитесь и согласуйте с оператором другое имя, чтобы не перезаписать чужие данные.
- **Проверка разрешений (`auth can-i`).** Создание пространства имён (`create namespaces`) — операция уровня кластера. Если она вернула `no`, пространство имён перед установкой должен создать оператор. Остальные четыре проверки (`deployments.apps`, `persistentvolumeclaims`, `secrets` и `pods/portforward` внутри `-n "$NS"`) должны вернуть `yes`. Право `create secrets` нужно самому `Helm` для сохранения служебных метаданных релиза, даже если секрет приложения `open-webui-auth` создаёт оператор. Приведённый набор `auth can-i` проверяет только ключевые действия нашего урока и не заменяет полную корпоративную матрицу RBAC.

Отдельно проверим с оператором устройство хранилища и исходящую сеть:

1. **Блочный диск и зона доступности.** По [рекомендациям Open WebUI для Kubernetes](<https://docs.openwebui.com/deployment/kubernetes/>) , база данных SQLite требует блочного хранилища, а сетевые файловые системы вроде NFS или SMB для неё не подходят из-за проблем с блокировками файлов. Встроенный класс `yc-network-ssd` создаёт сетевой блочный SSD-диск Compute Cloud, который монтируется к узлу как обычная локальная файловая система и подходит для нашей задачи. В настройках чарта мы оставим параметр `persistence.provider: local`. Он выбирает в самом приложении работу с локальной файловой системой контейнера (в отличие от облачных объектных корзин S3/GCS), а не физический диск внутри узла. Как объясняет [документация по томам Яндекс Cloud](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/volume>) , диск Compute Cloud жёстко привязан к конкретной зоне доступности. Режим `ReadWriteOnce` (`RWO`) разрешает монтировать диск на чтение и запись только одному узлу, а чтобы на этом узле к базе SQLite не обращались два контейнера одновременно, мы закрепим в конфигурации одну реплику и стратегию обновления `Recreate`.
2. **Исходящий доступ к реестру образов и внешним ресурсам.** Наш частный интерфейс не требует открывать входящие порты `NodePort` (`30000–32767`) или SSH из примеров [документации по группам безопасности](<https://github.com/yandex-cloud/docs/blob/master/ru/managed-kubernetes/operations/connect/security-groups.md>) (при этом существующие служебные правила обмена между мастером и узлами трогать нельзя). Однако согласно [схеме сети Managed Service for Kubernetes](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/network>) , самим рабочим узлам нужен исходящий маршрут в интернет (через публичные IP узлов или настроенный оператором NAT-шлюз) и работающий DNS. Роль сервисного аккаунта узлов для доступа к Yandex Container Registry не даёт доступа к внешнему реестру `ghcr.io`. Узлы должны иметь разрешённый HTTPS-выход к `ghcr.io` (включая CDN-адреса скачивания слоёв образа) и к API выбранного вами провайдера языковой модели.
3. **Стартовая инициализация вспомогательной модели документов.** Даже при выключенной Ollama приложение Open WebUI при запуске инициализирует вспомогательную embedding-модель для работы с документами. Как видно в исходном коде `v0.12.0` ([`retrieval.py`](<https://raw.githubusercontent.com/open-webui/open-webui/v0.12.0/backend/open_webui/routers/retrieval.py>) и [`retrieval/utils.py`](<https://raw.githubusercontent.com/open-webui/open-webui/v0.12.0/backend/open_webui/retrieval/utils.py>) ), в стандартной конфигурации используется `sentence-transformers/all-MiniLM-L6-v2`, и приложение может обращаться к Hugging Face за её файлами или проверкой кеша. Хотя стандартный образ обычно включает предзагруженный кеш при сборке, а чарт копирует стартовое содержимое `/app/backend/data` в том, одна лишь доступность `ghcr.io` ещё не гарантирует, что все стартовые обращения в закрытой сети пройдут успешно. Оператору следует заранее проверить разрешённый исходящий доступ или подготовленные ресурсы.

Когда целевой кластер, права, класс диска и исходящая сеть подтверждены, подготовим на своём компьютере точную конфигурацию `Helm` и проверим её локально до обращения к кластеру.

## Подготовим настройки Helm

По сравнению с базовым уроком [«Open WebUI в Kubernetes через Helm»](<https://timofei-ermolaev.ru/courses/open-webui/drugie-sposoby/open-webui-v-kubernetes/>) мы сохраняем проверенную связку версий чарта и приложения, одиночный режим работы и внешнюю ссылку на секрет, но явно указываем облачный класс хранилища `yc-network-ssd` для создания сетевого SSD-диска в Яндекс Cloud.

Обратите внимание на версии и маршруты проверки здоровья:

- В соседнем уроке про виртуальную машину закреплён образ `v0.12.3`, однако здесь мы строго сохраняем пару **чарт `17.0.0` и приложение `v0.12.0`** из [локально сохранённого официального чарта](<https://github.com/open-webui/helm-charts/blob/b30ba72cecd81c90b629d18dadae00bd14a9930b/charts/open-webui/Chart.yaml>) . Это обеспечивает точное совпадение шаблонов и переменных чарта. Такая фиксация нужна для воспроизводимости урока и не означает, что версия самая свежая или прошла отдельный аудит безопасности.
- В текущей неверсионированной [справке по Kubernetes на сайте Open WebUI](<https://docs.openwebui.com/deployment/kubernetes/>) встречается пример с более старой парой (`16.5.0` / `v0.11.3`) и проверкой готовности `/health/db`. Мы не копируем тот фрагмент, а оставляем маршрут `/ready`: как подтверждает [исходный код `main.py` версии `v0.12.0`](<https://github.com/open-webui/open-webui/blob/v0.12.0/backend/open_webui/main.py>) , именно `/ready` возвращает код `200`, когда завершена инициализация приложения и проверена связь с базой данных.

В рабочей папке на своём компьютере сохраните следующий файл под именем `values-yc-course.yaml`:

```
# One new release in its own namespace; chart 17.0.0 only.  
replicaCount :  1  
workload :  
  kind :  Deployment  
strategy :  
  type :  Recreate  
image :  
  repository :  ghcr.io/open-webui/open-webui  
  tag :  v0.12.0  
ollama :  
  enabled :  false  
pipelines :  
  enabled :  false  
tika :  
  enabled :  false  
terminals :  
  enabled :  false  
websocket :  
  enabled :  true  
  manager :  ""  
  redis :  
    enabled :  false  
service :  
  type :  ClusterIP  
  port :  80  
  containerPort :  8080  
ingress :  
  enabled :  false  
route :  
  enabled :  false  
persistence :  
  enabled :  true  
  provider :  local  
  storageClass :  yc-network-ssd  
  accessModes :  
    -  ReadWriteOnce  
  size :  10Gi  
  annotations :  
    helm.sh/resource-policy :  keep  
# No model endpoint is installed or tested by this lesson.  
openaiApiKey :  ""  
resources :  
  requests :  
    cpu :  500m  
    memory :  1Gi  
  limits :  
    cpu :  "2"  
    memory :  4Gi  
startupProbe :  
  httpGet :  
    path :  /health  
    port :  http  
  periodSeconds :  10  
  timeoutSeconds :  5  
  failureThreshold :  60  
readinessProbe :  
  httpGet :  
    path :  /ready  
    port :  http  
  periodSeconds :  10  
  timeoutSeconds :  5  
extraEnvVars :  
  -  name :  WEBUI_SECRET_KEY  
    valueFrom :  
      secretKeyRef :  
        name :  open-webui-auth  
        key :  WEBUI_SECRET_KEY  
  -  name :  UVICORN_WORKERS  
    value :  "1"  
```

Разберём, за что отвечают блоки этого файла в облачном кластере:

- **Одиночный процесс и стратегия обновления.** Параметры `replicaCount: 1`, `workload.kind: Deployment` и переменная `UVICORN_WORKERS: "1"` задают одну реплику с одним рабочим процессом. При штатном обновлении Deployment стратегия `Recreate` сначала завершает старые Pod, затем запускает новые; интерфейс на это время недоступен. Это не универсальная защита от одновременного доступа к SQLite: ручное удаление Pod или создание дополнительных объектов требует отдельного контроля оператора.
- **Выключенные локальные дополнения и частная сеть.** Блоки `ollama`, `pipelines`, `tika`, `terminals` и `websocket.redis` отключены (`false`), чтобы не создавать в кластере лишние сервисы и не требовать Redis. Внутренний сервис `ClusterIP` направляет порт `80` на контейнерный порт `8080`, а внешние входные точки (`ingress.enabled: false`, `route.enabled: false`) закрыты.
- **Хранилище в Яндекс Cloud.** В блоке `persistence` явно выбран `storageClass: yc-network-ssd` вместо стандартного медленного класса `yc-network-hdd`. Запрашивается том `10Gi` с режимом `ReadWriteOnce`. Аннотация `helm.sh/resource-policy: keep` указывает `Helm` не удалять этот `PVC`, если вы когда-нибудь решите удалить сам Helm-релиз.
- **Секретный ключ и внешние модели.** Поле `openaiApiKey: ""` оставлено пустым: мы никогда не записываем ключи API или пароли в открытый YAML-файл, аргументы командной строки или рендер шаблонов. Переменная [`WEBUI_SECRET_KEY`](<https://docs.openwebui.com/reference/env-configuration/>) , которая подписывает токены сессий и защищает сохранённые в базе учётные данные, подключается через `secretKeyRef` из подготовленного оператором секрета `open-webui-auth`.

Теперь добавим официальный репозиторий чартов на своём компьютере, сверим описание версии `17.0.0`, проверим наш файл линтером и выполним локальный рендер манифестов в файл `rendered-open-webui.yaml`. Эти команды работают офлайн или с репозиторием чартов и ничего не устанавливают в облачный кластер:

```
helm  repo  add  open-webui  https://open-webui.github.io/helm-charts  
helm  repo  update  open-webui  
helm  show  chart  open-webui/open-webui  --version  17.0.0  
helm  pull  open-webui/open-webui  --version  17.0.0  
helm  lint  ./open-webui-17.0.0.tgz  -f  values-yc-course.yaml  
helm  template  " $RELEASE "  open-webui/open-webui  --version  17.0.0  --namespace  " $NS "  -f  values-yc-course.yaml  >  rendered-open-webui.yaml  
```

Вывод `helm show chart` должен подтвердить связку `version: 17.0.0` и `appVersion: 0.12.0`, а `helm lint` — завершиться без ошибок (`0 chart(s) failed`). Откройте созданный локально файл `rendered-open-webui.yaml` и убедитесь, что в нём сгенерированы ровно четыре объекта в пространстве имён `open-webui-yc-course`:

1. `ServiceAccount` с именем `open-webui-yc-course-sa`;
2. `PersistentVolumeClaim` с именем `open-webui-yc-course`, классом `yc-network-ssd`, размером `10Gi` и аннотацией `helm.sh/resource-policy: keep`;
3. `Service` с именем `open-webui-yc-course` типа `ClusterIP` (порт `80` → `8080`);
4. `Deployment` с именем `open-webui-yc-course`, одной репликой, стратегией `Recreate`, образом `ghcr.io/open-webui/open-webui:v0.12.0`, монтированием `/app/backend/data`, проверками `/health` и `/ready` и ссылкой `secretKeyRef` на `open-webui-auth` без открытых значений секретов.

Успешный локальный рендер доказывает, что наш `values-yc-course.yaml` синтаксически верен и формирует ровно те объекты Kubernetes, которые мы ожидаем. При этом он не проверяет допуск объектов политиками кластера, наличие секрета `open-webui-auth`, скачивание образа и выделение диска в Яндекс Cloud. Перейдём к установке в живой кластер.

## Установим Open WebUI и дождёмся готовности

Перед запуском `helm install` подготовим пространство имён и убедимся, что оператор создал в нём стабильный секрет. После установки сверим фактическое состояние объектов и события облачного драйвера дисков, в том числе если ожидание завершится по тайм-ауту.

Если пространство имён `open-webui-yc-course` ещё не создано оператором и на предыдущем шаге проверка `auth can-i create namespaces` вернула `yes`, создайте его:

```
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  create  namespace  " $NS "  
```

Прежде чем запускать установку чарта, оператор должен создать в пространстве имён `open-webui-yc-course` секрет `open-webui-auth` с непустым ключом `WEBUI_SECRET_KEY` (и сохранить само значение в корпоративном хранилище секретов). Проверим наличие метаданных этого секрета в кластере:

```
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  get  secret  open-webui-auth  
```

Вызываем обычный `get secret` без флагов `-o yaml` или `-o json`, чтобы не выводить на экран закодированное в Base64 значение секрета. Команда подтверждает, что объект `open-webui-auth` существует в нужном `namespace`; правильность самого ключа `WEBUI_SECRET_KEY` внутри него подтверждает оператор.

Теперь запустим установку нового релиза с явным указанием версии чарта `17.0.0`, нашего файла настроек, изолированного `kubeconfig` и контекста. Мы используем команду `helm install` (а не `upgrade --install`, чтобы случайно не замаскировать обновление существующего релиза) и задаём ожидание готовности до 15 минут:

```
helm  install  " $RELEASE "  open-webui/open-webui  --version  17.0.0  --kube-context  " $CTX "  --namespace  " $NS "  -f  values-yc-course.yaml  --wait  --timeout  15m  --kubeconfig  " $COURSE_KUBECONFIG "  
```

Независимо от того, завершилась ли команда сообщением об успехе или прервалась по тайм-ауту ожидания, сразу после неё проверьте фактическое состояние релиза, развёртывания, Pod и тома данных:

```
helm  status  " $RELEASE "  --kube-context  " $CTX "  -n  " $NS "  --kubeconfig  " $COURSE_KUBECONFIG "  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  get  deployment,service,pvc  -l  " $SELECTOR "  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  rollout  status  deployment/open-webui-yc-course  --timeout=15m  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  get  pods  -l  " $SELECTOR "  -o  wide  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  get  pvc  open-webui-yc-course  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  describe  pvc  open-webui-yc-course  
```

В рабочем состоянии `helm status` показывает `STATUS: deployed`, `get pvc` отображает статус `Bound` с привязанным томом `PV`, а `get pods` показывает один Pod в статусе `Running` с готовностью `1/1` (`READY`). Готовность `1/1` означает, что внутри контейнера успешно отработала проверка [`/ready`](<https://github.com/open-webui/open-webui/blob/v0.12.0/backend/open_webui/main.py>) (приложение запустилось и подключилось к своей базе SQLite на диске), однако связь с внешним API модели этим ещё не проверялась.

Если установка задержалась или `helm install --wait` вернул ошибку тайм-аута, **не пытайтесь повторно запускать `helm install`, не меняйте `StorageClass` на лету и не удаляйте `PVC` наугад**. Сначала определите причину задержки по таблице симптомов:

| Что видно в выводе команд | Возможные причины | Что проверить (самостоятельно или с оператором) |
| --- | --- | --- |
| `PVC` в статусе `Pending`, а Pod ещё не назначен на узел | Для класса [`yc-network-ssd`](<https://yandex.cloud/ru/docs/managed-kubernetes/operations/volumes/manage-storage-class>) с `WaitForFirstConsumer` диск ожидает выбора узла. Долгое ожидание может означать проблему планирования | Посмотрите события Pod: что именно мешает назначению, например нехватка CPU/RAM |
| `PVC` долго остаётся `Pending`, хотя планирование Pod продвинулось | Возможна ошибка создания диска через CSI; само состояние ещё не устанавливает причину | Изучите `Events` заявки `PVC`. По указанной ошибке оператор проверит квоту SSD-дисков, CSI и права сервисного аккаунта кластера |
| Событие `FailedScheduling` у Pod | Возможны нехватка ресурсов, несовпадение зоны диска и узла или другие ограничения планирования | Оператор читает конкретное сообщение события, проверяет состояние узлов, свободные ресурсы и [топологию тома](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/volume>) |
| Статус `ImagePullBackOff` или `ErrImagePull` | Образ не скачан: возможны ошибка имени/тега, доступ к реестру или сетевая проблема | По событию оператор проверяет имя образа, DNS и [исходящий доступ](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/network>) к `ghcr.io` и адресам скачивания |
| Статус `CreateContainerConfigError` | Возможно, отсутствует Secret `open-webui-auth` или ключ `WEBUI_SECRET_KEY` в нём | Проверьте сообщение в событиях Pod и попросите оператора проверить наличие ссылки и ключа, не выводя их значения |
| Статус `Running`, но `READY 0/1`, или `CrashLoopBackOff` | Процесс ещё инициализируется, не проходит пробу или завершается с ошибкой; состояние само по себе не объясняет причину | Проверьте события и ограниченный хвост лога: причину могут показать ошибка приложения или недоступные стартовые ресурсы. Не публикуйте чувствительные строки |
| Ошибка `Forbidden` или тайм-аут `kubectl` / `Helm` | Возможны нехватка прав или потеря связи с API | Вернитесь к проверкам `cluster-info` и `auth can-i` вместе с оператором |

При чтении событий и последнего фрагмента лога явно указывайте файл подключения, контекст и пространство имён. Вместо `POD_NAME` подставьте имя Pod из уже выполненной команды `get pods`:

```
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  describe  pod  POD_NAME  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  describe  pvc  open-webui-yc-course  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  logs  POD_NAME  --tail=50  
```

Если ваших прав чтения не хватает для просмотра событий уровня узлов или `PersistentVolume`, попросите оператора посмотреть их со своей стороны. Продолжайте урок только после того, как `PVC` перешёл в `Bound`, а единственный Pod достиг состояния `Running` и `READY 1/1`.

## Откроем интерфейс и создадим администратора

У сервиса `ClusterIP` нет внешнего адреса в интернете. Чтобы открыть веб-интерфейс в своём браузере, пробросим локальный порт с компьютера, на котором запущен браузер, через защищённое соединение `kubectl port-forward` прямо к сервису внутри кластера.

Для этого не нужны доменное имя, TLS-сертификат, публичный `Ingress` или облачный `LoadBalancer`. При этом сохраняется сетевая граница из [правил подключения к кластеру](<https://yandex.cloud/ru/docs/managed-kubernetes/operations/connect/>) : частный доступ к веб-интерфейсу приложения через `port-forward` не делает внешний API-адрес самого кластера внутренним (защита API по-прежнему держится на IAM и [группах безопасности](<https://github.com/yandex-cloud/docs/blob/master/ru/managed-kubernetes/operations/connect/security-groups.md>) ).

Откройте **второе окно терминала на том же компьютере, где запущен ваш браузер** (не запускайте эту команду на удалённом сервере или бастионе). Укажите в переменной `COURSE_KUBECONFIG` тот же самый абсолютный путь к файлу `kubeconfig-yc-course.yaml`, который вы использовали в первом терминале, и запустите перенаправление с локального адреса `127.0.0.1:13000` на порт `80` сервиса:

```
COURSE_KUBECONFIG = "REPLACE_WITH_SAME_ABSOLUTE_KUBECONFIG_PATH"  
CTX = "open-webui-yc-course"  
NS = "open-webui-yc-course"  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  port-forward  --address  127.0.0.1  service/open-webui-yc-course  13000:80  
```

Флаг `--address 127.0.0.1` привязывает открытый порт `13000` строго к петлевому интерфейсу вашего компьютера, чтобы к нему нельзя было подключиться из локальной сети. Оставьте этот второй терминал открытым на всё время работы с браузером.

Откройте в браузере адрес:

```
http://127.0.0.1:13000  
```

Поскольку мы подключились к новому экземпляру с чистой базой данных на новом диске, приложение предложит создать первую учётную запись администратора. Если вместо регистрации первого администратора вы сразу увидели окно обычного входа в чужой или старый экземпляр, остановитесь и проверьте `COURSE_KUBECONFIG`, контекст `CTX` и имя пространства имён `NS`.

Заполните имя, адрес электронной почты и пароль администратора. Как подтверждает [исходный код роутера `auths.py` версии `v0.12.0`](<https://github.com/open-webui/open-webui/blob/v0.12.0/backend/open_webui/routers/auths.py>) , когда в пустой базе создаётся самый первый пользователь (общее число пользователей равно единице), приложение автоматически назначает ему роль `admin` и сразу сохраняет в базу настройку `ui.enable_signup: False`, закрывая регистрацию для следующих посетителей.

Согласно [справочнику переменных окружения Open WebUI](<https://docs.openwebui.com/reference/env-configuration/>) , параметр `ENABLE_SIGNUP` относится к категории `ConfigVar`: при включённом по умолчанию сохранении конфигурации настройки, записанные в базу данных или изменённые через интерфейс администратора (Admin UI), имеют приоритет над переменными окружения контейнера. Поэтому пытаться управлять регистрацией через добавление `ENABLE_SIGNUP` в `values-yc-course.yaml` после первого запуска ненадёжно. Проверим безопасность входа прямо в интерфейсе:

1. Откройте панель администратора (**Admin Panel** → **Settings** → **General**) и убедитесь, что самостоятельная регистрация новых пользователей (**Enable New Sign Ups**) выключена.
2. Откройте адрес `http://127.0.0.1:13000` в новом приватном (инкогнито) окне браузера и убедитесь, что на странице входа нет кнопки регистрации нового аккаунта.
3. В основном окне браузера выйдите из системы (Sign Out) и снова войдите под только что созданным аккаунтом администратора.

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

## Проверим данные после замены Pod

Проверим сохранение аккаунта администратора при перезапуске или замене единственного Pod. В нашей схеме база SQLite лежит в каталоге `/app/backend/data` на сетевом SSD-диске Compute Cloud. Kubernetes Secret `open-webui-auth` передаёт стабильный `WEBUI_SECRET_KEY`: приложение использует его для подписи токенов сессий и защиты соответствующих зашифрованных учётных данных. Чтобы проверить сохранность данных при штатной замене контейнера, сравним уникальные идентификаторы (`UID`) объектов до и после перезапуска.

Вернитесь в **первый терминал** и запишите текущие `UID` работающего Pod, `UID` заявки `PVC` и имя привязанного тома `PV` (`.spec.volumeName`), а затем запустите штатный перезапуск развёртывания (`rollout restart`) и дождитесь его завершения:

```
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  get  pods  -l  " $SELECTOR "  -o  custom-columns=NAME:.metadata.name,UID:.metadata.uid  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  get  pvc  open-webui-yc-course  -o  custom-columns=NAME:.metadata.name,UID:.metadata.uid,VOLUME:.spec.volumeName,STATUS:.status.phase  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  rollout  restart  deployment/open-webui-yc-course  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  rollout  status  deployment/open-webui-yc-course  --timeout=15m  
```

Во время перезапуска со стратегией `Recreate` старый Pod завершается до старта нового, поэтому веб-интерфейс на короткое время станет недоступен. Когда команда `rollout status` сообщит об успешном завершении, повторите в первом терминале две первые команды чтения `UID`:

```
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  get  pods  -l  " $SELECTOR "  -o  custom-columns=NAME:.metadata.name,UID:.metadata.uid  
kubectl  --kubeconfig  " $COURSE_KUBECONFIG "  --context  " $CTX "  -n  " $NS "  get  pvc  open-webui-yc-course  -o  custom-columns=NAME:.metadata.name,UID:.metadata.uid,VOLUME:.spec.volumeName,STATUS:.status.phase  
```

Сравните вывод до и после перезапуска:

- Имя и `UID` у Pod должны стать **новыми** — это доказывает, что контейнер действительно был пересоздан.
- `UID` у `PVC`, имя тома в колонке `VOLUME` (`PV`) и статус `Bound` должны остаться **прежними** — новый Pod подключился к тому же самому облачному диску Compute Cloud в той же зоне доступности ([топология дисков](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/volume>) ).

При удалении старого Pod процесс `kubectl port-forward` во втором терминале мог разорвать соединение. Переключитесь во второй терминал: если перенаправление остановилось или перестало отвечать, завершите его клавишами `Ctrl+C` и запустите ту же команду `port-forward` заново.

После восстановления туннеля не полагайтесь на открытую ранее вкладку браузера. Откройте **новое приватное окно**, перейдите по адресу `http://127.0.0.1:13000` и выполните вход под своим логином и паролем администратора.

Если вход прошёл успешно и идентификаторы `PVC/PV` остались прежними, проверка подтвердила вход под существующим аккаунтом после этой штатной замены Pod с прежним томом. Она не проверяет все настройки, чаты и загруженные файлы. Если же приложение снова просит зарегистрировать первого администратора или не принимает пароль, не сбрасывайте базу данных: проверьте вместе с оператором, не изменился ли контекст/пространство имён, смонтирован ли прежний том и не менялось ли значение [`WEBUI_SECRET_KEY`](<https://docs.openwebui.com/reference/env-configuration/>) в секрете `open-webui-auth`.

Учитывайте границу этой проверки: мы подтвердили работу штатной замены Pod с тем же самым облачным диском на доступном узле. Это не проверка восстановления из резервной копии (backup restore), не тест отказа самого диска и не проверка высокой доступности (HA).

После проверки интерфейса и входа под прежним аккаунтом отдельно проверим подключение внешнего API языковой модели.

## Подключим внешний API модели

Готовность интерфейса и базы данных не доказывает, что из кластера Яндекс Cloud работает обращение к языковой модели. Серверное подключение к модели настраивается и проверяется отдельно.

Поскольку в нашей конфигурации [сохранение настроек в базе данных включено по умолчанию](<https://docs.openwebui.com/reference/env-configuration/>) , мы настраиваем подключение к внешнему поставщику через панель администратора (Admin UI), не записывая секретные API-ключи в `values-yc-course.yaml`, аргументы `Helm` или сгенерированные манифесты. Пошаговая настройка URL провайдера, ключа и списка моделей в интерфейсе подробно разобрана в опубликованном уроке [«Подключаем OpenAI-совместимый API»](<https://timofei-ermolaev.ru/courses/open-webui/configure/openai-compatible/>) .

Выполните настройку серверного подключения в открытом интерфейсе администратора (`http://127.0.0.1:13000`), соблюдая правила вашей инфраструктуры:

1. Используйте только согласованный адрес API (`Base URL`), разрешённый идентификатор модели и ключ, полученный по правилам безопасности вашей организации (создание аккаунтов у внешних провайдеров, настройка корпоративного SSO, функций или агентов в этот урок не входят).
2. Если у вас есть разрешение и бюджет на платный вызов API, откройте новый чат, выберите подключённую модель и отправьте один короткий обезличенный тестовый вопрос без персональных или коммерческих тайн. Появление списка моделей в выпадающем меню ещё не доказывает работоспособность генерации — только фактически полученный текстовый ответ подтверждает, что весь маршрут от Pod через [исходящую сеть рабочего узла](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/network>) до внешнего API исправен.
3. Если вы сейчас не вводите реальный ключ или не отправляете платный запрос, урок можно завершить и без этого. Зафиксируйте для себя точный статус: *интерфейс и вход под прежним аккаунтом после штатной замены Pod с тем же PVC/PV проверены, а вызов внешней модели не тестировался*.

Если при отправке запроса возвращается ошибка соединения или авторизации, проверьте правильность введённого в Admin UI адреса и ключа, доступность выбранной модели на вашем тарифе и разрешённый исходящий HTTPS-маршрут с рабочих узлов кластера. Не пытайтесь устранить ошибку исходящего доступа к API публикацией `Ingress` или `LoadBalancer`: входящий доступ к веб-интерфейсу и исходящие запросы Pod к внешнему провайдеру работают по разным сетевым путям.

## Завершим сеанс и проверим расходы

У локального туннеля, объектов Kubernetes и платных ресурсов Яндекс Cloud разные жизненные циклы. Разберём, что остановится после `Ctrl+C` во втором терминале и какие действия могут привести к удалению облачного диска с базой данных.

Когда вы закончите работу в браузере, перейдите во второй терминал, где запущен `kubectl port-forward`, и нажмите `Ctrl+C`. Локальный порт `127.0.0.1:13000` на вашем компьютере закроется.

Посмотрим, как разные операции влияют на данные и ресурсы кластера, опираясь на свойства нашего чарта и [документацию по жизненному циклу томов и классов хранилищ Яндекс Cloud](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/volume>) :

| Операция | Что происходит с приложением и доступом | Что происходит с `PVC`, `PV` и облачным SSD-диском |
| --- | --- | --- |
| Нажать `Ctrl+C` в окне `kubectl port-forward` | Закрывается только локальный туннель на вашем компьютере. Pod и Service в кластере продолжают работать | Ничего не меняется: `PVC`, `PV` и диск Compute Cloud продолжают работать и хранить данные |
| Удалить только Helm-релиз (`helm uninstall`) | Удаляются `Deployment`, `Pod`, `Service` и `ServiceAccount` нашего приложения | Благодаря аннотации `helm.sh/resource-policy: keep` объект `PVC` намеренно оставляется в кластере, поэтому `PV` и облачный диск сохраняются |
| Вручную удалить `PVC` или весь `namespace` в Kubernetes | Приложение теряет хранилище (или удаляется вместе с пространством имён) | У встроенного класса [`yc-network-ssd`](<https://yandex.cloud/ru/docs/managed-kubernetes/operations/volumes/manage-storage-class>) стоит политика `reclaimPolicy: Delete`: удаление `PVC` может автоматически удалить `PV` и сам облачный диск Compute Cloud |
| Удалить весь кластер Managed Kubernetes в облаке | Кластер и рабочие узлы уничтожаются | По [правилам работы томов](<https://yandex.cloud/ru/docs/managed-kubernetes/concepts/volume>) диски Compute Cloud, связанные с `PersistentVolumes`, при удалении кластера **не удаляются автоматически** и остаются в каталоге |

Аннотация `helm.sh/resource-policy: keep` защищает том только при удалении релиза через `Helm`. Она не спасает данные при ручном удалении `PVC`, удалении `namespace` или прямом удалении диска в консоли облака, и не заменяет регулярного резервного копирования.

В общем (разделяемом) кластере **не нужно останавливать или удалять сам кластер, рабочие узлы, пространство имён или `PVC` просто ради завершения урока**. Любое удаление ресурсов должно быть отдельным согласованным решением владельца инфраструктуры после проверки принадлежности объектов (`ownership`), точных идентификаторов томов и наличия резервной копии.

Прежде чем закрыть терминалы, проверьте структуру текущих расходов по [правилам тарификации Managed Service for Kubernetes](<https://yandex.cloud/ru/docs/managed-kubernetes/pricing>) :

- **Мастер и рабочие узлы кластера.** В работающем кластере тарифицируются ресурсы мастера (зависит от зонального или регионального типа) и вычислительные ресурсы виртуальных машин рабочих узлов (vCPU, RAM и их загрузочные диски) в Compute Cloud. То, что узлы уже существовали до нашего урока, не делает их бесплатными. Если владелец останавливает свой отдельный кластер, плата за мастер прекращается, но диски и сетевые адреса могут тарифицироваться дальше.
- **Диск приложения и снимки.** Созданный через `PVC` блочный диск `yc-network-ssd` объёмом `10Gi` (а также любые созданные для него снэпшоты или резервные копии) оплачивается всё время, пока этот диск существует в каталоге облака, даже если сам Pod или релиз остановлен.
- **Сеть и внешние сервисы.** Исходящий трафик, публичные IP-адреса или NAT-шлюз (если они используются в вашей сети) тарифицируются по правилам облака, а запросы к языковой модели оплачиваются по счёту вашего внешнего API-провайдера. Точную текущую стоимость всегда сверяйте в актуальном прайс-листе и калькуляторе Яндекс Cloud для вашего региона и валюты.

Чтобы сохранить результаты установки для дальнейшей эксплуатации без утечки секретов, запишите для себя и оператора короткую памятку по итогам работы (без значений паролей, токенов и ключей):

- идентификатор каталога и кластера (`FOLDER_ID`, `CLUSTER_ID`), путь к изолированному файлу `kubeconfig-yc-course.yaml`;
- пространство имён и имя релиза: `open-webui-yc-course`;
- имя созданного `PVC` (`open-webui-yc-course`), имя связанного с ним `PV` (`.spec.volumeName`) и имя ссылки на секрет (`open-webui-auth`);
- три раздельных статуса проверки: вход администратора через `127.0.0.1:13000` (подтверждён), сохранение аккаунта на прежнем `PVC/PV` после замены Pod (подтверждено), ответ внешнего API модели (подтверждён фактическим ответом либо отмечен как «не проверялся»).

Теперь у вас есть рабочий частный экземпляр Open WebUI в Managed Kubernetes Яндекс Cloud с постоянным томом, проверенным входом под прежним аккаунтом после штатной замены Pod и понятной картой облачных ресурсов. Настройка регулярного резервного копирования дисков, выбор схемы публичного доступа или переход к отказоустойчивой архитектуре с внешней базой данных остаются отдельными эксплуатационными задачами, которые решаются поверх этой базовой установки.

## Материалы урока

- [Open WebUI в Kubernetes через Helm timofei-ermolaev.ru](<https://timofei-ermolaev.ru/courses/open-webui/drugie-sposoby/open-webui-v-kubernetes/>)
- [Open WebUI на виртуальной машине Яндекс Cloud timofei-ermolaev.ru](<https://timofei-ermolaev.ru/courses/open-webui/drugie-sposoby/open-webui-v-yandeks-cloud/>)
- [Подключаем OpenAI-совместимый API timofei-ermolaev.ru](<https://timofei-ermolaev.ru/courses/open-webui/configure/openai-compatible/>)

## Отметить прохождение

Отметьте урок после того, как получили проверяемый результат из практической части.

Урок пройден

![Тимофей Ермолаев](https://timofei-ermolaev.ru/_astro/timofei-ermolaev-portrait.s0mCFw-J_2r7Nkv.webp)

## Об авторе

### Тимофей Ермолаев

Директор по информационным технологиям (CIO)

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

[Подробнее об авторе](<https://timofei-ermolaev.ru/ob-avtore/>)
