Files
2026-09-05 19:10:43 +06:00

336 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HRBox Helm Chart
Чарт для установки HRBox в свой Kubernetes-кластер.
Сам чарт лежит в [`.helm`](.helm), настройки — в [`.helm/values.yaml`](.helm/values.yaml).
Каждый параметр там подписан, ниже — только то, что нужно сделать руками.
---
## Что разворачивается
| Компонент | Что делает | Порт |
|---|---|---|
| `web` | PHP-FPM и nginx: веб-интерфейс и API | 80 |
| `worker` | фоновые задачи: файлы, почта, отчёты | — |
| `conductor` | задачи по расписанию, всегда 1 под | 8080 |
| `chatbox` | вебсокеты чата и уведомлений | 80 → 9797 |
| `nanabush-player` | плеер курсов: SCORM, cmi5, xAPI, нативные материалы | 8094 |
| `goworker` | мессенджеры, пуши, синхронизация оргструктуры с 1С | 8686 |
| `kedoca` | электронная подпись: КЭДО, МЧД | 8558 |
| `geonames` | справочник городов, стран, часовых поясов | 8181 |
| `file-processor` | конвертация документов и изображений | — |
| `file-processor-video` | конвертация видео, по умолчанию выключен | — |
| `dragonfly` | Redis-совместимый кеш и сессии | 6379 |
| `nats` | брокер сообщений JetStream | 4222 |
Публичных маршрутов три, и все на одном домене: `/` — приложение,
`/chatbox/` — вебсокеты, `/nanabush-player` — плеер курсов.
## Что нужно подготовить
- Kubernetes 1.21+ и ingress-контроллер (nginx или traefik);
- PostgreSQL 14+ (с Citus, если планируется шардирование);
- S3-совместимое хранилище: AWS S3, MinIO, Yandex Object Storage, VK Cloud;
- SMTP-сервер;
- доступ к реестру образов HRBox и токен HRBox Hub — выдают сотрудники HRBox.
Базу и S3 чарт не разворачивает: эти хранилища содержат постоянные данные и должны быть развёрнуты вручную.
---
## Установка
### 1. Доступ к реестру образов
```bash
kubectl create secret docker-registry regsecret \
--docker-username=json_key \
--docker-password="$(cat key-puller.json)" \
--docker-server=cr.yandex \
--docker-email=not@used.com
```
### 2. TLS-сертификат
```bash
kubectl create secret tls hrbox-tls --cert=cert.pem --key=key.pem
```
Либо выпустите сертификат через cert-manager и укажите его Secret
в `ingress.tls.secretName`.
### 3. Ключи
```bash
# secrets.cookieValidationKey и app.chatbox.wrappingKey
openssl rand -hex 16
# secrets.encryptionKey, secrets.servicesInternalSecret,
# app.nanabushPlayer.keys.ticketHs256, app.nanabushPlayer.keys.sessionHs256
openssl rand -base64 48
```
`secrets.encryptionKey` шифруют пароли, в случае его утери придётся заново задавать пароли в настройках интеграций.
Ключи плеера `ticketHs256` и `sessionHs256` должны быть разными, одинаковые чарт не примет.
### 4. Заполните `values.yaml`
Минимум:
```yaml
ingress:
host: "hrbox.company.com"
tls:
secretName: "hrbox-tls"
app:
defaultTenantHostname: "hrbox.company.com"
postgres:
host: "postgresql"
database: "hrbox"
user: "hrbox"
password: "..."
s3:
endpoint: "https://storage.company.com"
bucket: "hrbox"
key: "..."
secret: "..."
smtp:
host: "smtp.company.com"
user: "noreply@company.com"
password: "..."
from: "noreply@company.com"
fromHost: "company.com"
hub:
token: "..."
chatbox:
wrappingKey: "..."
nanabushPlayer:
keys:
ticketHs256: "..."
sessionHs256: "..."
secrets:
cookieValidationKey: "..."
encryptionKey: "..."
servicesInternalSecret: "..."
```
У остальных параметров есть рабочие значения по умолчанию.
Проверить конфигурацию, ничего не устанавливая:
```bash
helm template hrbox .helm -f values.yaml > /dev/null
```
Если чего-то не хватает, команда остановится и напишет, что заполнить.
### 5. Установка
```bash
helm upgrade --install hrbox .helm -n hrbox --create-namespace -f values.yaml
```
### 6. Дождитесь миграций
```bash
kubectl -n hrbox wait --for=condition=complete --timeout=30m job -l app=jobs
```
### 7. Создайте администратора
```bash
kubectl -n hrbox exec -it deploy/hrbox-worker -- \
php yii user/create-admin admin@company.com --tenant-id=1
```
---
## Секреты
Пароли и ключи из `values.yaml` чарт кладёт в один Secret `hrbox-secrets`,
поды читают их оттуда. В спеке Deployment паролей нет.
Если секретами управляет внешний инструмент, создайте Secret сами и укажите
имя в `secrets.existingSecret`. Ключи должны называться так:
| Ключ | Что кладут |
|---|---|
| `cookie-validation-key` | `secrets.cookieValidationKey` |
| `encryption-key` | `secrets.encryptionKey` |
| `services-internal-secret` | `secrets.servicesInternalSecret` |
| `postgres-password` | `app.postgres.password` |
| `s3-key` | `app.s3.key` |
| `s3-secret` | `app.s3.secret` |
| `smtp-password` | `app.smtp.password` |
| `hub-token` | `app.hub.token` |
| `chatbox-wrapping-key` | `app.chatbox.wrappingKey` |
| `livekit-api-secret` | `app.livekit.apiSecret` |
| `yandex-client-password` | `app.yandex.clientPassword` |
| `yandex-ai-api-key` | `app.ai.yandex.apiKey` |
| `google-client-secret` | `app.integrations.google.clientSecret` |
| `slack-client-secret` | `app.slack.clientSecret` |
| `slack-verification-token` | `app.slack.verificationToken` |
Ключи плеера лежат в отдельном Secret `hrbox-nanabush-player`, за него
отвечает `app.nanabushPlayer.deployment.existingSecret`.
---
## Nanabush Player
Плеер учебных материалов: SCORM 1.2 и 2004, cmi5, xAPI, нативные курсы,
тесты и эссе.
В облаке HRBox плеер стоит на отдельном поддомене. В on-premise поддомена
нет, поэтому плеер живёт на основном домене по пути `/nanabush-player`.
Из этого следуют две вещи:
- **Cookie общие.** Плеер и HRBox на одном домене, поэтому cookie сессии
HRBox уходят и в запросы к содержимому курсов, включая сторонние
SCORM-пакеты. Если такая изоляция нужна, запросите у HRBox схему
с отдельным поддоменом.
- **Часы должны быть синхронны.** Launch-тикет живёт 5 минут, у сессии
допуск 2 минуты. Настройте NTP на нодах и сервере базы. Если это
невозможно, выключите плеер: `app.nanabushPlayer.enabled: false`.
Порядок первого включения:
1. Убедитесь, что миграции применились: плееру нужны свои таблицы.
2. Дождитесь, пока **все** поды `web` перейдут на новую версию. Пока часть
подов старая, при `rollout.percent > 0` по одному назначению может
открыться вторая попытка.
3. Проверьте, что отвечает именно плеер, а не HRBox через общий маршрут:
```bash
kubectl -n hrbox exec deploy/hrbox-worker -- \
curl -s http://hrbox-nanabush-player:8094/readyz
```
Плеер вернёт JSON. HTML означает, что запрос ушёл в HRBox.
4. Откройте `https://<домен>/nanabush-player/start` и проверьте статику
и API плеера по этому пути.
`/healthz`, `/readyz` и метрики отвечают в корне и от `basePath` не зависят.
Порт метрик наружу не публикуется.
Быстро выключить плеер можно тремя переключателями:
```yaml
app:
nanabushPlayer:
enabled: false # пользователи вернутся на старый проигрыватель
ingress:
enabled: false # маршрут снимается
deployment:
enabled: false # под останавливается
```
Выключать нужно сверху вниз: чарт не даст оставить маршрут без пода
или включённый плеер без маршрута.
Подробности контракта — `docs/nanabush-player-deployment.md` в репозитории HRBox.
---
## Эксплуатация
### Обновление
```bash
helm upgrade hrbox .helm -n hrbox -f values.yaml
```
Миграции и обновление кластера запускаются сами как хуки `post-upgrade`,
строго по очереди. В имени джобы есть номер ревизии релиза, поэтому
в `kubectl get jobs` видно, к какому выкату она относится.
### Масштабирование
```yaml
app:
replicas:
web: 4 # по числу одновременных пользователей
worker: 3 # по объёму фоновых задач
chatbox: 4 # по числу открытых вкладок
```
`conductor` всегда в одном экземпляре: два планировщика запустят каждую
задачу дважды.
Для `web` от двух реплик создаётся PodDisruptionBudget (`minAvailable: 75%`),
чтобы вывод ноды из обслуживания не уронил приложение целиком.
### Конвертация видео
Выключена по умолчанию, потому что требует заметно больше ресурсов, чем
остальная обработка файлов. Включение:
```yaml
app:
videoConverter:
enabled: true
nodeSelector:
role: converter-dedicated
tolerations:
- key: dedicated
operator: Equal
value: video-converter
effect: NoSchedule
```
### Трассировка
```yaml
app:
tracing:
enabled: true
tempoUrl: "http://tempo.monitoring:4317"
```
Рядом с `web` появится коллектор OpenTelemetry, PHP начнёт слать трейсы.
### Внешние Redis и NATS
```yaml
dragonfly:
enabled: false
nats:
enabled: false
app:
redis:
host: "redis.company.local"
nats:
url: "nats://n1:4222,nats://n2:4222,nats://n3:4222"
```
### Диагностика
```bash
kubectl -n hrbox get pods
kubectl -n hrbox logs -l app=web -c fpm --tail=200
kubectl -n hrbox logs -l app=worker --tail=200
kubectl -n hrbox logs -l app=nanabush-player --tail=200
kubectl -n hrbox get jobs
```
| Что видно | Куда смотреть |
|---|---|
| Поды `web` не готовы | пробы `/healthz` и `/health-check`, логи контейнера `fpm` |
| Джоба миграций висит | init-контейнер `wait-postgres`: доступность базы и права |
| Курс не открывается | логи `nanabush-player`, совпадают ли `ingress.host` и `app.defaultTenantHostname` |
| Не приходят уведомления | логи `goworker`, очереди NATS, `app.launchpad.topics` |
| Пользователей разлогинивает | перезапуски `dragonfly`: сессии хранятся в памяти |
---
## Обновление с версии 2.x
Часть ключей `values.yaml` переехала. Старые имена чарт узнаёт и
останавливает установку с подсказкой, поэтому ничего не потеряется.
Список изменений и порядок перехода — в [CHANGELOG.md](CHANGELOG.md).