iac/apps/processing/workflows-api.CONFIGURATION.md

22 KiB
Raw Permalink Blame History

Конфигурация проекта workflows-api

workflows-api — HTTP-сервис (Go 1.24, фреймворк Fiber v2) для работы с workflow: создание, чтение, перезапуск задач, отмена запусков, приоритизация. Хранилище — PostgreSQL. Трейсинг — OpenTelemetry (через внешнюю библиотеку gitlab.sarex.io/infra/golang-fiber-otel-tools).

Способы конфигурирования

Конфигурация читается только из переменных окружения. Используется библиотека github.com/ilyakaznacheev/cleanenv (cleanenv.ReadEnv). Файлы конфигурации (.yaml, .json) не читаются — вызывается именно ReadEnv, а не ReadConfig.

  • Префикс у переменных отсутствует — используются «плоские» имена (POSTGRES_ADDRESS, HTTP_HOST и т. п.).
  • Вложенность структуры Config описывается через встроенные (embedded) структуры (App, Log, HTTP, pgxconnection.Postgres, TRACER, Execution), но на имена переменных это не влияет — теги env заданы плоско.
  • Значения по умолчанию задаются тегом env-default.
  • Булевы значения cleanenv принимает как true/false, а также 1/0 (в Helm используется числовая форма).

Точка сборки конфигурации — config/config.go, функция config.New(). Отдельно, для запуска миграций, вторая структура pkg/postgres/gopg.Postgres читается своим вызовом cleanenv.ReadEnv в gopg.GetPgConnectionWithoutConfig()у неё те же имена переменных, но частично другие значения по умолчанию (см. «Замечания»).

Способы запуска

Способ запуска Откуда берутся переменные
Бинарь httpserver (production, Dockerfile ENTRYPOINT ["/httpserver", "migrate"]) Переменные окружения контейнера (в k8s — из Helm-чарта: блоки envs и secretEnvs)
Бинарь migrations (отдельный ранер миграций) Переменные окружения контейнера
Локальный запуск через air (.air.toml, hot-reload, сборка ./cmd/httpserver/main.go) Переменные окружения оболочки / .env (подхватываются вручную), значения по умолчанию из кода
docker-compose up (docker-compose.yaml) environment: в compose + значения по умолчанию из кода

Точки входа и вспомогательные скрипты

Файл / скрипт Назначение
cmd/httpserver/main.go Основная точка входа. Если передан хотя бы один аргумент (например migrate) — сначала выполняет миграции (go-pg-migrations), затем поднимает Fiber-сервер
cmd/migrations/main.go Отдельный бинарь только для миграций (без запуска сервера)
Dockerfile Multi-stage сборка: собирает httpserver и migrations, ENTRYPOINT ["/httpserver", "migrate"]
entrypoint.sh Скрипт-обёртка (/go/bin/migrations migrate/go/bin/httpserver). Не используется Dockerfile и ссылается на несуществующие пути бинарей — устаревший артефакт (см. «Замечания»)
.air.toml Конфиг hot-reload air для локальной разработки
docker-compose.yaml Локальный стенд: PostgreSQL 14-alpine + сборка API. Блок migrations закомментирован
Makefile Юнит-тесты, генерация моков, поднятие/сборка контейнера БД (.docker/postgres)
.docker/postgres/Dockerfile Образ локальной БД для make container-run-deps

Порядок старта контейнера (production)

  1. Контейнер стартует с ENTRYPOINT ["/httpserver", "migrate"].
  2. httpserver видит аргумент migrate (len(os.Args) > 1) → открывает подключение к БД через go-pg (gopg.GetPgConnectionWithoutConfig, читает env заново) и прогоняет миграции из cmd/migrations/migrationfiles.
  3. После миграций поднимается Fiber-приложение (server.Newserver.Run), подключается пул pgx (pgxconnection.GetPgConnection), при TRACER_USE=true инициализируется трейсер/otel-логгер.
  4. Сервер слушает адрес из HTTP_HOST. Health-check — GET /ping.

Переменные приложения

Ниже — переменные, которые реально читает код (config/config.go + pkg/postgres/pgxconnection/postgres.go).

App (config/config.go)

Переменная Тип Значение по умолчанию Назначение
APP_NAME string workflows-api Имя приложения (App.Name)
APP_VERSION string v1 Версия приложения (App.Version)

Log

