iac/apps/issues/CONFIGURATION.md

246 lines
19 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.

# Конфигурация проекта issues-backend
Документ описывает все переменные окружения и способы конфигурирования сервиса замечаний (Issues).
## Способы конфигурирования
Сервис настраивается **через переменные окружения**. Это Django-приложение; настройки читаются в `src/config/settings/base.py` и `src/config/settings/production.py` напрямую через `os.getenv(...)`. В начале `base.py` вызывается `load_dotenv()` ([`python-dotenv`](https://pypi.org/project/python-dotenv/)), поэтому при локальном запуске файл `.env` из рабочего каталога **подхватывается автоматически**.
Активный модуль настроек задаётся переменной `DJANGO_SETTINGS_MODULE` (в контейнере/Helm — `config.settings.production`) либо флагом `--settings=config.settings.production` у `manage.py`. Модуль `production.py` импортирует всё из `base.py` и переопределяет `DEBUG=False`, `ALLOWED_HOSTS`, `SIMPLE_JWT`, `LOGGING` и часть внешних хостов.
Отдельного конфиг-файла (yaml/toml) у приложения нет. Дополнительно на инфраструктурном уровне используются `config/settings/base.py` для Celery/Kafka/OTel и Helm-чарт для задания переменных в Kubernetes.
Источники переменных по способам запуска:
| Способ запуска | Откуда берутся переменные |
| --- | --- |
| Локально | Переменные окружения процесса и файл `.env` (грузится `load_dotenv()` в `base.py`) |
| Локально (Kafka) | `docker compose --file local-kafka-docker-compose.yml up -d` поднимает брокер; консьюмер — `manage.py consume_kafka` |
| Kubernetes (Helm) | `.helm/values.yaml`: блоки `envs` (обычные значения) и `secretEnvs` (значения из k8s-секретов) для каждого сервиса (`api`, `celery`, `celery-beat`, `kafka-app`) |
| CI/CD (GitLab) | `.gitlab-ci.yml`: общий шаблон `generic/common-ci` (`universal-pipeline.yaml`, ref `apps-business`); окружение выбирается по ветке/тегу |
Способы запуска процессов:
| Процесс | Команда | Назначение |
| --- | --- | --- |
| HTTP API | `uwsgi` (entrypoint) / `manage.py runserver` | REST API (DRF), OpenAPI-схема через drf-spectacular |
| Celery worker | `celery -A config worker -l info -E --concurrency=2` | Обработчик фоновых задач (`issues.tasks`, `issues.notifications`, `prescriptions.tasks`) |
| Celery beat | `celery -A config beat -l info` | Периодические задачи (ежедневный инкремент счётчиков, отчёт о просрочках) |
| Kafka consumer | `python3 run_kafka_app.py` / `manage.py consume_kafka` | Консьюмер Kafka (топики ассетов и замечаний) |
Порядок старта в контейнере задаётся `compose/server/entrypoint.sh` (миграции + запуск uWSGI по `compose/server/uwsgi.ini`). Базовый образ — `python:3.10-slim-bookworm` (`compose/server/Dockerfile`).
## Переменные приложения
Дефолт `—` означает, что явного значения по умолчанию в коде нет (`os.getenv` вернёт `None`); для корректной работы переменную нужно задать.
### Django и окружение
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `DJANGO_SETTINGS_MODULE` | string | `config.settings.production` (Helm) | Модуль настроек Django |
| `DJANGO_ADMIN_SECRET_KEY` | string | `''` | `SECRET_KEY` Django |
| `DJANGO_TOKEN` | string | `django-token` | Служебный токен |
| `ENVIRONMENT` | string | `production` | Окружение развёртывания (в т.ч. атрибут OTel) |
| `ENVIRONMENT_CLIENT` | string | `production` | Клиентское окружение (`stage`/`preprod`/`production`) |
### База данных (PostgreSQL)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `DATABASE_NAME` | string | — | Имя базы данных |
| `DATABASE_USER` | string | — | Пользователь БД |
| `DATABASE_PASSWORD` | string | — | Пароль пользователя БД |
| `DATABASE_HOST` | string | — | Хост PostgreSQL |
| `DATABASE_PORT` | int | — | Порт PostgreSQL |
> Движок — `django.db.backends.postgresql`. В Kubernetes значения приходят из секрета (`issues-postgresql-secret` для stage, `ya-pg-secret` для preprod/production), CA-сертификат монтируется как `/root/.postgresql/ca.crt`.
### Внешние сервисы (URL)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `SAREX_API` | string | — | Базовый API Sarex (`SAREX_HOST` по умолчанию равен ему) |
| `SAREX_HOST` | string | `= SAREX_API` | Хост Sarex |
| `AERO_HOST` | string | `https://stage.sarex.io` | Хост Aero |
| `AERO_PUBLIC_HOST` | string | `https://stage.sarex.io``production.py` — из env) | Публичный хост Aero |
| `BASE_AERO_URL` | string | `https://lk.sarex.io` | Базовый URL Aero |
| `BASE_AUTH_URL` | string | `https://lk.sarex.io` | Базовый URL аутентификации |
| `SERVICE_URL` | string | `https://lk.sarex.io` | URL сервиса |
| `GATEWAY_URL` | string | `https://lk.sarex.io` | URL gateway |
| `DOCUMENTATIONS_URL` | string | `https://lk.sarex.io` | URL сервиса документаций |
| `WORKFLOWS_URL` | string | `https://lk.sarex.io` | URL сервиса workflows |
| `WORKFLOWS_HOST` | string | `https://lk.sarex.io` | Хост workflows |
| `RESOURCES_API_HOST` | string | `https://lk.sarex.io``production.py``http://sarex-resources-service.resources-prod`) | Хост сервиса ресурсов (IAM) |
| `REVIEW_HOST` | string | `https://lk.sarex.io` | Хост сервиса review/flows |
| `INSPECTION_HOST` | string | `https://lk.sarex.io` | Хост сервиса инспекций |
| `EAV_HOST` | string | `http://eav-service.eav-stage` | Хост сервиса атрибутов (EAV) |
| `SAREX_USERNAME` | string | — | Логин для basic-auth Sarex |
| `SAREX_PASSWORD` | string | — | Пароль для basic-auth Sarex |
### RabbitMQ и Celery
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `RABBITMQ_USERNAME` | string | `mcc` | Пользователь брокера |
| `RABBITMQ_PASSWORD` | string | `mcc` | Пароль брокера |
| `RABBITMQ_HOSTNAME` | string | `rabbitmq-service` | Хост брокера |
| `RABBITMQ_VHOST` | string | `api` | Виртуальный хост |
| `REDIS_HOST` | string | `redis` | Хост Redis (result backend) |
| `REDIS_DB` | int | `0` | Номер БД Redis |
> `CELERY_BROKER_URL` собирается как `amqp://{user}:{password}@{hostname}/{vhost}` + `?heartbeat=30`. `CELERY_RESULT_BACKEND` — `redis://{REDIS_HOST}:6379/{REDIS_DB}`. Расписание beat: инкремент счётчиков `1:00`, отчёт о просрочках `6:00` (`Europe/Moscow`).
### Kafka
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `KAFKA_HOST` | string | — | Адрес брокера Kafka |
| `KAFKA_USERNAME` | string | — | Пользователь |
| `KAFKA_PASSWORD` | string | — | Пароль |
| `KAFKA_SSL_CAFILE` | string | — | Путь к CA-сертификату (в Helm — YandexInternalRootCA) |
| `KAFKA_EAV_ASSETS_TOPIC` | string | — | Топик трансляции ассетов (EAV) |
| `KAFKA_ISSUES_TOPIC` | string | — | Топик трансляции замечаний |
### S3 (Yandex Cloud)
Основное хранилище (`django-storages`, `S3Boto3Storage`):
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `YC_S3_ACCESS_KEY_ID` | string | — | Access key |
| `YC_S3_SECRET_ACCESS_KEY` | string | — | Secret key |
| `YC_S3_BUCKET_NAME` | string | — | Имя бакета |
| `YC_S3_ENDPOINT_URL` | string | — | Эндпоинт S3 |
| `YC_S3_VERIFY` | bool | `None` | Проверять TLS-сертификат (`"true"` → `True`) |
Хранилище предписаний (отдельный бакет):
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `PRESCRIPTION_S3_ACCESS_KEY_ID` | string | — | Access key |
| `PRESCRIPTION_S3_SECRET_ACCESS_KEY` | string | — | Secret key |
| `PRESCRIPTION_S3_BUCKET` | string | — | Имя бакета |
| `PRESCRIPTION_S3_ENDPOINT_URL` | string | — | Эндпоинт S3 |
### Почта (Mailgun / SMTP)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `ENABLE_MAILGUN` | bool | `True` | Использовать Mailgun |
| `MAILGUN_BASE_URL` | string | `https://api.mailgun.net/v3/mg.sarex.io` | URL API Mailgun |
| `MAILGUN_API_KEY` | string | (задан дефолт в коде) | API-ключ Mailgun (в проде — из секрета) |
| `EMAIL_FROM` | string | `hello@sarex.io` | Адрес отправителя |
| `EMAIL_DOCKER_IMAGE` | string | `cr.yandex/.../notification:email` | Образ сервиса нотификаций |
| `USE_NOTIFICATIONS` | bool | `True` | Включить отправку уведомлений (`False`/`false`/`0` → выкл.) |
| `SMTP_HOST` | string | `None``production.py``""`) | SMTP-хост (альтернатива Mailgun) |
| `SMTP_PORT` | int | `None` | SMTP-порт |
### Предписания (workflow)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `PRESCRIPTION_WF_IMAGE` | string | — | Образ workflow генерации предписаний |
| `DOCX_TO_PDF_IMAGE` | string | — | Образ конвертера DOCX→PDF |
| `PRESCRIPTION_WF_RESULT_PATH` | string | — | Путь/бакет результата |
| `PRESCRIPTION_WF_CALLBACK` | string | — | Образ webhook-caller |
| `PRESCRIPTION_INTERNAL_HOST` | string | — | Внутренний хост колбэков предписаний |
| `EXPORT_WF_CROPPING_DOCKER_IMAGE` | string | `cr.yandex/.../crop-issue-pin-area:prod` | Образ кропа области пина для экспорта |
### OpenTelemetry
Трейсинг подключается только если `USE_OTEL` истинно (`django_otel_tools`).
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `USE_OTEL` | bool | `False` | Включить трейсинг/логирование через OTel |
| `SERVICE_NAME` | string | `issues-backend.sarex-issues` | Имя сервиса в трейсах |
| `TRACER_ENDPOINT` | string | `localhost:4375` | Адрес OTLP-коллектора |
| `USE_INSECURE` | bool | `False` | Небезопасное (без TLS) подключение к коллектору |
| `MODULE` | string | `issues` | Атрибут трейсов |
| `TEAM` | string | `proc_team` | Атрибут трейсов |
| `COMPONENT` | string | `backend` | Атрибут трейсов |
## Переменные инфраструктуры
Не читаются кодом приложения напрямую (или используются вспомогательными компонентами), но участвуют в запуске/деплое.
| Переменная | Где используется | Назначение |
| --- | --- | --- |
| `API_ADDRESS` | Helm (`envs`) | Порт uWSGI (`8000`) |
| `SENTRY_KEY` | Helm (`envs`) | DSN Sentry (задан для stage) |
| `SAREX_MAILER_URL` | Helm (`envs`) | URL сервиса рассылок (`http://mailer-service.mailer:8000`) |
| `MAILGUN_HOST` | Helm (`envs`) | Хост Mailgun на уровне чарта |
| `NPM_TOKEN`, `BUILD_ENV` | CI/Dockerfile | Сборка (актуально для фронтенда) |
## Переменные из Helm-чарта (`.helm/values.yaml`)
Чарт — обёртка над `universal-chart`. Определены четыре сервиса: `api`, `celery`, `celery-beat`, `kafka-app`. Обычные значения (`envs`) задаются для окружений `_default`/`stage`/`preprod`/`production` (различаются адресами БД/сервисов, топиками Kafka, образами, `SERVICE_NAME`, `TRACER_ENDPOINT`).
Значения из секретов (блок `secretEnvs`, монтируются через `secretKeyRef`):
| Переменная | Секрет (stage / preprod-prod) | Ключ |
| --- | --- | --- |
| `KAFKA_USERNAME` | `issues-kafka-secret` / `yc-kafka-secret` | `username` |
| `KAFKA_PASSWORD` | `issues-kafka-secret` / `yc-kafka-secret` | `password` |
| `KAFKA_HOST` | `issues-kafka-secret` / `yc-kafka-secret` | `host` |
| `SAREX_USERNAME` | `sarex-auth` | `username` |
| `SAREX_PASSWORD` | `sarex-auth` | `password` |
| `DATABASE_HOST` | `issues-postgresql-secret` / `ya-pg-secret` | `host` |
| `DATABASE_NAME` | `issues-postgresql-secret` / `ya-pg-secret` | `database` |
| `DATABASE_PORT` | `issues-postgresql-secret` / `ya-pg-secret` | `port` |
| `DATABASE_USER` | `issues-postgresql-secret` / `ya-pg-secret` | `username` |
| `DATABASE_PASSWORD` | `issues-postgresql-secret` / `ya-pg-secret` | `password` |
| `YC_S3_ACCESS_KEY_ID` | `issues-s3-secret` / `yc-s3-secret` | `key_id` |
| `YC_S3_SECRET_ACCESS_KEY` | `issues-s3-secret` / `yc-s3-secret` | `access_key` |
| `YC_S3_BUCKET_NAME` | `issues-s3-secret` / `yc-s3-secret` | `storage_bucket_name` |
| `YC_S3_ENDPOINT_URL` | `issues-s3-secret` / `yc-s3-secret` | `endpoint_url` |
| `RABBITMQ_VHOST` | `issues-rabbitmq-secret` / `rabbitmq-secret` | `vhost` |
| `RABBITMQ_USERNAME` | `issues-rabbitmq-secret` / `rabbitmq-secret` | `user` |
| `RABBITMQ_HOSTNAME` | `issues-rabbitmq-secret` / `rabbitmq-secret` | `host` |
| `RABBITMQ_PASSWORD` | `issues-rabbitmq-secret` / `rabbitmq-secret` | `password` |
| `MAILGUN_API_KEY` | `mailgun-secret` | `api-key` |
| `DJANGO_TOKEN` | `django-secret` | `token` |
| `DJANGO_ADMIN_SECRET_KEY` | `django-admin-secret` | `secret_key` |
| `PRESCRIPTION_S3_ACCESS_KEY_ID` | `prescription-s3-secret` | `key_id` |
| `PRESCRIPTION_S3_SECRET_ACCESS_KEY` | `prescription-s3-secret` | `access_key` |
| `PRESCRIPTION_S3_BUCKET` | `prescription-s3-secret` | `storage_bucket_name` |
| `PRESCRIPTION_S3_ENDPOINT_URL` | `prescription-s3-secret` | `endpoint_url` |
Дополнительно чарт монтирует конфиг uWSGI (`uwsgi-configmap` → `/opt/server/uwsgi.ini`, только сервис `api`), CA-сертификат PostgreSQL (`yc-ch-certificate` → `/root/.postgresql/ca.crt`) и внутренний CA Яндекса (`YandexInternalRootCA.crt`).
## Переменные в CI (`.gitlab-ci.yml`)
Пайплайн подключает общие шаблоны из `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml`, ref `apps-business`). Основные переменные: `SERVICE_NAME=issues`, `DOCKERFILE_PATH=./compose/server/Dockerfile`. Окружение выбирается по ветке/тегу:
| Условие | STAND | Namespace | CHART_VERSION |
| --- | --- | --- | --- |
| ветка `stage` | `stage` | `proc` | `0.0.1-stage` |
| ветка `master` | `preprod` | `issues-preprod` | `0.0.1-preprod` |
| тег (`CI_COMMIT_TAG`) | `production` | `issues-prod` | `0.0.1-prod` |
`HELM_SET_ARGS` для каждого окружения проставляет образы четырёх сервисов (`api`, `celery`, `celery-beat`, `kafka-app`), `universal-chart.global.env` и метаданные коммита (`commitSha`, `gitlabUri`, `gitlabJobUrl`, `owner`).
## Замечания и потенциальные проблемы
- В отличие от FastAPI-сервисов, переменные не имеют единого префикса и читаются напрямую через `os.getenv`. Файл `.env` подхватывается автоматически (`load_dotenv()` в `base.py`).
- `DEBUG` в `base.py` установлен в `True`; в `production.py` переопределяется на `False`. Для боевого окружения обязателен модуль `config.settings.production`.
- `MAILGUN_API_KEY` имеет захардкоженный дефолт в коде — в реальных окружениях его нужно переопределять секретом.
- Ряд переменных без дефолта (`DATABASE_*`, `KAFKA_*`, `YC_S3_*`, `SAREX_USERNAME`/`SAREX_PASSWORD`, `PRESCRIPTION_WF_*`) обязательны для полноценной работы соответствующих подсистем.
- Переменные `SAREX_MAILER_URL`, `MAILGUN_HOST`, `SENTRY_KEY`, `API_ADDRESS` задаются в Helm, но не читаются кодом приложения напрямую.
## Минимальный набор для локального запуска
Postgres, RabbitMQ, Redis и Kafka поднимаются локально; приложение — `python ./src/manage.py runserver --settings=config.settings.production`, консьюмер — `manage.py consume_kafka`. Минимально необходимо задать:
- `DJANGO_ADMIN_SECRET_KEY`
- `DATABASE_NAME`, `DATABASE_USER`, `DATABASE_PASSWORD`, `DATABASE_HOST`, `DATABASE_PORT`
- `RABBITMQ_USERNAME`, `RABBITMQ_PASSWORD`, `RABBITMQ_HOSTNAME`, `RABBITMQ_VHOST`, `REDIS_HOST`
- `KAFKA_HOST`, `KAFKA_USERNAME`, `KAFKA_PASSWORD`, `KAFKA_EAV_ASSETS_TOPIC`, `KAFKA_ISSUES_TOPIC` (для консьюмера)
- `YC_S3_*` (для работы с файлами) и при необходимости `PRESCRIPTION_S3_*`
- внешние URL: `SAREX_API`, `AERO_HOST`, `GATEWAY_URL`, `DOCUMENTATIONS_URL`, `WORKFLOWS_URL`, `RESOURCES_API_HOST`, `EAV_HOST`, `INSPECTION_HOST`, `REVIEW_HOST`
- почта: `ENABLE_MAILGUN` + `MAILGUN_*` **или** `SMTP_HOST`/`SMTP_PORT`
- `USE_OTEL=False` для локальной разработки
Готовые значения-примеры приведены в `.env.example`.