MAATRIX / Блог / S3-совместимое хранилище у себя: зачем и на чём

S3-совместимое хранилище у себя: зачем и на чём

MAATRIX

Приложение уже умеет работать с S3 — SDK встроен, настройки на месте, — но платить за облачное объектное хранилище стороннего провайдера вы не хотите: то ли из-за цены на объёме, то ли из-за зависимости от чужой инфраструктуры, то ли просто потому, что данные должны оставаться на вашем железе. Хорошая новость: S3 — это не облако AWS, а протокол. Его можно поднять у себя и получить тот же интерфейс, но с полным контролем над данными.

Зачем разворачивать S3-совместимое хранилище у себя

S3 (Simple Storage Service) появился как продукт Amazon, но за прошедшие годы его HTTP API — PUT/GET/DELETE объектов, bucket'ы, presigned URL, multipart upload — стал де-факто отраслевым стандартом интерфейса для объектного хранения. Это не преувеличение: сегодня подавляющее большинство фреймворков, self-hosted сервисов и утилит резервного копирования умеют работать именно с этим API «из коробки», даже если никогда не видели настоящий AWS. Разницу между объектным хранилищем и обычной файловой системой — почему объекты, а не файлы в папках, и когда это вообще нужно — мы разбирали отдельно в статье про объектное хранилище против файловой системы; здесь же — практический вопрос: как получить этот интерфейс не в чужом облаке, а на своём сервере.

Смысл в том, что S3-совместимость — это соглашение об API, а не привязка к конкретному провайдеру. Если вы развернули у себя сервер, который отвечает на те же HTTP-запросы, что и AWS S3, — с той же подписью запросов (AWS Signature), теми же заголовками, тем же поведением bucket'ов — то приложение, написанное для работы с S3, будет работать с вашим хранилищем без единой правки в коде. Меняется только один параметр — адрес эндпоинта (endpoint URL), — а иногда ещё регион и флаг «путь вместо поддомена» (path-style access). Ключи доступа, SDK, логика загрузки/скачивания — всё остаётся прежним.

Отсюда и практическая выгода:

  • Экономика на объёме. Облачные объектные хранилища обычно берут не только за хранение, но и за исходящий трафик (egress) — при больших объёмах скачивания это может быть заметной статьёй расходов. У себя на сервере вы платите за диск и канал один раз, независимо от того, сколько раз скачали файл.
  • Контроль и предсказуемость. Данные физически лежат там, где вы решили — важно для требований к резидентности данных, для параноика внутри вас или просто для спокойствия.
  • Отсутствие vendor lock-in. Приложение говорит на языке S3 — а этот язык одинаков что у AWS, что у вашего сервера. Миграция в обе стороны — это смена endpoint, а не переписывание интеграции.
  • Знакомый интерфейс без обучения с нуля. Разработчики и так знают S3 API — не нужно осваивать проприетарный протокол ради базовой функции «положить и забрать файл».

Честно: это не бесплатный обед. Ниже — и про то, на чём это поднять, и про то, что вы берёте на себя взамен.

На чём технически поднять такое хранилище

Технически задача звучит так: нужен сервер, который реализует S3 API поверх обычного дискового пространства. Это отдельный класс открытого ПО — не файловый сервер и не NAS-прошивка, а именно сервис, слушающий HTTP(S), понимающий подпись запросов AWS Signature v4, умеющий bucket'ы, объекты, политики доступа и multipart upload.

Такое ПО обычно предлагает сразу два интерфейса:

  1. Веб-консоль — для человека: создать bucket, посмотреть список объектов, настроить права, сгенерировать ключи доступа, включить версионирование.
  2. Стандартный S3 API — для программ: тот же порт (или соседний), но вместо браузера туда стучится ваше приложение, скрипт бэкапа или CI-раннер через SDK (boto3, aws-cli, AWS SDK для Node/PHP/Go и т.д.).

Самый известный представитель этого класса — MinIO: мы разбирали его установку и эксплуатацию отдельно, в статьях как установить и настроить MinIO на VPS и MinIO в docker-compose — там пошагово, с TLS и systemd. Но важно понимать: MinIO — не единственный вариант, а один из представителей класса. Существуют и другие открытые реализации S3-совместимого API поверх собственного диска, в том числе распределённые, рассчитанные на кластер из нескольких узлов с избыточностью на уровне самого ПО (erasure coding), а не RAID-контроллера. Конкретный выбор продукта и его актуальная версия — вопрос отдельного исследования на момент внедрения: экосистема развивается, и то, что верно сегодня, может устареть через полгода. Здесь важна не марка, а сам принцип: открытое ПО + свой диск + S3 API поверх этого.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть ИИ на сервере

Как это выглядит на практике: минимальный пример