Переменная Тип Значение по умолчанию Назначение
LOG_LEVEL string info Уровень логирования (logging.NewLogger)

HTTP

Переменная Тип Значение по умолчанию Назначение
HTTP_HOST string 0.0.0.0:8000 Адрес и порт прослушивания Fiber-сервера
PUBLIC_KEY string — (пусто) PEM-публичный ключ (PKIX) для проверки JWT Sarex. Обязателен: при пустом значении auth.New вызывает panic на старте
HTTP_BODY_LIMIT int 268435456 (256 MiB) Максимальный размер тела запроса (fiber.Config.BodyLimit)
HTTP_READ_BUFFER_SIZE int 98304 (96 KiB) Размер буфера чтения (fiber.Config.ReadBufferSize)

Database (pkg/postgres/pgxconnection)

Переменная Тип Значение по умолчанию Назначение
POSTGRES_ADDRESS string localhost Хост PostgreSQL
POSTGRES_DB string processing_db Имя базы данных
POSTGRES_USER string sarex Пользователь БД
POSTGRES_PASSWORD string sarex Пароль БД
POSTGRES_PORT string 5432 Порт PostgreSQL
POSTGRES_POOL_SIZE int 3 Размер пула (используется только для логирования; фактический размер пула pgx задаётся строкой подключения)
ENABLE_SQL_QUERY bool true Флаг логирования SQL. Читается в конфиг, но нигде не используется (см. «Замечания»)
YC-PG-CERTIFICATE string — (пусто) CA-сертификат (PEM) для TLS-подключения к БД. Непустое значение включает TLS
POSTGRES_SSL_USE bool false Включение TLS-подключения к БД

Tracer (config.TRACER, OpenTelemetry)

Переменная Тип Значение по умолчанию Назначение
TRACER_USE bool false Включить трейсинг/otel-логгер и otelfiber-middleware
TRACER_HOST string localhost:4317 Адрес OTLP-коллектора (gRPC)
TRACER_USE_INSECURE bool true Небезопасное (без TLS) подключение к коллектору
SERVICE_NAME string wf-test-db Имя сервиса в трейсах
TRACER_LOGGER_NAME string tracer_logger Имя otel-логгера

Execution (лимиты ресурсов задач, config.Execution)

Переменная Тип Значение по умолчанию Назначение
MAX_CPU_REQUESTS string 25 Максимально допустимый CPU-request в конфиге execution задачи (валидация через k8s.io/apimachinery/resource)
MAX_MEMORY_REQUESTS string 300Gi Максимально допустимый memory-request в конфиге execution задачи

Переменные инфраструктуры, сборки и вспомогательных утилит

Переменные Makefile (значения по умолчанию, переопределяются через make VAR=...):

Переменная Значение по умолчанию Назначение
OCI docker Контейнерный движок (docker/podman)
WF_API_CONTAINER__NETWORK_NAME wf-api-network Имя bridge-сети для локальных контейнеров
WF_API_DATABASE_IMAGE__TAG wf-api-database Тег образа локальной БД
WF_API_DATABASE_CONTAINER__NAME wf-api-database-c Имя контейнера БД
WF_API_DATABASE__VOLUME_NAME wf-api-data Имя тома данных БД
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB / POSTGRES_PORT берутся из окружения Прокидываются в контейнер БД при container-run-database

Переменные сборки образа (Dockerfile):

Переменная Значение Назначение
CGO_ENABLED 0 Статическая сборка Go
GOOS linux Целевая ОС
GOARCH amd64 Целевая архитектура

Переменные .docker/postgres/Dockerfile и docker-compose.yaml (локальный стенд):

Переменная Значение Назначение
POSTGRES_DB processing_db БД локального PostgreSQL
POSTGRES_USER processing Пользователь локального PostgreSQL
POSTGRES_PASSWORD processing Пароль локального PostgreSQL
POSTGRES_ADDRESS database (в compose для сервиса api) Хост БД внутри сети compose
POSTGRES_SSL_USE false Отключение TLS локально

Переменные из Helm-чарта

Деплой выполняется зависимостью-чартом universal-chart (.helm/Chart.yaml, версия 0.1.7), значения — в .helm/values.yaml. Значения даются по стендам через ключи _default / stage / preprod / production.

Обычные переменные (services.workflows-api.envs)

