185 lines
15 KiB
Markdown
185 lines
15 KiB
Markdown
# Конфигурация проекта notes-backend
|
||
|
||
Документ описывает все переменные окружения и способы конфигурирования сервиса.
|
||
|
||
## Способы конфигурирования
|
||
|
||
Сервис настраивается **только через переменные окружения**. Разбор выполняется в `src/app/config.py` через библиотеку [`pydantic`](https://docs.pydantic.dev/) (`pydantic.BaseSettings`, pydantic v1).
|
||
|
||
Конфигурация разбита на несколько классов настроек, каждый со своим префиксом (`Config.env_prefix`):
|
||
|
||
- `PostgresSettings` — префикс `PG_`;
|
||
- `DjangoSettings` — префикс `DJANGO_`;
|
||
- `Documentations` — префикс `DOCUMENTATIONS_`;
|
||
- `WorkflowSettings` — префикс `WORKFLOW_`;
|
||
- `AttachmentSettings` — префикс `ATTACHMENT_`;
|
||
- `LoggerSettings` — префикс `LOG_`;
|
||
- корневой `Settings` — **без префикса** (поля читаются по имени в верхнем регистре, напр. `BASE_HOST`, `FAAS_SERVICE`).
|
||
|
||
Каждый вложенный класс настроек инстанцируется отдельно и читает свои переменные из окружения по своему префиксу. Отдельного конфиг-файла (yaml/toml) у приложения нет.
|
||
|
||
Источники переменных по способам запуска:
|
||
|
||
| Способ запуска | Откуда берутся переменные |
|
||
| --- | --- |
|
||
| Локально (uvicorn/gunicorn) | Переменные окружения процесса. Приложение **не загружает `.env` автоматически** (в `config.py` нет `env_file`/`python-dotenv`) — переменные нужно экспортировать самому |
|
||
| Локально (контейнеры) | `docker-compose.yml`: блок `environment` для сервиса `notes` (`PG_HOST`, `PG_DB`, `PG_LOGIN`, `PG_PASSWORD`, `DJANGO_USE`, `TIMEOUT`) |
|
||
| Kubernetes (Helm) | `.helm/values.yaml`: блоки `envs` (обычные значения) и `secretEnvs` (значения из k8s-секретов) чарта `universal-chart` |
|
||
| CI/CD (GitLab) | `.gitlab-ci.yml`: переменные пайплайна (`workflow.rules`) — выбор окружения по ветке/тегу |
|
||
|
||
Порядок запуска в контейнере (`entrypoint.sh`): сначала выполняются миграции (`alembic upgrade head`), затем стартует gunicorn с воркерами `uvicorn.workers.UvicornWorker` на `0.0.0.0:8000` с таймаутом `$TIMEOUT`.
|
||
|
||
## Переменные приложения
|
||
|
||
Дефолт `—` означает, что явного значения по умолчанию нет (пустая строка/обязательно задать для реального окружения).
|
||
|
||
### App / корневой `Settings` (без префикса)
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `BASE_HOST` | string | `https://lk.sarex.io` | Внешний базовый URL сервиса |
|
||
| `API_PREFIX` | string | `/api/v1` | Префикс публичного API |
|
||
| `DEBUG` | bool | `False` | Режим отладки. Также влияет на `PostgresSettings` (см. ниже) и включает `ProfilingSqlQueryMiddleware` |
|
||
| `FAAS_SERVICE` | string | `https://stage-api.sarex.io/lambdas` | URL сервиса лямбд/FaaS |
|
||
| `WORKSPACE_URL` | string | `https://stage-api.sarex.io/workspaces/api/v1` | URL сервиса рабочих областей (для `SYNC_RESOURCE_ID`) |
|
||
| `RESOURCE_URL` | string | `https://stage-api.sarex.io/resources/api/v1` | URL сервиса ресурсов (для `SYNC_RESOURCE_ID`) |
|
||
| `SYNC_RESOURCE_ID` | bool | `False` | При `True` `resource_id` заметки вычисляется по workspace → target → resource |
|
||
| `REGISTRY` | string | `cr.yandex/crp3ccidau046kdj8g9q/` | Реестр образов (используется вспомогательно) |
|
||
| `ENABLE_ND` | bool | `False` | Подключить роутер `nd_service` (`/api/v1/nd/*`) |
|
||
|
||
### ND-сервис (без префикса)
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `ND_JWT_ENABLE` | bool | `False` | Включить проверку JWT (`JWTBearer`) на части эндпоинтов НД |
|
||
| `ND_JWT_SECRET` | string | `""` | Секрет для подписи/проверки JWT |
|
||
| `ND_JWT_ALGORITHM` | string | `HS256` | Алгоритм JWT |
|
||
| `ND_ACCESS_TOKEN_EXPIRE_DAYS` | int | `30` | Срок жизни токена НД (дни) |
|
||
|
||
### Database (`PG_*`)
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `PG_LOGIN` | string | `""` | Пользователь PostgreSQL |
|
||
| `PG_PASSWORD` | string | `""` | Пароль пользователя |
|
||
| `PG_DB` | string | `""` | Имя базы данных |
|
||
| `PG_HOST` | string | `""` | Хост PostgreSQL |
|
||
| `PG_PORT` | string | `5432` | Порт PostgreSQL |
|
||
| `PG_SSL_MODE` | string | `disable` | Поле `ssl_mode` настроек (см. замечание ниже — фактически подключение всегда `verify-full`) |
|
||
| `DEBUG` | bool | `False` | Через `Field(env='DEBUG')`. При `True` хост БД принудительно `localhost:6432` (pgbouncer) |
|
||
|
||
> Итоговый DSN собирается в `PostgresSettings.url` как `postgresql://<login>:<password>@<host>:<port>/<db>`.
|
||
|
||
### Django / sarex-backend (`DJANGO_*`)
|
||
|
||
Клиент к основному backend (Django). Используется middleware `DjangoUserMiddleware` для аутентификации пользователя (запрос `/client/settings/`).
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `DJANGO_USE` | bool | `True` | При `False` аутентификация через Django отключается, используется тестовый пользователь (`is_admin=True`) |
|
||
| `DJANGO_HOST` | string | `http://localhost:8000` | Базовый хост Django (к нему добавляется `/api`) |
|
||
| `DJANGO_TIMEOUT` | int | `10` | Таймаут HTTP-клиента (сек) |
|
||
| `DJANGO_TOKEN` | string | `token` | Токен для служебных (sync) запросов |
|
||
|
||
### Documentations (`DOCUMENTATIONS_*`)
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `DOCUMENTATIONS_HOST` | string | `https://stage-api.sarex.io/documentations/api/v1` | URL сервиса документации |
|
||
|
||
### Workflows (`WORKFLOW_*`)
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `WORKFLOW_HOST` | string | `https://stage-api.sarex.io/workflows/api/v1` | URL сервиса обработки процессов |
|
||
| `WORKFLOW_TAG` | string | `dev` | Тег/канал workflow (`dev`/`stable`) |
|
||
| `WORKFLOW_TIMEOUT` | int | `30` | Таймаут HTTP-клиента (сек) |
|
||
|
||
### Attachments (`ATTACHMENT_*`)
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `ATTACHMENT_HOST` | string | `http://attachments-service.attachments-stage.svc.cluster.local:80/api/v1` | URL сервиса вложений |
|
||
| `ATTACHMENT_TIMEOUT` | int | `30` | Таймаут HTTP-клиента (сек) |
|
||
|
||
### Logger (`LOG_*`)
|
||
|
||
| Переменная | Тип | Значение по умолчанию | Назначение |
|
||
| --- | --- | --- | --- |
|
||
| `LOG_LEVEL` | string | `INFO` | Уровень логирования (`DEBUG`/`INFO`/…); при неизвестном значении используется `INFO` |
|
||
| `LOG_FORMAT` | string | `[%(asctime)s] [%(levelname)s] [%(filename)s]: %(message)s` | Формат сообщений лога |
|
||
|
||
## Переменные инфраструктуры, сборки и вспомогательных утилит
|
||
|
||
Не читаются кодом приложения, но участвуют в запуске/сборке/деплое.
|
||
|
||
| Переменная | Где используется | Назначение |
|
||
| --- | --- | --- |
|
||
| `TIMEOUT` | `docker-compose.yml`, `.helm/values.yaml`, `entrypoint.sh` | Таймаут воркеров gunicorn (`--timeout`) |
|
||
| `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` | `docker-compose.yml` (сервис `database`) | Параметры локального контейнера Postgres |
|
||
| `PGADMIN_DEFAULT_EMAIL` / `PGADMIN_DEFAULT_PASSWORD` | `docker-compose.yml` (сервис `pgadmin`) | Учётные данные pgAdmin для локальной разработки |
|
||
| `NPM_NEXUS_TOKEN` | (для фронтенда) | Токен приватного npm-реестра — здесь не используется |
|
||
|
||
## Переменные из Helm-чарта (`.helm/values.yaml`)
|
||
|
||
Чарт — `universal-chart` (зависимость в `.helm/Chart.yaml`). Обычные значения задаются в блоке `services.main.envs` и различаются по окружениям (`_default`/`stage`/`preprod`/`production`):
|
||
|
||
| Переменная | `_default` (stage) | `preprod` | `production` |
|
||
| --- | --- | --- | --- |
|
||
| `PG_SSL_MODE` | `verify-full` | — | — |
|
||
| `PG_PORT` | `6432` | — | — |
|
||
| `DJANGO_HOST` | `https://stage.sarex.io` | `https://lk.preprod.sarex.io` | `https://lk.sarex.io` |
|
||
| `BASE_HOST` | `https://stage-api.sarex.io/notes` | `https://api.preprod.sarex.io/notes` | `https://api.sarex.io/notes` |
|
||
| `TIMEOUT` | `120` | — | — |
|
||
| `FAAS_SERVICE` | `https://stage-api.sarex.io/lambdas` | `https://api.preprod.sarex.io/lambdas` | `https://api.sarex.io/lambdas` |
|
||
| `WORKSPACE_URL` | `https://stage-api.sarex.io/workspaces/api/v1` | `https://api.preprod.sarex.io/workspaces/api/v1` | `https://api.sarex.io/workspaces/api/v1` |
|
||
| `WORKFLOW_HOST` | `https://stage-api.sarex.io/workflows/api/v1` | `https://api.preprod.sarex.io/workflows/api/v1` | `https://api.sarex.io/workflows/api/v1` |
|
||
| `WORKFLOW_TAG` | `dev` | `stable` | `stable` |
|
||
| `RESOURCE_URL` | `https://stage-api.sarex.io/resources/api/v1` | `https://api.preprod.sarex.io/resources/api/v1` | `https://api.sarex.io/resources/api/v1` |
|
||
| `SYNC_RESOURCE_ID` | `0` | — | — |
|
||
| `ENABLE_ND` | `1` | `0` | `0` |
|
||
| `ATTACHMENT_HOST` | `…attachments-stage…` | `…attachments-preprod…` | `…attachments-prod…` |
|
||
|
||
Значения из секретов (блок `secretEnvs`, монтируются как env через `secretKeyRef`):
|
||
|
||
| Переменная | Секрет (`secretName`, stage) | Ключ (`secretKey`) |
|
||
| --- | --- | --- |
|
||
| `PG_DB` | `notes-postgresql-secret` | `database` |
|
||
| `PG_LOGIN` | `notes-postgresql-secret` | `username` |
|
||
| `PG_PASSWORD` | `notes-postgresql-secret` | `password` |
|
||
| `PG_HOST` | `notes-postgresql-secret` | `host` |
|
||
| `DJANGO_TOKEN` | `django-secret` | `token` |
|
||
|
||
Прочие значения чарта (не переменные приложения): `deployment.*` (имя, порт `8000`, реплики, ресурсы, probes отключены), `image.*`, `service.*` (`notes-backend-service`, в production — `backend-service`), `imagePullSecrets` (`dockerhub`), `ingress.enabled: false`.
|
||
|
||
## Переменные в CI (`.gitlab-ci.yml`)
|
||
|
||
Пайплайн подключает общие шаблоны из `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml`) и переключает окружение по ветке/тегу через `workflow.rules`:
|
||
|
||
| Условие | STAND | NAMESPACE | CHART_VERSION |
|
||
| --- | --- | --- | --- |
|
||
| ветка `stage` | `stage` | `aero` | `0.0.1-stage` |
|
||
| ветка `master` | `preprod` | `notes-preprod` | `0.0.1-preprod` |
|
||
| тег (`CI_COMMIT_TAG`) | `production` | `notes-prod` | `0.0.1-prod` |
|
||
|
||
Ключевые переменные: `SERVICE_NAME=notes-backend`, `DOCKERFILE_PATH`, `RELEASE_NAME`, `CHART_NAME`, `HELM_SET_ARGS` (проброс образа/окружения в `universal-chart`). Джобы `linter` (flake8), `typechecker` (mypy), `rest-api` (docker-compose + newman/postman) выполняются на MR/ветках/тегах.
|
||
|
||
## Замечания и потенциальные проблемы
|
||
|
||
- **SSL к БД всегда `verify-full`.** Поле `PG_SSL_MODE` (по умолчанию `disable`) в код подключения не попадает: и `PostgresSettings.create_session`, и `DBSessionMiddleware` жёстко передают `connect_args={'sslmode': "verify-full"}`. CA-сертификат монтируется из образа: `Dockerfile` копирует `yandex_pg.pem` → `/root/.postgresql/root.crt`.
|
||
- **`DEBUG` — общая переменная.** Она читается и корневым `Settings.debug`, и `PostgresSettings.debug` (`Field(env='DEBUG')`). При `DEBUG=true` хост БД принудительно становится `localhost:6432`, а также включается `ProfilingSqlQueryMiddleware`.
|
||
- **Приложение не загружает `.env` автоматически** — переменные нужно экспортировать в окружение (или задавать через `--env`/compose/helm).
|
||
- **Аутентификация.** При `DJANGO_USE=true` каждый публичный запрос (кроме путей с `/nd`) проверяется через Django `/client/settings/` по заголовку `Authorization` (опционально `Identity` для Zitadel). При `DJANGO_USE=false` подставляется тестовый администратор — использовать только локально.
|
||
- **Роутер НД включается флагом `ENABLE_ND`.** На stage он включён (`1`), на preprod/production выключен (`0`).
|
||
- Значение `SYNC_RESOURCE_ID` требует доступности `WORKSPACE_URL` и `RESOURCE_URL`; клиент к ним создаётся с `verify=False`.
|
||
|
||
## Минимальный набор для локального запуска
|
||
|
||
Postgres и pgAdmin поднимаются через `docker-compose up -d database pgadmin`. Минимально необходимо задать:
|
||
|
||
- `PG_LOGIN`, `PG_PASSWORD`, `PG_DB`, `PG_HOST`, `PG_PORT`
|
||
- `DJANGO_USE=false` (чтобы не требовать реальный Django-токен)
|
||
- при `ENABLE_ND=true` — `ND_JWT_*` при необходимости проверки токена
|
||
|
||
Остальные значения имеют рабочие дефолты (см. `.env.example`).
|