Чтобы не быть голословным, вот минимальный запуск такого сервиса в контейнере — на примере MinIO, просто чтобы показать форму, а не как исчерпывающую инструкцию (полный вариант с TLS и постоянным хранением — в статьях выше):

docker run -d \
  --name object-storage \
  -p 9000:9000 \
  -p 9001:9001 \
  -e "MINIO_ROOT_USER=admin" \
  -e "MINIO_ROOT_PASSWORD=ChangeMeToStrongPassword" \
  -v /srv/object-storage/data:/data \
  minio/minio server /data --console-address ":9001"

Что здесь происходит:

  • порт 9000 — тот самый S3 API, куда стучатся приложения и SDK;
  • порт 9001 — веб-консоль для человека;
  • /srv/object-storage/data на хосте — реальное дисковое пространство, где физически лежат объекты;
  • root-пользователь и пароль — стартовые учётные данные, от которых дальше создаются отдельные ключи доступа (access key / secret key) для каждого приложения — не используйте root-пару в продакшене нигде, кроме первого входа в консоль.

Дальше в веб-консоли создаётся bucket (например, app-media или ci-artifacts), и для него выпускаются ключи доступа с ограниченными правами — отдельные для бэкапов, отдельные для приложения, отдельные для CI. Это тот же принцип, что и в IAM у AWS, только настраиваете и выдаёте права вы сами.

Для проверки, что API отвечает, достаточно стандартного клиента:

aws configure set aws_access_key_id ВАШ_ACCESS_KEY --profile selfhosted
aws configure set aws_secret_access_key ВАШ_SECRET_KEY --profile selfhosted

aws --endpoint-url https://storage.example.ru:9000 \
    --profile selfhosted \
    s3 mb s3://app-media

aws --endpoint-url https://storage.example.ru:9000 \
    --profile selfhosted \
    s3 cp ./photo.jpg s3://app-media/uploads/photo.jpg

Обратите внимание: это команды родного aws-cli от Amazon, без единой модификации — работает, потому что мы говорим на одном языке API.

Совместимость приложений: меняется endpoint, а не код

Это ключевой практический момент всей статьи. Большинство библиотек и фреймворков, умеющих работать с S3, принимают набор параметров примерно такого вида:

ПараметрЗначение для AWS S3Значение для своего хранилища
endpoint_urlне указывается (используется по умолчанию)https://storage.example.ru:9000
regionнапример, eu-west-1любое значение, часто us-east-1 как совместимое по умолчанию
access_key / secret_keyвыданные AWSвыданные вашей консолью хранилища
force_path_style / path_styleобычно falseчасто нужно true (bucket в пути, а не в поддомене)
bucketимя bucket в AWSимя bucket в вашем хранилище

Пример на Python (boto3), без единой строчки специфичного для конкретного продукта кода:

import boto3

s3 = boto3.client(
    "s3",
    endpoint_url="https://storage.example.ru:9000",
    aws_access_key_id="ВАШ_ACCESS_KEY",
    aws_secret_access_key="ВАШ_SECRET_KEY",
    region_name="us-east-1",
)

s3.upload_file("report.pdf", "app-media", "reports/report.pdf")

Если приложение уже написано под S3 (а это касается практически всех современных фреймворков для загрузки файлов — от Django с django-storages до Laravel с встроенным S3-драйвером, и большинства self-hosted платформ, умеющих писать объекты во внешнее хранилище), то весь переход на своё хранилище сводится к смене нескольких переменных окружения в конфиге приложения. Код, который умеет "положить файл в S3", не знает и не должен знать, чей это S3 — AWS, ваш сервер или ещё чей-то.

Практические сценарии использования

На практике S3-совместимое хранилище у себя закрывает три повторяющиеся задачи:

Резервное копирование через инструменты, ожидающие S3 API. Большинство современных бэкап-утилит умеют писать снапшоты и архивы в объектное хранилище напрямую, воспринимая его как «облако», хотя физически это ваш собственный сервер в соседней стойке или в другом дата-центре. Настраивается это ровно так же, как для настоящего AWS S3 — только endpoint свой. Это удобно тем, что бэкап физически отделён от сервера-источника (другой диск, а лучше другая машина), но не привязан к конкретному облачному провайдеру и его тарифам.

Хранение пользовательских медиа-файлов приложения. Аватарки, загруженные документы, сгенерированные отчёты, обложки — всё, что раньше складывалось в папку /uploads на диске веб-сервера, лучше выносить в объектное хранилище: так приложение можно масштабировать на несколько серверов без проблемы «файл загрузили на один сервер, а второй его не видит». S3-совместимое хранилище у себя даёт это разделение без ежемесячного счёта за исходящий трафик у стороннего облака.

