iac/apps/documentations/cde-api.CONFIGURATION.md
2026-10-28 12:30:02 +02:00

237 lines
21 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.

# Конфигурация cde-api и его воркеров
Документ описывает переменные окружения `cde-api` и воркеров, развёрнутых в неймспейсе `documentations`. Манифесты — `base/cde-api*.yaml` (канонический вариант) и одноимённые файлы в оверлеях контуров. Источник значений — `cde-api/.helm/values.yaml`; значения в таблицах — из `base` (контуры переопределяют URL зависимостей, см. ниже).
## Процессы
| HelmRelease | Deployment | Образ | Service | Назначение |
| --- | --- | --- | --- | --- |
| `cde-api` | `cde-api` | `cde-api` | `cde-api:8000` | HTTP-API (`CDE_API_HTTP_PORT=8000`) |
| `cde-api-worker-s32d-create-upload` | `worker-s32d-create-upload` | `cde-api-worker-s32d-create-upload` | — | воркер S32D: создание и загрузка s3→disk |
| `cde-api-worker-s32d-process-workflows` | `worker-s32d-process-workflows` | `cde-api-worker-s32d-process-workflows` | — | воркер S32D: запуск workflow-обработки |
| `cde-api-worker-s32d-publish-documents` | `worker-s32d-publish-documents` | `cde-api-worker-s32d-publish-documents` | — | воркер S32D: публикация документов |
| `cde-api-worker-s32d-handle-error` | `worker-s32d-handle-error` | `cde-api-worker-s32d-handle-error` | — | воркер S32D: обработка ошибок |
| `cde-api-worker-copy` | `worker-copy` | `cde-api-worker-copy` | — | воркер копирования |
| `cde-api-worker-move` | `worker-move` | `cde-api-worker-move` | — | воркер перемещения |
Не развёрнуты (в `universal-chart` нет поддержки `cronjobs`): `workspace-recovery`, `resource-id-backfill`, `sizer` — остаются в `cde-api/.helm`.
Назначение воркеров выведено из имён образов и переменных `CDE_API_S32D_*`; точное поведение — в коде `cde-api/cmd`.
## Способ конфигурирования
- Только переменные окружения с префиксом `CDE_API_`; вложенные секции задаются через `__` (`CDE_API_DATABASE__HOST`).
- Несекретные значения — `envs` в HelmRelease. Секреты: в vault-контурах (`base`, а значит `sarex-contour`, `yc-k8s-test`, `d8-ugmk-prod`, `uralkal`, `vad`) — Vault Agent Injector (файлы в `/vault/secrets/`, которые `command: /bin/sh -ec` загружает в окружение перед `exec /opt/main` / `exec /opt/worker`, как у `documentations-api`); в остальных (`ugok`, `brusnika-*`, `wb`) — k8s `secretEnvs`.
- Для Vault-схемы в образы cde-api добавлен статический busybox (`/bin/sh`, `/bin/cat`) — см. `.docker/*/Dockerfile` в репозитории cde-api; без него контейнер не стартует.
- **Postgres, Valkey и S3 — общие с documentations** (отдельных ресурсов у cde-api нет): БД и креды те же, что у `documentations-api`; Valkey — внутрикластерный `redis:6379` (ns `documentations`, без TLS и пароля, DB 5); S3 — доступ MinIO из `secrets/data/minio/apps/documentations`.
- Файл `/etc/app/tasks_execution_config.json` (`CDE_API_WORKFLOWS_CONFIG_FILEPATH`) монтируется из ConfigMap `tasks-execution-config-documentation-v2` (`tasks-execution-config.yaml`; содержимое — `cde-api/.example.tasks_execution_config.json`, в реальных контурах заменить боевыми ресурсами задач).
- Значения по умолчанию в `values.yaml` источника — для stage; в iac всегда `global.env=_default`, поэтому здесь взяты prod-значения, а URL зависимостей — по конвенции соответствующего контура (из его `api.yaml`).
## Секреты в Vault (vault-контуры)
Инжектируются Vault Agent (role `documentations`, SA `documentations-vault`); каждый путь — отдельный файл `/vault/secrets/cde-api-<имя>`.
| Файл | Путь Vault | Переменные | Процессы |
| --- | --- | --- | --- |
| `postgres` | `secrets/data/apps/documentations/postgres` (общий с documentations) | `CDE_API_DATABASE__HOST/PORT/NAME/USER/PASSWORD` | все |
| `s3` | `secrets/data/minio/apps/documentations` (общий) | `CDE_API_S3_ENDPOINT/ACCESS_KEY/SECRET_KEY` | все |
| `zeebe` | `secrets/data/apps/cde-api/zeebe` (**нужно создать**: `gateway_address`, `client_id`, `client_secret`, `auth_server_url`) | `CDE_API_ZEEBE_*` | все |
| `rabbitmq` | `secrets/data/rabbitmq/apps/cde` | `CDE_API_RABBITMQ__USER/PASSWORD/VHOST` (хост и порт — в envs) | api, copy, move |
| `django-auth` | `secrets/data/vault/common/django_auth` (ключ `key`) | `CDE_API_USERS_AUTH_TOKEN` | api |
| `rsa-public` | `secrets/data/vault/common/rsa_keys` (ключ `public_key`) | `CDE_API_PUBLIC_KEY` | api |
Точный состав файлов у каждого процесса — в `podAnnotations` его HelmRelease.
## Секреты k8s-контуров (`ugok`, `brusnika-*`, `wb`; ns `documentations`)
Postgres — тот же хост/БД, что у `documentations-api` контура (литералы в envs), логин/пароль из его секрета (`postgres-secret` или `documentations-postgresql-secret`, ключи `username`/`password`); Valkey — `redis`. S3 и RabbitMQ — Secret'ы, которые в контуре уже используют hasher / pdf-markings / api; новый нужен только для Zeebe (`cde-api-zeebe-secret`).
| Контур | S3 (endpoint / access / secret) | RabbitMQ |
| --- | --- | --- |
| `ugok` | `documentations-s3-secret`: `endpoint` / `access_key` / `secret_key` | `documentations-rabbitmq-secret`: `host, port, username, password, vhost` |
| `brusnika-prod` | `hasher-s3-secret`: `endpoint` / `access_key` / `secret_key` | `rabbitmq`: `host, port, username, password, vhost` |
| `brusnika-stage` | `yc-s3`: `endpoint_url` / `key_id` / `access_key` | `rabbitmq`: как выше |
| `wb` | `yc-s3`: `endpoint_url` / `key_id` / `access_key` | как в `wb/api.yaml`: host/port/vhost (`cde`) — литералы в envs, user/password — `hasher-rabbitmq-secret` (`user`, `password`) |
Таблица ниже — для справки по `wb` (остальные контуры отличаются именами Secret'ов и ключей, см. таблицу выше):
| Secret | Ключи | Переменные |
| --- | --- | --- |
| `public-key` | `key` | `CDE_API_PUBLIC_KEY` |
| `postgres-secret` | `username`, `password` | `CDE_API_DATABASE__USER`, `CDE_API_DATABASE__PASSWORD` |
| `yc-s3` | `endpoint_url`, `key_id`, `access_key` | `CDE_API_S3_ENDPOINT`, `CDE_API_S3_ACCESS_KEY`, `CDE_API_S3_SECRET_KEY` |
| `cde-api-zeebe-secret` | `gateway_address`, `client_id`, `client_secret`, `auth_server_url` | `CDE_API_ZEEBE_GATEWAY_ADDRESS`, `CDE_API_ZEEBE_CLIENT_ID`, `CDE_API_ZEEBE_CLIENT_SECRET`, `CDE_API_ZEEBE_AUTH_SERVER_URL` |
| `django-auth` | `key` | `CDE_API_USERS_AUTH_TOKEN` |
| `hasher-rabbitmq-secret` | `user`, `password` | `CDE_API_RABBITMQ__USER`, `CDE_API_RABBITMQ__PASSWORD` |
## Переменные окружения
Колонка «Процессы»: api, create-upload, process-workflows, publish-documents, handle-error, copy, move. Если значение различается между процессами, показано значение первого процесса из списка.
| Переменная | Значение (base) | Процессы |
| --- | --- | --- |
| `CDE_API_APP_NAME` | `cde-api` *(различается)* | все |
| `CDE_API_BIMAPI_RETRY_COUNT` | `3` | api, process-workflows, copy, move |
| `CDE_API_BIMAPI_RETRY_WAIT_MS` | `1000` | api |
| `CDE_API_BIMAPI_TIMEOUT_MS` | `30000` | api, process-workflows, copy, move |
| `CDE_API_BIMAPI_TIMEOUT_V2_MS` | `300000` | api, process-workflows, copy, move |
| `CDE_API_BIMAPI_URL` | `http://backend-svc.bim.svc.cluster.local:80` | api, process-workflows, copy, move |
| `CDE_API_BIMAPI_V2_URL` | `http://backend-svc.bim.svc.cluster.local:80` | api, process-workflows, copy, move |
| `CDE_API_CONTAINER_REGISTRY` | `cr.yandex/crp3ccidau046kdj8g9q` | api, process-workflows, copy, move |
| `CDE_API_CONVERTED_PDF_TO_S3` | `true` | api, process-workflows, copy, move |
| `CDE_API_CONVERT_DWG_TO_GEOJSON` | `true` | api, process-workflows, copy, move |
| `CDE_API_CONVERT_DXF_TO_GEOJSON` | `true` | api, process-workflows, copy, move |
| `CDE_API_COPY_JOB_TIMEOUT_MINUTES` | `30` | copy |
| `CDE_API_COPY_MAX_SYNC_WAIT_MS` | `300000` | api |
| `CDE_API_COPY_S3_PARALLELISM` | `1` | copy |
| `CDE_API_COPY_STEP_PARALLELISM` | `1` | copy |
| `CDE_API_COPY_WORKER_JOBS` | `""` | copy |
| `CDE_API_DATABASE_HEALTH_CHECK_PERIOD` | `30s` | все |
| `CDE_API_DATABASE_MAX_CONN_IDLE_TIME` | `10m` | все |
| `CDE_API_DATABASE_MAX_CONN_LIFETIME` | `30m` | все |
| `CDE_API_DATABASE_OBSERVABILITY_ENABLE` | `true` | api |
| `CDE_API_DATABASE_POOL_SIZE` | `10` *(различается)* | все |
| `CDE_API_DATABASE__INSECURE_SKIP_TLS` | `false` | все |
| `CDE_API_DATABASE__SSLMODE` | `disable` | все |
| `CDE_API_DIAGNOSTICS_SLOW_OPERATION_THRESHOLD` | `30s` | api |
| `CDE_API_DISK_BUCKET_NAMESPACE` | `documentations-prod` | api |
| `CDE_API_DJANGO_HOST` | `http://backend-svc.django.svc.cluster.local:80` | api, process-workflows, copy, move |
| `CDE_API_DOCUMENTATION_V2_URL` | `http://backend-api-svc.documentations.svc.cluster.local:80` | api, process-workflows, copy, move |
| `CDE_API_EAV_HOST` | `http://backend-svc.eav.svc.cluster.local:80` | все |
| `CDE_API_EAV_TIMEOUT_MS` | `10000` | api |
| `CDE_API_ENVIRONMENT` | `production` | api, process-workflows, copy, move |
| `CDE_API_FLOWS_URL` | `http://backend-svc.flows.svc.cluster.local:80` | все |
| `CDE_API_HTTP_IDLE_TIMEOUT` | `120s` | api |
| `CDE_API_HTTP_PORT` | `8000` | api |
| `CDE_API_HTTP_READ_BUFFER_SIZE` | `96` | api |
| `CDE_API_HTTP_READ_TIMEOUT` | `0s` | api |
| `CDE_API_HTTP_WRITE_TIMEOUT` | `0s` | api |
| `CDE_API_INTERNAL_URL` | `http://cde-api.documentations:8000` | api, process-workflows, copy, move |
| `CDE_API_ISSUES_BASE_URL` | `http://issues-service.platform:8000` | copy |
| `CDE_API_ISSUES_RETRY_COUNT` | `3` | copy |
| `CDE_API_ISSUES_SYNC_ENABLED` | `false` | copy |
| `CDE_API_ISSUES_TIMEOUT_MS` | `30000` | copy |
| `CDE_API_LAST_MASTER_BIM` | `36311` | api, process-workflows, copy, move |
| `CDE_API_LAST_SLAVE_1_BIM` | `94015` | api, process-workflows, copy, move |
| `CDE_API_LAST_SLAVE_2_BIM` | `135771` | api, process-workflows, copy, move |
| `CDE_API_LOG_LEVEL` | `debug` *(различается)* | все |
| `CDE_API_MAILER_BASE_URL` | `http://mailer-service.mailer:8000` | все |
| `CDE_API_MAILER_FROM_EMAIL` | `noreply@sarex.io` | все |
| `CDE_API_MAILER_RETRY_COUNT` | `2` | api |
| `CDE_API_MAILER_TIMEOUT_MS` | `10000` | api |
| `CDE_API_MOVE_JOB_TIMEOUT_MINUTES` | `30` | move |
| `CDE_API_MOVE_WORKER_JOBS` | `""` | move |
| `CDE_API_OBSERVABILITY_ENABLE` | `true` | все |
| `CDE_API_OBSERVABILITY_HOST` | `signoz-otel-collector-external.signoz.svc.cluster.local` | все |
| `CDE_API_OBSERVABILITY_PORT` | `4317` | все |
| `CDE_API_OBSERVABILITY_SERVICE_NAME` | `worker-s32d-create-upload` *(различается)* | create-upload, process-workflows, publish-documents, handle-error, copy, move |
| `CDE_API_PUBLIC_LINK_HOST` | `https://document-link-srx.wb.ru` | api |
| `CDE_API_RABBITMQ__HASHER_EXCHANGE` | `hash.compute` | api, copy, move |
| `CDE_API_RABBITMQ__HASHER_ROUTING_KEY` | `hash.compute.normal` | api, copy, move |
| `CDE_API_RABBITMQ__HOST` | `rabbitmq.rabbitmq.svc.cluster.local` | api, copy, move |
| `CDE_API_RABBITMQ__MARKS_ROUTING_KEY` | `pdf_markings_input` | api, copy, move |
| `CDE_API_RABBITMQ__PORT` | `5672` | api, copy, move |
| `CDE_API_REDIS__DB` | `5` | api |
| `CDE_API_REDIS__DEFAULT_TTL_MINUTES` | `10` | все |
| `CDE_API_REDIS__DIAL_TIMEOUT_MS` | `5000` | все |
| `CDE_API_REDIS__HOST` | `redis` | все |
| `CDE_API_REDIS__MIN_IDLE_CONNS` | `2` *(различается)* | все |
| `CDE_API_REDIS__PERMISSION_CACHE_ENABLED` | `false` | все |
| `CDE_API_REDIS__POOL_SIZE` | `10` *(различается)* | все |
| `CDE_API_REDIS__PORT` | `6379` | все |
| `CDE_API_REDIS__READ_TIMEOUT_MS` | `3000` | все |
| `CDE_API_REDIS__SSL` | `false` | все |
| `CDE_API_REDIS__WRITE_TIMEOUT_MS` | `3000` | все |
| `CDE_API_RESOURCES_BASE_URL` | `http://iams.iam.svc.cluster.local:8080` | api |
| `CDE_API_RESOURCES_TIMEOUT` | `10s` | api |
| `CDE_API_S32D_MAX_ARCHIVE_SIZE_BYTES` | `1099511627776` | api |
| `CDE_API_S32D_MAX_FILES_COUNT` | `500` | api |
| `CDE_API_S32D_READERAT_BLOCK_SIZE_MB` | `8` | create-upload |
| `CDE_API_S32D_READERAT_CACHE_BLOCKS` | `8` | create-upload |
| `CDE_API_S32D_WORKER_CREATE_UPLOAD_MAX_JOBS` | `2` | create-upload |
| `CDE_API_S32D_WORKER_CREATE_UPLOAD_TIMEOUT_MIN` | `240` | create-upload |
| `CDE_API_S32D_WORKER_HANDLE_ERROR_MAX_JOBS` | `4` | handle-error |
| `CDE_API_S32D_WORKER_HANDLE_ERROR_TIMEOUT_MIN` | `10` | handle-error |
| `CDE_API_S32D_WORKER_PROCESS_WORKFLOWS_MAX_JOBS` | `2` | process-workflows |
| `CDE_API_S32D_WORKER_PROCESS_WORKFLOWS_TIMEOUT_MIN` | `480` | process-workflows |
| `CDE_API_S32D_WORKER_PUBLISH_DOCUMENTS_MAX_JOBS` | `2` | publish-documents |
| `CDE_API_S32D_WORKER_PUBLISH_DOCUMENTS_TIMEOUT_MIN` | `10` | publish-documents |
| `CDE_API_S3_BUCKET_LOOKUP` | `auto` | все |
| `CDE_API_S3_BUCKET_NAME` | `documentations-prod` | все |
| `CDE_API_S3_CHECK_BUCKET` | `false` | все |
| `CDE_API_S3_CONNECT_TIMEOUT` | `10s` | api |
| `CDE_API_S3_INSECURE_SKIP_TLS` | `true` | все |
| `CDE_API_S3_MAX_PART_SIZE` | `524288000` | все |
| `CDE_API_S3_MAX_SINGLE_UPLOAD_SIZE` | `5368709120` | все |
| `CDE_API_S3_TLS_HANDSHAKE_TIMEOUT` | `10s` | api |
| `CDE_API_S3_UPLOAD_STALL_TIMEOUT` | `10m` | все |
| `CDE_API_S3_USE_SSL` | `true` | все |
| `CDE_API_SENTRY_DSN` | `""` | все |
| `CDE_API_SENTRY_ENVIRONMENT` | `""` | все |
| `CDE_API_SYSTEMLOG_BASE_URL` | `http://backend-svc.system-log.svc.cluster.local:80` | api, publish-documents, copy, move |
| `CDE_API_SYSTEMLOG_TIMEOUT_MS` | `10000` | api, publish-documents, copy, move |
| `CDE_API_TRANSMITTALS_URL` | `http://transmittal-service.transmittal.svc.cluster.local:80` | все |
| `CDE_API_USERS_BASE_URL` | `http://backend-svc.django.svc.cluster.local:80` | api |
| `CDE_API_USERS_ORIGINATOR` | `docs_prod` | api |
| `CDE_API_USERS_TIMEOUT_MS` | `10000` | api |
| `CDE_API_USE_BIMV1_FOR_BIMV2` | `true` | api, process-workflows, copy, move |
| `CDE_API_USE_BIM_INSERTER` | `true` | api, process-workflows, copy, move |
| `CDE_API_USE_LEGACY_BIM_FLOW` | `0` | api, process-workflows, copy, move |
| `CDE_API_WORKFLOWS_CONFIG_FILEPATH` | `/etc/app/tasks_execution_config.json` | все |
| `CDE_API_WORKFLOWS_IMAGES_VERSION` | `master` | api, process-workflows, copy, move |
| `CDE_API_WORKFLOW_BASE_URL` | `http://backend-svc.processing.svc.cluster.local:80` | api, process-workflows, copy, move |
| `CDE_API_WORKFLOW_RETRY_COUNT` | `3` | api, process-workflows, copy, move |
| `CDE_API_WORKFLOW_RETRY_WAIT_MS` | `500` | api |
| `CDE_API_WORKFLOW_TIMEOUT_MS` | `30000` | api, process-workflows, copy, move |
| `CDE_API_WORKSPACE_BASE_URL` | `http://backend-svc.workspaces.svc.cluster.local:80` | api, publish-documents, copy, move |
| `CDE_API_WORKSPACE_RETRY_COUNT` | `3` | api, publish-documents, copy, move |
| `CDE_API_WORKSPACE_TIMEOUT_MS` | `10000` | api, publish-documents, copy, move |
| `CDE_API_ZEEBE_USE_PLAINTEXT` | `true` | все |
## Переменные из k8s-секретов (ugok, brusnika-*, wb)
| Переменная | Secret / ключ | Процессы |
| --- | --- | --- |
| `CDE_API_DATABASE__PASSWORD` | `postgres-secret` / `password` | все |
| `CDE_API_DATABASE__USER` | `postgres-secret` / `username` | все |
| `CDE_API_PUBLIC_KEY` | `public-key` / `key` | api |
| `CDE_API_RABBITMQ__PASSWORD` | `hasher-rabbitmq-secret` / `password` | api, copy, move |
| `CDE_API_RABBITMQ__USER` | `hasher-rabbitmq-secret` / `user` | api, copy, move |
| `CDE_API_S3_ACCESS_KEY` | `yc-s3` / `key_id` | все |
| `CDE_API_S3_ENDPOINT` | `yc-s3` / `endpoint_url` | все |
| `CDE_API_S3_SECRET_KEY` | `yc-s3` / `access_key` | все |
| `CDE_API_USERS_AUTH_TOKEN` | `django-auth` / `key` | api |
| `CDE_API_ZEEBE_AUTH_SERVER_URL` | `cde-api-zeebe-secret` / `auth_server_url` | все |
| `CDE_API_ZEEBE_CLIENT_ID` | `cde-api-zeebe-secret` / `client_id` | все |
| `CDE_API_ZEEBE_CLIENT_SECRET` | `cde-api-zeebe-secret` / `client_secret` | все |
| `CDE_API_ZEEBE_GATEWAY_ADDRESS` | `cde-api-zeebe-secret` / `gateway_address` | все |
## Различия по контурам
От контура к контуру меняются URL зависимостей, внешний хост публичных ссылок и источник образов:
| Контур | Тип оверлея | Что отличается |
| --- | --- | --- |
| `sarex-contour`, `yc-k8s-test` | наследуют `base` | ничего (значения `base`) |
| `d8-ugmk-prod`, `uralkal`, `vad` | патч `cde-api.yaml` поверх `base` | `CDE_API_PUBLIC_LINK_HOST` |
| `ugok` | полная копия HelmRelease, chart 0.1.9 | URL зависимостей (порты 8000/8080), образы из `10.4.10.187:80/library`, pull-secret `dockerhub` |
| `brusnika-prod`, `brusnika-stage` | полная копия, chart 0.1.7 | URL зависимостей; stage — профиль stage (`CDE_API_ENVIRONMENT=stage`, bucket `documentations-stage`) |
| `wb` | полная копия, chart 0.1.7 | URL зависимостей, `CDE_API_PUBLIC_LINK_HOST=https://document-link-srx.wb.ru` |
Правка `base` на полные копии (ugok, brusnika-*, wb) не влияет.
## Допущения и что нужно проверить
- **Теги образов** (`prod_c9bc246`; у brusnika-stage `stage_c9bc246`, у ugok `ugok_c9bc246`) — placeholder на основе HEAD ветки develop cde-api; заменить на фактически собранные CI.
- `CDE_API_DJANGO_HOST` и `CDE_API_USERS_BASE_URL` в источнике — внешний хост (`https://lk.sarex.io`), здесь заменены внутренним адресом Django контура. Если cde-api использует их для внешних ссылок — вернуть внешний хост.
- `CDE_API_S3_BUCKET_NAME` для prod-контуров выставлен в `documentations-prod` по аналогии с `CDE_API_DISK_BUCKET_NAMESPACE`; в источнике задан только stage-бакет.
- `CDE_API_EAV_HOST`, `CDE_API_TRANSMITTALS_URL` выбраны по конвенции остальных приложений контура (`backend-svc.eav`, `eav-service.eav`, `transmittal-service.transmittal`); сверить с `inventory.yaml`.
- Sentry отключён (`CDE_API_SENTRY_DSN=""`): DSN источника ведёт во внешний SaaS.
- Реплики воркеров `create-upload` и `process-workflows` — `1` (в prod-конфиге cde-api — `0`).
- Порт: в источнике `deployment.port=8080` при `CDE_API_HTTP_PORT=8000` и `service.targetPort=8000`; здесь везде 8000.
- Общая с documentations БД: cde-api применяет свои миграции в той же базе — проверить отсутствие конфликтов имён таблиц/схемы и версий миграций (отдельная схема или префикс при необходимости).
- Общий Valkey без пароля и TLS (в источнике cde-api — управляемый Valkey с TLS и логином): подтвердить, что cde-api работает без `CDE_API_REDIS__USERNAME/PASSWORD`. DB 5 совпадает с `VALKEY_DB=5` у documentations-api (в stage так же).
- `secrets/data/apps/cde-api/zeebe` в Vault нужно создать; в k8s-контурах нужен только Secret `cde-api-zeebe-secret`; S3 и RabbitMQ используют существующие Secret'ы hasher / pdf-markings / api (таблица выше). Если в Secret'ах S3 другие права или бакет, чем нужны cde-api, заменить на отдельный.
- Значения секретов из Vault подставляются в окружение через `. file` без кавычек — как у `documentations-api`; пароли со спецсимволами shell ломают этот способ.
- Образы cde-api нужно пересобрать с добавленным busybox (проверка сборки Docker не выполнялась); без этого поды в vault-контурах не стартуют.