Переменная Значение (_default) Значения по стендам / примечание
POD_NAME $(K8S_POD_NAME) Имя пода. Кодом не читается
POSTGRES_POOL_SIZE 3 Размер пула (логирование)
HTTP_HOST 0.0.0.0:8080 Адрес прослушивания в k8s (порт 8080)
S3_SERVICE_ACCOUNT /etc/sarex/yc-s3/yc-s3-service-account.json Кодом не читается
DJANGO_HOST https://stage.sarex.io stage: stage.sarex.io, preprod: preprod.sarex.io, production: lk.sarex.io. Кодом не читается
OBSERVABILITY_TRACE_COLLECTOR_ENDPOINT opentelemetry-collector.observability.svc.cluster.local:4318 Одинаково на всех стендах. Кодом не читается (легаси-пакет observavility не подключён)
ENABLE_SQL_QUERY 0 Читается в конфиг, но не используется
POSTGRES_SSL_USE 1 preprod: true, остальные 1
ENABLE_OBSERVABILITY 1 stage 1, preprod 0, production 1. Кодом не читается
TRACER_USE 1 Включает трейсинг
TRACER_HOST signoz-otel-collector.signoz.svc.cluster.local:4317 preprod/production: signoz-otel-collector-external.signoz.svc.cluster.local:4317
SERVICE_NAME workflows-api.processing-stage stage: workflows-api.platform, preprod: workflows-api.processing-preprod, production: workflows-api.processing-prod
TRACER_USE_INSECURE 1 Небезопасное подключение к коллектору
TRACER_LOGGER_NAME tracer_logger Имя otel-логгера
MAX_CPU_REQUESTS 25 Лимит CPU-request задач
MAX_MEMORY_REQUESTS 300Gi Лимит memory-request задач

Секретные переменные (services.workflows-api.secretEnvs)

Переменная Секрет (secret_name) Ключ (secret_key)
POSTGRES_ADDRESS _default/stage: processing-postgresql-secret; preprod/production: ya-pg-secret host
POSTGRES_PORT _default/stage: processing-postgresql-secret; preprod/production: ya-pg-secret port
POSTGRES_DB _default/stage: processing-postgresql-secret; preprod/production: ya-pg-secret database
POSTGRES_USER _default/stage: processing-postgresql-secret; preprod/production: ya-pg-secret _default/stage: user; preprod/production: username
POSTGRES_PASSWORD _default/stage: processing-postgresql-secret; preprod/production: ya-pg-secret password
PUBLIC_KEY _default/stage: jwt-secret; preprod/production: public-key _default/stage: public_key; preprod/production: key
YC-PG-CERTIFICATE _default/stage: processing-postgresql-secret; preprod/production: yc-pg-certificate _default/stage: ca.crt; preprod/production: certificate

Прочие параметры чарта

  • Порт деплоймента: 8080; сервис ClusterIP, targetPort: 8080, port: 80 (stage: 8000).
  • Имя сервиса: workflows-service (stage: workflows-api-service).
  • Реплики: _default/stage — 1, preprod/production — 2.
  • Ресурсы пода: requests _default 100Mi / 100m, preprod/production 200Mi / 200m.
  • Пробы: liveness и readiness — httpGet /ping на порту 8080.
  • serviceAccount: workflows-api-sa.
  • imagePullSecrets: dockerhub. Образ: cr.yandex/crp3ccidau046kdj8g9q/workflows-api.

Переменные в CI

.gitlab-ci.yml подключает общие пайплайны generic/common-ci (common-security-scan.yaml, universal-pipeline.yaml@apps-business). Глобальные переменные:

Переменная Значение Назначение
SERVICE_NAME workflows-api Имя сервиса в пайплайне
DOCKERFILE_PATH Dockerfile Путь к Dockerfile
BUILD_ARGS --build-arg CI_COMMIT_SHORT_SHA=${CI_COMMIT_SHORT_SHA} Аргументы сборки образа
CI_TRIGGER_SOURCE app Источник триггера

Маппинг ветка/тег → стенд и namespace (workflow.rules):

Условие STAND NAMESPACE CHART_VERSION K8S_HUSTLER_BRANCH env (universal-chart.global.env)
CI_COMMIT_BRANCH == "stage" stage platform 0.0.1-stage universal-chart-stage stage
CI_COMMIT_BRANCH == "master" preprod processing-preprod 0.0.1-preprod universal-chart-preprod preprod
CI_COMMIT_TAG (любой тег) production processing-prod 0.0.1-prod universal-chart-production production
CI_PIPELINE_SOURCE == "merge_request_event" сборка образа выключена (ENABLE_BUILD_IMAGE=false)