Промежуточное хранилище для CI/CD-артефактов. Результаты сборки, Docker-слои для кэша, тестовые отчёты — CI-раннерам часто нужно куда-то сложить артефакт между этапами пайплайна или сохранить его после сборки. Многие CI-системы поддерживают выгрузку артефактов в S3-совместимое хранилище нативно, через тот же принцип: endpoint, ключи, bucket. Это избавляет от раздувания диска самого раннера и от необходимости платить внешнему облаку за то, что живёт там условные несколько дней.

Общий знаменатель всех трёх сценариев один: приложению или утилите нужен «S3 где-то там», а вам не обязательно платить за это облачному провайдеру — можно предоставить свой.

Честный компромисс: контроль против встроенной отказоустойчивости

Здесь — самая важная часть статьи, и не совсем рекламная. Крупные облачные провайдеры не просто продают вам место на диске — они продают географическую репликацию, автоматическое избыточное хранение на нескольких физических носителях и дата-центрах, и SLA на доступность и сохранность данных, выстроенные годами инженерной работы, которую вы не видите и не оплачиваете отдельной строкой.

Когда вы поднимаете S3-совместимое хранилище на своём сервере, вы получаете тот же удобный интерфейс — но не получаете эту инфраструктуру автоматически. Это ваша задача, и её нужно продумать заранее, а не после первого отказа диска:

  • Отказоустойчивость самого диска. Один диск на одном сервере — это единая точка отказа. RAID-массив снижает риск потери данных при отказе одного диска, но не спасает при отказе всего сервера, блока питания или при ошибке администратора (в том числе вашей).
  • Резервное копирование хранилища как отдельная задача. Ваше S3-совместимое хранилище может быть конечной точкой для чужих бэкапов (см. сценарий выше) — но кто бэкапит само хранилище? Если это единственная копия данных, при потере сервера вы теряете и оригиналы, и резервные копии одновременно. Мы отдельно разбирали этот нюанс на примере конкретного ПО в статье про бэкап и восстановление MinIO — принцип актуален для любого self-hosted S3-совместимого решения.
  • География. Один сервер — один физический адрес. Если критично пережить отказ целого дата-центра, нужна вторая копия в другом месте: либо второй узел вашего хранилища в другом регионе, либо периодическая синхронизация в стороннее объектное хранилище как холодный резерв.
  • Мониторинг и место на диске. У облачного провайдера место закончится не «внезапно» — оно просто продолжит расти и в конце месяца придёт счёт. У своего сервера диск может физически закончиться, и это авария, а не строчка в биллинге. Нужен мониторинг заполненности заранее.

Честный вывод: самостоятельно развёрнутое S3-совместимое хранилище — это не бесплатная замена надёжности облака, а осознанный компромисс. Вы выигрываете в контроле, предсказуемости расходов и независимости от провайдера — особенно заметно на больших объёмах данных. Взамен вы берёте на себя ответственность за то, что раньше решал чужой инженерный отдел: резервирование, географическую избыточность и мониторинг. Для многих сценариев (внутренние бэкапы, медиатека небольшого приложения, буфер для CI) это более чем оправданный размен. Для данных, потеря которых недопустима ни при каких условиях, разумный подход — не полагаться только на один self-hosted узел, а держать вторую независимую копию отдельно, в том числе, возможно, у стороннего облачного провайдера как последний рубеж.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть ИИ на сервере

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Обязательно ли использовать именно MinIO?

Нет, это самый известный представитель класса, но не единственный. Принцип — открытое ПО, реализующее S3 API поверх диска, — шире одного продукта; выбор конкретной реализации стоит делать исходя из актуального состояния экосистемы на момент внедрения.

Заработает ли моё приложение без изменений в коде?

Если оно уже использует S3 SDK (boto3, aws-sdk, django-storages и подобные) — да, в подавляющем большинстве случаев меняются только endpoint, ключи доступа и, возможно, флаг path-style access. Логика загрузки/скачивания объектов остаётся той же.

Нужен ли отдельный сервер под хранилище?

Не обязательно для небольших нагрузок — можно развернуть на том же сервере, что и приложение, если ресурсов хватает. Но для нагруженных сценариев и для настоящей отказоустойчивости хранилище стоит выносить на отдельный сервер или несколько.

Что если данные в моём хранилище потеряются?

Тогда встаёт вопрос резервной копии самого хранилища — см. раздел про честный компромисс выше. Полагаться только на один self-hosted узел без отдельного бэкапа рискованно для действительно важных данных.

Дороже или дешевле, чем облачное объектное хранилище?

Зависит от объёма и трафика. На малых объёмах разница может быть незаметна или даже не в пользу self-hosted (нужно администрировать самому). На больших объёмах с активным скачиванием (egress-трафик) собственное хранилище часто выигрывает по деньгам, но проигрывает по объёму «бесплатной» инженерной работы, которую в облаке вы не видите.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →