Перейти к содержанию

Хранилище объектов (MinIO)

Как в установке Taimen устроено S3-совместимое хранилище: зачем оно ядру, какие бакеты и учётные записи заводятся, как подключить внешний S3 вместо MinIO контура, что бэкапить и как разбирать типичные сбои. Статья для инженера эксплуатации.

Кто пользуется хранилищем

Потребитель Бакет (переменная, умолчание) Учётная запись Что лежит
Control Plane (API и worker) CP_S3_BUCKET, artifacts отдельный пользователь CP_S3_ACCESS_KEY_ID с политикой только на свой бакет Содержимое артефактов задач (см. Артефакты)

Ядро хранит в PostgreSQL только записи: ссылку на объект, размер, media type и SHA-256. Байты — только в хранилище. Объект содержимого адресуется контрольной суммой внутри tenant'а: tenants/<tenant-id>/sha256/<hex>. Одинаковые файлы одного tenant'а хранятся одним объектом, файлы разных tenant'ов не пересекаются.

MinIO в compose

Сервис Профили Назначение
minio core S3-сервер, данные в томе platform_minio, лимит памяти MINIO_MEM_LIMIT (256m), healthcheck mc ready local
minio-bootstrap core одноразовый: бакет, политика и пользователь ядра; завершается после старта

MinIO входит в профиль core и хранит только содержимое артефактов ядра. Имя тома (историческое) — ${COMPOSE_PROJECT_NAME}_platform_minio, переопределяется VOLUME_PLATFORM_MINIO.

Наружу MinIO не смотрит. Портов на хост не публикуется, маршрута в Caddy (профиль edge) нет. Клиенты не получают адресов объектов: байты артефактов входят через PUT /api/v1/artifact-contents и выходят через GET /api/v1/artifacts/{id}/content, где ядро проверяет права и пишет событие выдачи.

Что делает minio-bootstrap

Сервис выполняет набор команд mc от root-учётки MinIO:

  1. создаёт бакет CP_S3_BUCKET (mc mb --ignore-existing);
  2. создаёт политику cp-artifacts (см. ниже);
  3. заводит пользователя CP_S3_ACCESS_KEY_ID с секретом CP_S3_SECRET_ACCESS_KEY;
  4. привязывает к нему политику, если она ещё не привязана.

Все шаги идемпотентны: сервис можно перезапускать при каждом up. control-plane-api ждёт его успешного завершения (service_completed_successfully); зависимость помечена необязательной, чтобы установка с внешним S3, где сервиса нет, тоже поднималась.

Политика пользователя ядра

Политика cp-artifacts для бакета по умолчанию artifacts:

{"Version": "2012-10-17", "Statement": [
  {"Effect": "Allow", "Action": ["s3:GetBucketLocation", "s3:ListBucket"],
   "Resource": ["arn:aws:s3:::artifacts"]},
  {"Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
   "Resource": ["arn:aws:s3:::artifacts/*"]}
]}
  • Объекты своего бакета — чтение, запись и удаление: загрузка содержимого, выдача, удаление администратором и очистка worker'ом.
  • s3:ListBucket на бакет нужен, потому что при старте API проверяет бакет запросом HeadBucket, а без этого права хранилище отвечает 403 и ядро считает хранилище недоступным.
  • Создавать бакеты ядру не нужно и нельзя: бакет заводит minio-bootstrap. Других бакетов пользователь ядра не видит, root-ключи ядру не выдаются.

Ключи

Все четыре ключа генерирует make secrets (tools/fill_secrets.py), если в .env они пусты:

Переменная Кто использует
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY root-учётка minio; ею ходит только minio-bootstrap
CP_S3_ACCESS_KEY_ID, CP_S3_SECRET_ACCESS_KEY пользователь ядра: minio-bootstrap заводит его, процессы Control Plane ходят под ним
CP_S3_BUCKET бакет содержимого артефактов, по умолчанию artifacts

CP_S3_ACCESS_KEY_ID и CP_S3_SECRET_ACCESS_KEY в deploy/local/compose.yml обязательны (${VAR:?…}): без них не поднимется ни MinIO-bootstrap, ни процессы ядра. Остальные настройки ядра (CP_S3_ENDPOINT_URL, CP_S3_REGION, таймауты, лимиты) — в Конфигурации Control Plane.

