DEVOPS-117: чарт on-premise 3.0 — Nanabush Player, секреты в Secret, валидация values

Актуализация чарта по продовому .helm из HRBOX.

Nanabush Player перенесён из прода и упрощён под one-release-топологию
on-premise: без карт env/ci_dc, но с сохранёнными инвариантами (audience =
https://<host>, basePath отдельно от aud, allowlist обратного канала только
на внутрикластерный web, метрики на непубликуемом порту). Выделенного
поддомена в on-premise нет, поэтому плеер монтируется на основной домен под
/nanabush-player. Три переключателя для аварийного отката сохранены.

Из прода также перенесены: пул конвертации видео, PodDisruptionBudget для
web, OpenTelemetry-сайдкар, assetlinks, набор location в nginx (/healthz,
/health-check, потоковый /api/v1/integration/commit, /ai/, sw.js, шрифты).
Версии образов подтянуты к продовым.

Приведение чарта в порядок: все образы в блоке image, imagePullSecrets в
настройках, девять одинаковых define ресурсов заменены одним хелпером,
удалено ~100 строк мёртвого кода в _helpers.tpl, пароли и ключи уехали в
Secret и читаются через secretKeyRef, добавлены 00-validate.yaml и NOTES.txt.

Исправлено в 2.x:
- SERVICES_INTERNAL_SECRET имел захардкоженное значение по умолчанию, то есть
  все установки, где его не заполнили, работали на одном секрете межсервисной
  аутентификации;
- cluster.domain игнорировался: маршруты кластера NATS были захардкожены на
  cluster.local;
- CLUSTER_ADVERTISE без сегмента svc — ноды NATS объявляли соседям
  недостижимый адрес;
- nats.replicas и nats.cluster.replicas задавались независимо, при
  расхождении часть нод не входила в кластер;
- пробы web проверяли только TCP-порт 9000, поэтому под с неработающим PHP
  считался готовым;
- внутренние URL были захардкожены строками hrbox-* и молча ломались при
  nameOverride.

Имена объектов и селекторы Deployment не менялись — обновление 2.x -> 3.0 не
пересоздаёт объекты. Переехавшие ключи values.yaml чарт распознаёт и
останавливает установку с подсказкой; порядок перехода — в CHANGELOG.md.

Проверено: helm lint чистый; отрендерены 4 конфигурации (дефолт, всё
включено, плеер и инфра выключены, nameOverride); структурная проверка
рендера без замечаний; 20 негативных сценариев срабатывают с ожидаемыми
сообщениями; реалистичный values.yaml из 2.x последовательно ловится всеми
шестью guard'ами.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-02 16:37:42 +06:00
co-authored by Claude Opus 5
parent 6363382f09
commit efc506e5de
35 changed files with 3150 additions and 1118 deletions
+263
View File
@@ -5,6 +5,268 @@ All notable changes to the HRBox Helm chart will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.0.0] - 2026-09-02
Синхронизация с продовым окружением HRBox и приведение чарта в порядок:
добавлен плеер учебных материалов, секреты перестали лежать открытым текстом
в спеках подов, вместо девяти одинаковых блоков ресурсов — один хелпер,
а неполная конфигурация теперь останавливает установку с внятным текстом.
### Added
#### Nanabush Player
Проигрыватель учебных материалов: SCORM 1.2 и 2004, cmi5, xAPI, нативные
курсы, тесты и эссе.
- `09-nanabush-player.yaml` — Deployment и Service, образ `nanabush-player:1.0.11`
- `00-nanabush-player-secret.yaml` — ключи launch-тикета и сессии
- маршрут `/nanabush-player` на основном Ingress
- настройки: `app.nanabushPlayer` в values.yaml, ресурсы — `resources.nanabushPlayer`
- переменные `NANABUSH_PLAYER_*` в HRBox и `PLAYER_*` в самом плеере
On-premise-топология отличается от облачной: выделенного поддомена нет,
плеер монтируется на основной домен под путём. Отсюда два ограничения,
описанные в README: нет изоляции cookie между HRBox и содержимым курсов,
и нужны синхронизированные часы (тикет живёт 5 минут).
Три независимых переключателя (`enabled`, `ingress.enabled`,
`deployment.enabled`) сохранены для аварийного отката; чарт не даёт оставить
маршрут без пода или раскатку без маршрута.
#### Проверка конфигурации
- `00-validate.yaml` — объектов не создаёт, но останавливает рендер, если
не заполнены обязательные значения, использованы ключи из версии 2.x или
нарушены инварианты плеера. Сообщения на русском, с указанием, что править.
#### Секрет приложения
- `00-app-secret.yaml` — единый Secret с паролями и ключами. Контейнеры
читают его через `secretKeyRef`, поэтому `kubectl get deploy -o yaml`
больше не показывает пароль базы и ключ шифрования.
- `secrets.existingSecret` — подстановка Secret, созданного вне чарта.
#### Новые компоненты и возможности
- `09-file-processor-video.yaml` — отдельный пул конвертации видео с
собственным профилем ресурсов, `nodeSelector` и `tolerations`
(`app.videoConverter.enabled`, по умолчанию выключен)
- `02-web-pdb.yaml` — PodDisruptionBudget для `web`, создаётся начиная с
двух реплик
- `01-otel-configmap.yaml` и sidecar-коллектор в поде `web`
(`app.tracing.enabled`)
- `01-nginx-assetlinks.yaml` — привязка мобильных приложений к домену
(`app.mobileApps`)
- `templates/NOTES.txt` — что делать после установки, с готовыми командами
и предупреждениями о небезопасных настройках
#### Новые переменные окружения
- `NATS_STREAM_REPLICAS` — число реплик JetStream-стримов по размеру кластера
- `TELEGRAM_API_URL`, `AUTH_GOOGLE_ENABLED`
- `LIVEKIT_URL`, `LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET` — видеозвонки
- `APP_INTERNAL_URL` — внутренний адрес HRBox для конвертера
- `VIDEO_CONVERTER_ENABLED` — отдельно для каждого пула
- `SENDER_ENV`, `IMAGE_RESIZE_MAX_PARALLEL`, `OTEL_*`
### Changed
#### Структура values.yaml
- все образы собраны в блок `image` — обновление версии сервиса стало
правкой одной строки
- `imagePullSecrets` вынесен в настройки, `regsecret` больше не захардкожен
- ключи приведены к camelCase: `file_processor` → `fileProcessor`,
`custom_policy` → `customPolicy`
- `resources` дополнен компонентами `fileProcessor`, `fileProcessorVideo`,
`nanabushPlayer`, `dragonfly`, `nats`
- адреса внутренних сервисов (`app.geonames.url`, `app.goworker.url`,
`app.kedoca.url`, `app.redis.host`, `app.nats.url`) по умолчанию пустые и
выводятся из имён, которые создаёт сам чарт. Раньше это были захардкоженные
строки `hrbox-*`, которые молча ломались при `nameOverride`. Явно заданное
значение по-прежнему используется как есть, поэтому старые values работают
без правок. Выключение `dragonfly` или `nats` без указания внешнего адреса
теперь останавливает установку
#### Шаблоны
- `_resources.tpl`: девять почти одинаковых define заменены одним
`hrbox.resources`; незаданные поля не рендерятся
- `_helpers.tpl`: убрано около сотни строк мёртвого кода (хелперы `nats.*`,
которыми ничего не пользовалось и которые ссылались на несуществующий
`nats.k8sClusterDomain`); добавлены `hrbox.component`, `hrbox.labels`,
`hrbox.selectorLabels`, `hrbox.secretEnv` и хелперы плеера
- у всех объектов появились стандартные лейблы `app.kubernetes.io/*`;
лейбл `app` сохранён, привычные `kubectl get pods -l app=worker` работают
- селекторы Deployment не менялись — обновление 2.x → 3.0 не пересоздаёт
объекты
- аннотации `checksum/*` перезапускают поды при изменении конфигурации nginx
или секрета приложения
- образы, порты и таймауты вынесены из шаблонов в values.yaml
#### nginx
Набор `location` синхронизирован с продовым:
- `/healthz` и `/health-check` — под них настроены пробы пода `web`
(раньше проверялся только TCP-порт)
- `/api/v1/integration/commit` — потоковая загрузка оргструктуры из 1С без
буферизации тела, лимит 500 МБ
- `/ai/` — увеличенные таймауты
- `/.well-known/assetlinks.json` и `/.well-known/apple-app-site-association`
- `/frontend/sw.js` — корректные заголовки service worker
- кеширование шрифтов
- убран TLSv1 и TLSv1.1
#### Версии образов
| Компонент | Было | Стало |
|---|---|---|
| chatbox | 3.0 | 5.18 |
| goworker | 2.7 | 3.21.2 |
| kedoca | 0.8 | 1.0.6 |
| geonames | 3.1 | 3.3 |
| file-processor | 1.0 | 1.4.6 |
| nanabush-player | — | 1.0.11 |
#### Джобы
- имя содержит номер ревизии релиза: в `kubectl get jobs` видно, какой выкат
запускал миграции, а повторный `upgrade` не спотыкается об уже существующий
объект
- `ttlSecondsAfterFinished` — час у обеих джоб (было 100 секунд у миграций и
ничего у обновления кластера): логи упавшей джобы успевают дожить до того,
как их посмотрят
#### Переименования файлов
- `03-websocket.yaml` → `03-chatbox.yaml` (содержимое было chatbox с версии 2.0)
- `09-geonames.yml` → `09-geonames.yaml`
- `99-update-cluser-job.yaml` → `99-update-cluster-job.yaml`
### Fixed
- **Общий секрет в коде чарта.** `SERVICES_INTERNAL_SECRET` имел захардкоженное
значение по умолчанию, то есть все установки, где его не заполнили, работали
на одном и том же секрете межсервисной аутентификации. Теперь значение
обязательно.
- **Домен кластера игнорировался.** Маршруты кластера NATS были захардкожены
на `cluster.local`, хотя `cluster.domain` присутствовал в values и
использовался в соседней переменной. На кластере с нестандартным доменом
ноды не находили друг друга.
- **`CLUSTER_ADVERTISE` без сегмента `svc`.** Имя не резолвилось, и ноды NATS
объявляли соседям недостижимый адрес.
- **Рассинхрон реплик NATS.** `nats.replicas` и `nats.cluster.replicas`
задавались независимо; при расхождении часть нод не входила в кластер.
Теперь чарт требует их совпадения.
- **Пробы `web` не проверяли приложение.** Проверялся TCP-порт 9000, поэтому
под с неработающим PHP считался готовым. Теперь readiness ходит в
`/health-check` через FPM.
- Пароли и ключи больше не видны в спеках Deployment.
- `imagePullPolicy` у части сервисов был `Always` на закреплённых тегах —
лишние обращения к реестру при каждом рестарте пода.
### Removed
- `secrets` больше не имеет значений по умолчанию — пустые ключи
останавливают установку вместо тихого запуска на предсказуемых секретах
- убраны неиспользуемые хелперы `nats.name`, `nats.fullname`, `nats.chart`,
`nats.labels`, `nats.selectorLabels`, `nats.clusterAdvertise`,
`nats.clusterRoutes`, `nats.extraRoutes`, `nats.tlsConfig`, `tplvalues.render`
- `SENDGRID_API_KEY` — не используется в on-premise
### Migration Guide
#### Переход с 2.x на 3.0
Все переехавшие ключи чарт распознаёт и сообщает, куда именно они переехали,
поэтому надёжнее всего запустить `helm template` и править по сообщениям.
**Шаг 1. Перенесите образы в блок `image`**
```yaml
# было
app:
image: "cr.yandex/.../hrbox:latest"
chatbox:
image: "cr.yandex/.../hrbox-chatbox:3.0"
goworker:
image: "cr.yandex/.../hrbox-goworker:2.7"
kedoca:
image: "cr.yandex/.../hrbox-kedoca:0.8"
file_processor:
image: "cr.yandex/.../hrbox-file-processor:1.0"
replicas: 1
# стало
image:
hrbox: "cr.yandex/.../hrbox:latest"
chatbox: "cr.yandex/.../hrbox-chatbox:5.18"
goworker: "cr.yandex/.../hrbox-goworker:3.21.2"
kedoca: "cr.yandex/.../hrbox-kedoca:1.0.6"
fileProcessor: "cr.yandex/.../hrbox-file-processor:1.4.6"
app:
replicas:
fileProcessor: 1
```
**Шаг 2. Переименуйте ключи**
| Было | Стало |
|---|---|
| `app.file_processor` | `app.fileProcessor` |
| `app.custom_policy` | `app.customPolicy` |
| `app.custom_policy.privacy_url` | `app.customPolicy.privacyUrl` |
| `app.custom_policy.terms_url` | `app.customPolicy.termsUrl` |
| `app.goworker.replicas` | `app.replicas.goworker` |
| `app.kedoca.replicas` | `app.replicas.kedoca` |
| `app.goworker.sentryDsn` | `app.sentry.goworkerDsn` |
| `app.chatbox.sentryDsn` | `app.sentry.chatboxDsn` |
| `nats.image` | `image.nats` |
**Шаг 3. Заполните ключи плеера**
```bash
openssl rand -base64 48 # app.nanabushPlayer.keys.ticketHs256
openssl rand -base64 48 # app.nanabushPlayer.keys.sessionHs256
```
Ключи должны отличаться друг от друга.
**Шаг 4. Проверьте `secrets.servicesInternalSecret`**
Если поле было пустым, установка работала на общем значении по умолчанию.
Сгенерируйте своё: `openssl rand -base64 48`. После обновления перезапустятся
все сервисы, обменивающиеся внутренними вызовами, — это ожидаемо.
**Шаг 5. Проверьте рендер и обновитесь**
```bash
helm template hrbox .helm -f values.yaml > /dev/null
helm upgrade hrbox .helm -n hrbox -f values.yaml
```
**Шаг 6. Включите плеер**
Порядок первого включения и проверки — в README, раздел «Nanabush Player».
#### Breaking Changes
1. **Ключи `values.yaml` переехали.** Установка останавливается с подсказкой,
молча ничего не игнорируется.
2. **`secrets.*` стали обязательными.** Установка без них не пройдёт.
3. **Появился Nanabush Player.** Это дополнительный под, Service, Secret и
маршрут; учтите ресурсы кластера. Плеер требует синхронизированного времени
на нодах.
4. **Пробы `web` стали строже.** Под, где PHP-FPM не отвечает по HTTP, теперь
не проходит readiness. Если приложение отдаёт `/health-check` иначе,
проверьте это до обновления.
5. **`app.replicas` расширился** полями `goworker`, `kedoca`, `fileProcessor`,
`fileProcessorVideo`; соответствующие `replicas` внутри сервисов удалены.
---
## [2.0.0] - 2026-01-30
Масштабная актуализация чарта на основе продового окружения hrbox. Синхронизированы версии компонентов, добавлены новые микросервисы, обновлены переменные окружения.
@@ -227,5 +489,6 @@ kubectl get pods -n hrbox -l app=websocket # Должно быть пусто
---
[3.0.0]: #300---2026-09-02
[2.0.0]: #200---2026-01-30
[1.2.0]: #120---previous-version