iac/apps/checklists/CONFIGURATION.md

172 lines
14 KiB
Markdown
Raw 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.

# Конфигурация проекта checklists-backend
Документ описывает все переменные окружения и способы конфигурирования сервиса.
## Способы конфигурирования
Сервис настраивается **только через переменные окружения**. Разбор выполняется в `src/config.py` через библиотеку [`pydantic-settings`](https://docs.pydantic.dev/latest/concepts/pydantic_settings/).
В отличие от единого класса настроек, конфигурация разбита на несколько независимых классов `BaseSettings`, у каждого — **свой** `env_prefix` (плоские имена, без вложенного разделителя):
| Класс | `env_prefix` | Раздел |
| --- | --- | --- |
| `Config` | *(нет префикса)* | `debug` |
| `HTTPAppConfig` | `HTTP_APP_` | Параметры HTTP-приложения/uvicorn |
| `DatabaseConfig` | `DATABASE_` | Подключение к PostgreSQL |
| `OTELConfig` | `OTEL_` | Трейсинг/логи OpenTelemetry |
| `JWTAuthConfig` | `JWT_AUTH_` | Аутентификация по JWT |
Подклассы подключаются к корневому `Config` как поля со значениями по умолчанию (`http_app`, `database`, `otel`, `jwt_auth`) и читают окружение в момент импорта. Отдельного конфиг-файла (yaml/toml) у приложения нет.
Особенности:
- **`.env` не загружается автоматически** — в `config.py` не задан `env_file`, зависимости `python-dotenv` нет. Файл `.env.template` — это шаблон; переменные нужно экспортировать в окружение самому (напр. `set -a && . ./.env && set +a`) либо задавать через `--env`/манифесты k8s.
- Помимо переменных приложения, для запуска нужны две инфраструктурные переменные Piccolo: `PYTHONPATH=src` и `PICCOLO_CONF=db.config` (заданы в `.env.template` и в `Dockerfile`).
Источники переменных по способам запуска:
| Способ запуска | Откуда берутся переменные |
| --- | --- |
| Локально (`make run`) | Переменные окружения процесса. `.env.template` — шаблон, приложение его **не подхватывает** автоматически |
| Контейнер | `docker/http/Dockerfile` задаёт `PYTHONPATH`/`PICCOLO_CONF`; прочие переменные пробрасываются при запуске |
| Kubernetes (Helm) | `.helm/values.yaml`: блоки `envs` (обычные значения) и `secretEnvs` (значения из k8s-секретов) чарта `universal-chart` |
| CI/CD (GitLab) | `.gitlab-ci.yml`: переменные пайплайна (`workflow.rules`) и `HELM_SET_ARGS` |
Способы запуска (`Makefile`):
| Команда | Точка входа | Назначение |
| --- | --- | --- |
| `make run` | `src/cmd/http/main.py``uvicorn` (factory `app.http:create_app`) | HTTP API |
| `make migrate` | `piccolo migrations forwards all` | Применение миграций БД |
| `make migrations` | `piccolo migrations new checklists --auto` | Генерация новой миграции |
| `make format` / `make format-check` | `ruff` | Форматирование/линт |
Порядок запуска в контейнере (`docker/http/entrypoint.sh`): сначала выполняются миграции (`piccolo migrations forwards all`), затем стартует приложение (`src/cmd/http/main.py`). Uvicorn запускается в режиме фабрики; `reload` включается при `DEBUG=true`, число воркеров — из `HTTP_APP_WORKERS`.
## Переменные приложения
В столбце «Переменная» указано полное имя (префикс + поле). Дефолт `—` означает, что значение обязательно.
### App (`Config`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `DEBUG` | bool | `True` | Режим отладки. Влияет на `reload` uvicorn, логирование SQL-запросов Piccolo (`log_queries`/`log_responses`), а также на `production`-флаг и `debug` piccolo-admin |
### HTTP-приложение (`HTTP_APP_*`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `HTTP_APP_HOST` | string | `0.0.0.0` | Адрес прослушивания |
| `HTTP_APP_PORT` | int | `8000` | Порт |
| `HTTP_APP_ROOT_PATH` | string | `""` | Root path (префикс за реверс-прокси; в k8s — `/checklists`) |
| `HTTP_APP_WORKERS` | int | `1` | Число воркеров uvicorn |
| `HTTP_APP_ADMIN_ENABLE` | bool | `True` | Монтировать ли piccolo-admin по пути `/admin/` |
### Database (`DATABASE_*`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `DATABASE_HOST` | string | `postgres` | Хост PostgreSQL |
| `DATABASE_PORT` | int | `5432` | Порт PostgreSQL |
| `DATABASE_NAME` | string | `postgres` | Имя базы данных |
| `DATABASE_USER` | string | `postgres` | Пользователь БД |
| `DATABASE_PASSWORD` | string | `postgres` | Пароль пользователя БД |
Подключение собирается в `src/db/config.py` (`PostgresEngine`). SSL-параметров в настройках нет; в prod TLS обеспечивается на уровне подключения/CA-сертификата (см. `docker/http/ca.crt`).
### OpenTelemetry (`OTEL_*`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `OTEL_ENABLE` | bool | `False` | Включить трейсинг/логи OTEL. При `True` подключаются `fastapi-otel-tools` и инструментирование FastAPI |
| `OTEL_URL` | string | `http://signoz-otel-collector-external.signoz.svc.cluster.local:4317` | Адрес OTLP-коллектора |
| `OTEL_SERVICE_NAME` | string | `checklists-backend.checklists-stage` | Имя сервиса в трейсах |
| `OTEL_INSECURE` | bool | `True` | Небезопасное (без TLS) подключение к коллектору |
> При `OTEL_ENABLE=true` `access_log` uvicorn отключается (логи идут через OTEL-обработчик).
### Auth (`JWT_AUTH_*`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `JWT_AUTH_ENABLE` | bool | `False` | Включить `JWTAuthMiddleware`. При `False` middleware не подключается, и в контекст подставляется дефолтный пользователь (для локальной разработки) |
| `JWT_AUTH_PUBLIC_KEY` | string | `key` | Публичный RSA-ключ для JWT (алгоритм `RS512`) |
## Переменные инфраструктуры и сборки
Не читаются кодом приложения, но участвуют в запуске/сборке.
| Переменная | Где используется | Назначение |
| --- | --- | --- |
| `PYTHONPATH` | `.env.template`, `Dockerfile` | Путь к исходникам (`src`) |
| `PICCOLO_CONF` | `.env.template`, `Dockerfile` | Путь к конфигу Piccolo (`db.config`) |
| `SERVICE_NAME` | `.gitlab-ci.yml` | Имя сервиса (`checklists-backend`) |
| `DOCKERFILE_PATH` | `.gitlab-ci.yml` | Путь к Dockerfile (`./docker/http/Dockerfile`) |
| `IMAGE_NAME` | `.gitlab-ci.yml` (`HELM_SET_ARGS`) | Имя собираемого образа |
| `CHART_NAME` / `CHART_VERSION` / `RELEASE_NAME` | `.gitlab-ci.yml` | Параметры релиза Helm |
Базовый образ — `python:3.13-slim-bookworm`; менеджер зависимостей — `uv` (`uv sync --locked`). В образ добавляется CA-сертификат Yandex (`docker/http/ca.crt`).
## Переменные из Helm-чарта (`.helm/values.yaml`)
Сервис деплоится подключаемым чартом `universal-chart` (OCI-зависимость). Окружение выбирается ключом `universal-chart.global.env` (`stage`/`preprod`/`production`); для каждой переменной значение берётся из блока с ключом текущего окружения либо из `_default`.
Обычные значения (блок `envs`) переопределяют дефолты кода, в частности:
| Переменная | Значение в чарте |
| --- | --- |
| `HTTP_APP_ROOT_PATH` | `/checklists` |
| `HTTP_APP_WORKERS` | `3` |
| `HTTP_APP_ADMIN_ENABLE` | `true` |
| `DATABASE_PORT` | `6432` (PgBouncer) |
| `DATABASE_NAME` | `checklists_db` (stage), `checklists` (preprod/production) |
| `OTEL_ENABLE` | `true` |
| `OTEL_URL` | `http://otel-collector.opentelemetry-collector.svc.cluster.local:4317` |
| `OTEL_SERVICE_NAME` | `checklists-backend.proc` (stage), `…checklists-preprod`, `…checklists-prod` |
| `JWT_AUTH_ENABLE` | `true` |
| `DEBUG` | `false` |
Значения из секретов (блок `secretEnvs`, монтируются как env через `secretKeyRef`):
| Переменная | Секрет (`secretName`) | Ключ (`secretKey`) |
| --- | --- | --- |
| `DATABASE_USER` | `checklists-postgresql-secret` (stage) / `ya-pg-secret` (preprod, production) | `user` |
| `DATABASE_PASSWORD` | `checklists-postgresql-secret` / `ya-pg-secret` | `password` |
| `DATABASE_HOST` | `checklists-postgresql-secret` / `ya-pg-secret` | `host` |
| `JWT_AUTH_PUBLIC_KEY` | `jwt-secret` | `public-key` |
Прочие значения чарта (не переменные приложения): `deployment.*` (имя, реплики — 1 по умолчанию, 2 в production, ресурсы), `image.*`, `service.*` (ClusterIP, порт `80``8000`). Проверки `liveness`/`readiness` отключены.
## Переменные в CI (`.gitlab-ci.yml`)
Пайплайн подключает общие шаблоны из `generic/common-ci` (`universal-pipeline.yaml`, `common-security-scan.yaml`) и переключает окружение по ветке/тегу через `workflow.rules`:
| Условие | STAND | Namespace |
| --- | --- | --- |
| ветка `stage` | `stage` | `proc` |
| ветка `master` | `preprod` | `checklists-preprod` |
| тег (`CI_COMMIT_TAG`) | `production` | `checklists-prod` |
Ключевые переменные пайплайна: `SERVICE_NAME`, `DOCKERFILE_PATH`, `RELEASE_NAME`, `CHART_NAME`, `CHART_VERSION`, `K8S_HUSTLER_BRANCH`, `HELM_SET_ARGS` (проброс `image.name`, `global.env`, метаданных коммита). Job `lint` прогоняет `ruff check`/`ruff format --check` на образе `uv`.
## Замечания и потенциальные проблемы
- Приложение **не загружает `.env` автоматически** — переменные нужно экспортировать в окружение вручную либо задавать в манифестах.
- Аутентификация JWT в коде выполняет разбор токена с `options={"verify_signature": False}` в обоих режимах (sarex-backend и Zitadel) — подпись фактически не проверяется на уровне приложения, доверие обеспечивается сетевым слоем (Istio). При `JWT_AUTH_ENABLE=false` middleware не подключается и используется дефолтный пользователь из `entity/context.py`.
- Внутренние эндпоинты (`/internal/*`) аутентификации на уровне приложения не требуют.
- SSL-настроек подключения к БД в коде нет; в prod используется PgBouncer (`DATABASE_PORT=6432`) и CA-сертификат, вшитый в образ.
- Piccolo-admin доступен по `/admin/` при `HTTP_APP_ADMIN_ENABLE=true`; в режиме `DEBUG=false` он поднимается в `production`-режиме.
## Минимальный набор для локального запуска
Нужен доступный PostgreSQL. Помимо `PYTHONPATH=src` и `PICCOLO_CONF=db.config`, для запуска достаточно значений по умолчанию — обязательных переменных без дефолта нет. Практически стоит задать:
- `DEBUG` (`true` локально)
- `HTTP_APP_HOST`, `HTTP_APP_PORT`
- `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_NAME`, `DATABASE_USER`, `DATABASE_PASSWORD`
- `JWT_AUTH_ENABLE` (`false` для локальной разработки — тогда используется дефолтный пользователь)
- `OTEL_ENABLE` (`false` локально)
Готовые значения-примеры приведены в `.env.example`.