Хранилище объектов (MinIO)¶
Как в установке Taimen устроено S3-совместимое хранилище: зачем оно ядру и панели платформы, какие бакеты и учётные записи заводятся, как подключить внешний S3 вместо MinIO контура, что бэкапить и как разбирать типичные сбои. Статья для инженера эксплуатации.
Кто пользуется хранилищем¶
| Потребитель | Бакет (переменная, умолчание) | Учётная запись | Что лежит |
|---|---|---|---|
| Control Plane (API и worker) | CP_S3_BUCKET, artifacts |
отдельный пользователь CP_S3_ACCESS_KEY_ID с политикой только на свой бакет |
Содержимое артефактов задач (см. Артефакты) |
platform-api (профиль platform) |
S3_BUCKET, platform |
root-учётка MinIO S3_ACCESS_KEY_ID |
Файлы документов панели (см. Документы и файлы) |
Ядро хранит в PostgreSQL только записи: ссылку на объект, размер, media
type и SHA-256. Байты — только в хранилище. Объект содержимого адресуется
контрольной суммой внутри tenant'а: tenants/<tenant-id>/sha256/<hex>.
Одинаковые файлы одного tenant'а хранятся одним объектом, файлы разных
tenant'ов не пересекаются.
MinIO в compose¶
| Сервис | Профили | Назначение |
|---|---|---|
minio |
core, platform |
S3-сервер, данные в томе platform_minio, лимит памяти MINIO_MEM_LIMIT (256m), healthcheck mc ready local |
minio-bootstrap |
core, platform |
одноразовый: бакеты, политика и пользователь ядра; завершается после старта |
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:
- создаёт бакеты
S3_BUCKETиCP_S3_BUCKET(mc mb --ignore-existing); - создаёт политику
cp-artifacts(см. ниже); - заводит пользователя
CP_S3_ACCESS_KEY_IDс секретомCP_S3_SECRET_ACCESS_KEY; - привязывает к нему политику, если она ещё не привязана.
Все шаги идемпотентны: сервис можно перезапускать при каждом 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, platform-api |
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 в compose.yml
обязательны (${VAR:?…}): без них не поднимется ни MinIO-bootstrap, ни
процессы ядра. Остальные настройки ядра (CP_S3_ENDPOINT_URL,
CP_S3_REGION, таймауты, лимиты) — в Конфигурации Control Plane.
Ключи — секреты
Храните .env вместе с остальной конфигурацией установки: без него
восстановленный том MinIO не откроется ни root-учёткой, ни пользователем
ядра. См. Секреты и ротация.
Внешний S3 вместо MinIO¶
Содержимое артефактов можно держать у любого S3-совместимого провайдера.
Файл compose.s3.example.yml в корне суперпроекта переводит minio и
minio-bootstrap только в профиль platform; подключайте его вторым файлом:
В .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 контура при этом остаётся нужен только панели платформы (профиль
platform, документы); ядру — нет.
Хранилище выключено совсем
Если CP_S3_ENDPOINT_URL пуст, Control Plane работает без хранилища:
артефакты-ссылки и JSON-артефакты создаются как обычно, а маршруты
содержимого отвечают 503 content_store_unavailable. В поставочном
compose.yml адрес по умолчанию — http://minio:9000.
Резервное копирование¶
Том platform_minio содержит и документы панели, и содержимое артефактов
ядра. Бэкапьте его вместе с базами:
control-plane-db↔ MinIO. Записи артефактов — в базе Control Plane, байты — в MinIO. Снимайте их в одном окне. Если том MinIO старше базы, у части записейcontentState = storedобъекта не окажется, и выдача таких артефактов ответит503 content_store_unavailable.platform-db↔ MinIO — так же для документов панели.
Скрипт ежедневного бэкапа и порядок восстановления — в Резервном копировании. Снимайте копию тома после дампа базы 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 |
docker compose ps minio minio-bootstrap, логи minio-bootstrap; проверить ключи в .env и политику |
503 content_store_unavailable только при чтении отдельных артефактов |
Объекта нет в хранилище при записи stored: том восстановлен из более старой копии, чем база |
Восстановить том MinIO из копии, согласованной с базой |
docker 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) |