Во всех деплой-правилах через HELM_SET_ARGS пробрасываются IMAGE_NAME, commitSha=${CI_COMMIT_SHA}, gitlabUri, gitlabJobUrl, owner. RELEASE_NAME/CHART_NAMEworkflows-api.

Джоба unittest (stage: test, образ golang:1.24, make unit-tests) запускается на любых ветках/тегах и MR, allow_failure: true.

Замечания и потенциальные проблемы

  1. Две разные структуры конфигурации БД с разными дефолтами. Сервер использует pkg/postgres/pgxconnection.Postgres (дефолты POSTGRES_USER=sarex, POSTGRES_PASSWORD=sarex), а миграции — pkg/postgres/gopg.Postgres (дефолты processing/processing). При запуске без явно заданных переменных сервер и миграции подключались бы под разными кредами. В production это не проявляется, т. к. все переменные приходят из секретов.
  2. ENABLE_SQL_QUERY не используется. Поле читается в обе структуры (EnableSQLQuery), но нигде в коде не применяется — флаг «мёртвый».
  3. OBSERVABILITY_TRACE_COLLECTOR_ENDPOINT, ENABLE_OBSERVABILITY не используются. Пакет pkg/observavility (с SetupOTelSDK) нигде не импортируется — это легаси. Реальный трейсинг настраивается переменными TRACER_* через внешнюю библиотеку golang-fiber-otel-tools.
  4. POD_NAME, S3_SERVICE_ACCOUNT, DJANGO_HOST из Helm кодом не читаются — либо задел на будущее, либо устаревшие переменные.
  5. entrypoint.sh устарел и не используется. Он ссылается на /go/bin/migrations и /go/bin/httpserver, тогда как в образе бинари лежат в /httpserver и /migrations, а ENTRYPOINT задан в Dockerfile напрямую (/httpserver migrate).
  6. Опечатка в mount-пути internal-middleware. В server.go middleware, выставляющий is_internal=true, монтируется как app.Use("./internal", ...) (с ведущей точкой) вместо "/internal". Из-за этого для маршрутов группы /internal флаг is_internal может не выставляться; в контроллерах nil-значение трактуется как «внутренний/доверенный запрос» (проверки принадлежности к компании пропускаются). Логически поведение сохраняется, но путь выглядит как баг.
  7. PUBLIC_KEY обязателен. При пустом значении auth.New делает panic("failed to parse PEM block ...") — сервис не стартует. Дефолта нет.
  8. Расхождение по порту. Дефолт кода HTTP_HOST=0.0.0.0:8000, docker-compose — 8000, а в k8s (Helm) — 8080. Локально сервис слушает 8000, в кластере — 8080.
  9. BUILD_ARGS передаёт CI_COMMIT_SHORT_SHA, но Dockerfile не объявляет соответствующий ARG — build-arg игнорируется.
  10. POSTGRES_SSL_USE в Helm задаётся то как 1, то как true (preprod). cleanenv корректно парсит обе формы, но единообразия нет.

Минимальный набор для локального запуска

Для запуска сервера локально (например, БД поднята через make container-run-deps или docker-compose) достаточно:

# БД
POSTGRES_ADDRESS=localhost
POSTGRES_PORT=5432
POSTGRES_DB=processing_db
POSTGRES_USER=processing
POSTGRES_PASSWORD=processing
POSTGRES_SSL_USE=false

# HTTP
HTTP_HOST=0.0.0.0:8000

# Обязательно: PEM публичный ключ (PKIX) для проверки JWT
PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"

# Трейсинг можно выключить
TRACER_USE=false

Минимальный сценарий:

  1. Поднять PostgreSQL: make container-run-deps (или docker-compose up database).
  2. Экспортировать переменные выше (особенно валидный PUBLIC_KEY, иначе panic).
  3. Прогнать миграции и запустить сервер: go run ./cmd/httpserver migrate (аргумент migrate включает миграции), либо air для hot-reload.
  4. Проверить: GET http://localhost:8000/ping{"status":"ready"}.

Через docker-compose up сервис поднимается на :8000, БД — processing/processing/processing_db, но PUBLIC_KEY в compose не задан — для полноценной работы API его нужно добавить.