Ключи — секреты

Храните .env вместе с остальной конфигурацией установки: без него восстановленный том MinIO не откроется ни root-учёткой, ни пользователем ядра. См. Секреты и ротация.

Внешний S3 вместо MinIO

Содержимое артефактов можно держать у любого S3-совместимого провайдера. Файл deploy/local/compose.s3.example.yml в корне суперпроекта выводит minio и minio-bootstrap из профиля core (назначает им профиль, который установка не поднимает); подключайте его вторым файлом:

tools/compose -f deploy/local/compose.s3.example.yml --profile core --profile edge up -d

В .env:

CP_S3_ENDPOINT_URL=https://s3.example.com
CP_S3_REGION=<регион провайдера>
CP_S3_BUCKET=<бакет>
CP_S3_ACCESS_KEY_ID=<ключ пользователя>
CP_S3_SECRET_ACCESS_KEY=<секрет пользователя>
  • Бакет создайте заранее средствами провайдера.
  • Пользователю нужны те же права, что у политики выше: ListBucket на бакет и GetObject, PutObject, DeleteObject на его объекты.
  • MinIO контура при этом не нужен.

Хранилище выключено совсем

Если CP_S3_ENDPOINT_URL пуст, Control Plane работает без хранилища: артефакты-ссылки и JSON-артефакты создаются как обычно, а маршруты содержимого отвечают 503 content_store_unavailable. В поставочном deploy/local/compose.yml адрес по умолчанию — http://minio:9000.

Резервное копирование

Том platform_minio содержит содержимое артефактов ядра. Бэкапьте его вместе с базой Control Plane:

  • control-plane-db ↔ MinIO. Записи артефактов — в базе Control Plane, байты — в MinIO. Снимайте их в одном окне. Если том MinIO старше базы, у части записей contentState = stored объекта не окажется, и выдача таких артефактов ответит 503 content_store_unavailable.

Скрипт ежедневного бэкапа и порядок восстановления — в Резервном копировании. Снимайте копию тома после дампа базы Control Plane: объекты неизменяемы и адресуются контрольной суммой, так что объекты записей из дампа к этому моменту уже лежат в томе. Исключение — содержимое, которое администратор удалил между дампом и копией тома.

Очистка и рост

  • Незавершённые загрузки. Загрузка, на которую за CP_ARTIFACT_UPLOAD_TTL_SECONDS (24 часа по умолчанию) не сослался ни один артефакт, удаляется worker'ом вместе с объектом, если тот больше никому не нужен. Если хранилище недоступно, строки остаются до следующего прохода.
  • Содержимое артефактов хранится бессрочно. Закрытие задачи его не удаляет. Удалить байты конкретного артефакта может администратор tenant'а: POST /api/v1/artifacts/{id}:purge-content (см. Удаление содержимого).
  • Потолок одного файла — CP_ARTIFACT_MAX_BYTES (100 МиБ по умолчанию); тип артефакта может сузить его своим maxBytes.

Рост тома учитывайте в Ресурсах и масштабировании.

Типичные проблемы

Симптом Причина Что делать
503 content_store_unavailable на PUT /artifact-contents при работающем MinIO CP_S3_ENDPOINT_URL пуст — хранилище в ядре выключено Задать адрес и пересоздать процессы Control Plane
503 content_store_unavailable, в журнале API предупреждение content store unavailable at start-up MinIO не поднят, неверные ключи или у пользователя нет ListBucket tools/compose ps minio minio-bootstrap, логи minio-bootstrap; проверить ключи в .env и политику
503 content_store_unavailable только при чтении отдельных артефактов Объекта нет в хранилище при записи stored: том восстановлен из более старой копии, чем база Восстановить том MinIO из копии, согласованной с базой
tools/compose up падает на set CP_S3_ACCESS_KEY_ID Ключей ядра нет в .env make secrets — допишет недостающие ключи
413 request_too_large на загрузке Файл больше CP_ARTIFACT_MAX_BYTES Уменьшить файл или поднять лимит установки
422 artifact_too_large при создании артефакта Файл больше maxBytes зарегистрированного типа артефакта Выпустить версию типа с большим maxBytes (не выше CP_ARTIFACT_MAX_BYTES)

См. также