RE:NODE

Эксплуатация10 мин чтения

Объектное хранилище S3: бакеты, ключи и эндпоинты

Что такое объектное хранилище и как работает S3: бакеты, объекты и ключи, эндпоинты, подписи и регионы, что на деле значит S3-совместимое и для чего оно подходит.

0 прочтений

Объектное хранилище - это большое плоское хранилище «ключ - значение», с которым вы общаетесь по HTTP. Вы кладёте файл целиком под каким-то именем в бакет, а потом получаете его целиком обратно по этому имени. Нет каталогов, нет дописывания в конец и нет правки на месте - измените один байт, и объект придётся загрузить заново. S3 - это API Amazon для всего этого, и он стал стандартом: «S3-совместимое» хранилище - это любой сервис, который отвечает на те же HTTP-запросы, поэтому AWS CLI, rclone, restic, Cyberduck и любая библиотека S3 работают с ним после изменения одной настройки - эндпоинта. Эта модель идеально подходит для бэкапов, загруженных медиафайлов, статических ресурсов и архивов и не подходит для баз данных и всего, что программа постоянно редактирует. В этой статье модель объяснена как следует, чтобы инструменты из остальных статей серии были понятны.

Бакеты, объекты и ключи#

Вся модель данных описывается тремя существительными.

  • Бакет - именованный контейнер. Каждый объект живёт ровно в одном бакете. Учётные данные и настройки обычно применяются на уровне бакета.
  • Объект - это данные, любые байты от нуля до очень большого объёма, плюс метаданные о них.
  • Ключ - имя объекта внутри бакета. backups/2026-10-08/world.tar.gz - это один ключ; косые черты в нём - просто символы.

В Amazon S3 имена бакетов - от 3 до 63 символов из строчных латинских букв, цифр, дефисов и точек, начинаются и заканчиваются буквой или цифрой и не выглядят как IP-адрес. S3-совместимые серверы часто принимают больше, но если ограничиться строчными буквами, цифрами и дефисами, бакет останется переносимым, а позже не будет проблем с сертификатами из-за точек. Ключи могут быть длиной до 1024 байт в UTF-8 и содержать почти что угодно, хотя пробелы, +, # и не-ASCII-символы провоцируют ошибки URL-кодирования в менее аккуратных инструментах.

Папки - это иллюзия

Пространство имён внутри бакета плоское. То, что инструменты показывают как папки, - трюк листинга: запросите ключи с префиксом backups/ и разделителем /, и сервер вернёт объекты непосредственно под этим префиксом плюс список «общих префиксов» следующего уровня - backups/2026-10-07/, backups/2026-10-08/, - которые клиенты рисуют как папки.

code
bucket: renode-backups  backups/2026-10-07/world.tar.gz  backups/2026-10-07/db.sql.gz  backups/2026-10-08/world.tar.gz  media/avatars/u123.png

Прямые следствия:

  • «Пустой папки» не существует, если какой-нибудь инструмент не создал объект нулевого размера с / на конце, чтобы её изобразить.
  • Переименование папки - это копирование и удаление каждого объекта под её префиксом. На миллионе объектов это два миллиона запросов.
  • Листинг постраничный - ListObjectsV2 в S3 возвращает не больше 1000 ключей за запрос, - поэтому подсчёт содержимого большого бакета требует множества обменов с сервером.

Что такое объект на самом деле#

Объект - это неизменяемые байты плюс метаданные. Метаданные, которые стоит знать:

ПолеЧто это
Content-LengthРазмер в байтах
Content-TypeMIME-тип, возвращается браузерам - для медиа задавайте правильно
ETagОтпечаток версии; для простых загрузок обычно MD5 содержимого
Last-ModifiedКогда записана эта версия
x-amz-meta-*Ваши собственные метаданные «ключ - значение», задаются при загрузке
Cache-Control, Content-DispositionПередаются HTTP-клиентам

Метаданные задаются при записи объекта. Чтобы их изменить, нужно скопировать объект поверх самого себя с новыми метаданными - с точки зрения сервера это ещё одна полная запись.

Большие объекты загружаются по частям. Multipart-загрузка начинается, отправляет части (в Amazon каждая от 5 MiB до 5 GiB, кроме последней, всего до 10 000 частей) и завершается; затем сервер собирает их в один объект. Части загружаются параллельно, а упавшая часть повторяется отдельно, поэтому каждый серьёзный инструмент переходит на multipart выше определённого порога. ETag multipart-объекта - это не MD5 файла: он заканчивается на - и число частей, - так что инструментам, которые проверяют загрузку по ETag, нужно знать, какой именно вид загрузки они сделали. В Amazon один PUT ограничен 5 GiB, а объект - 5 TiB; другие реализации задают свои лимиты.

Незавершённая multipart-загрузка оставляет свои части в хранилище, пока её не завершат или не прервут. Инструменты обычно убирают за собой, но упавшая загрузка может оставить части, которые занимают место, не появляясь в виде объекта. aws s3api list-multipart-uploads --bucket NAME их показывает.

API - это просто HTTP#

Каждая операция - это HTTP-запрос к эндпоинту. Поэтому S3 так легко поддерживать и поэтому он работает через обычные прокси и файрволы.

ОперацияHTTP-запрос
Загрузить объектPUT /bucket/key
Скачать объектGET /bucket/key (заголовок Range получает его часть)
Прочитать только метаданныеHEAD /bucket/key
Удалить объектDELETE /bucket/key
Получить список объектовGET /bucket?list-type=2&prefix=...
Скопировать на стороне сервераPUT /bucket/newkey с x-amz-copy-source
Создать бакетPUT /bucket

Именно GET с диапазоном делает объектное хранилище пригодным для потокового видео и для инструментов бэкапа вроде restic, которые читают маленькие кусочки больших pack-файлов. А копирование на стороне сервера делает возможным «переименование» без скачивания.

Учётные данные и подписи

Вы получаете две строки: access key ID, который идентифицирует вас и секретом не является, и secret access key, который является. Секрет никогда не передаётся по сети. Вместо этого клиент подписывает каждый запрос по Signature Version 4: строит каноническое описание запроса (метод, путь, параметры запроса, выбранные заголовки, хеш тела) и вычисляет цепочку HMAC из секрета, даты, региона и имени сервиса. Сервер пересчитывает подпись своей копией секрета и отклоняет запрос, если они не совпадают.

Два практических следствия:

  • Регион - часть подписи. Клиент и сервер должны о нём договориться. У Amazon регионы настоящие; S3-совместимый эндпоинт может принимать любое имя. Выберите одно - us-east-1 - общепринятая заглушка - и используйте его во всех инструментах.
  • Время имеет значение. Подпись содержит метку времени, и Amazon отклоняет запросы, которые расходятся с его часами больше чем на 15 минут, с ошибкой RequestTimeTooSkewed. Сервер со сбитыми часами порождает непонятные ошибки подписи; прежде всего проверьте date.

Подписи позволяют также делать presigned URL: ссылку с подписью в строке запроса, действующую ограниченное время, по которой человек без учётных данных может загрузить или скачать один конкретный объект. О них - статья presigned URL в S3 для загрузок.

Эндпоинты, адресация и HTTPS#

Эндпоинт - это базовый URL сервиса. Бакет в запросах указывается одним из двух способов:

  • Path-style: https://s3.example.com/my-bucket/photos/cat.jpg - бакет является первым сегментом пути.
  • Virtual-hosted style: https://my-bucket.s3.example.com/photos/cat.jpg - бакет является поддоменом.

Amazon предпочитает virtual-hosted; многие S3-совместимые серверы, особенно однопользовательские на одном имени хоста, используют path-style, потому что для него не нужны wildcard-DNS и wildcard-сертификат. Большинство инструментов по умолчанию используют virtual-hosted, и для переключения нужна одна настройка. Причины разобраны в статье path-style и virtual-hosted в S3.

подписанный запрос по TLSперенаправленPUT / GET / LISTКлиент или утилитаaws, rclone, resticИмя хоста HTTPSсертификат на проксиЭндпоинт S3HTTP на своём портуБакетобъекты по ключу
Один запрос к S3-совместимому эндпоинту

Для всего, что идёт через интернет, используйте HTTPS. Подпись SigV4 защищает секретный ключ и не даёт подменить подписанные части запроса, но по обычному HTTP данные объектов, имена ключей и ваш access key ID может прочитать любой на пути. В RE:NODE эндпоинт отвечает по обычному HTTP на своём порту, а в каждом тарифе есть слот прокси: направьте на него A-запись имени хоста, и сертификат будет выпущен и продлён автоматически, так что клиенты подключаются по HTTPS к вашему собственному имени.

Что «S3-совместимое» обещает, а что нет#

Ядро API S3 - бакеты, PUT, GET, HEAD, DELETE, листинг, multipart-загрузки, копирование, presigned URL - одинаково реализовано почти в каждом совместимом сервере, и это всё, что нужно инструментам бэкапа и синхронизации. Но у Amazon S3 поверх этого есть длинный хвост возможностей: версионирование, правила жизненного цикла, которые удаляют или перемещают объекты, object lock для хранения в режиме однократной записи, политики бакетов и IAM, классы хранения вроде Glacier, уведомления о событиях, репликация и несколько разновидностей шифрования на стороне сервера. Совместимые серверы реализуют разные подмножества этого хвоста или не реализуют его вовсе.

Так что «S3-совместимое» означает «ваши инструменты для S3 подключатся и будут перемещать данные», а не «в нём есть каждая возможность из документации AWS». Прежде чем строить решение вокруг какой-то возможности, проверьте, что ваш сервис её предлагает.

Линейка хранилища RE:NODE описывается в терминах ядра: S3-совместимый эндпоинт, access key и secret key, сгенерированные для каждого сервера, первый бакет, созданный за вас, path-style адресация, любое имя региона, и работает она с AWS CLI, rclone, Cyberduck, restic и S3-драйверами в приложениях. Версионирование, правила жизненного цикла, object lock и политики бакетов в это описание не входят, так что не рассчитывайте на них. Срок хранения бэкапов должен задаваться в инструменте бэкапа - например, политикой forget в restic, - и дополнительный плюс в том, что это одинаково работает с любым S3-эндпоинтом, на который вы потом переедете.

Есть ещё согласованность. С декабря 2020 года Amazon S3 гарантирует строгую согласованность чтения после записи: как только PUT вернул ответ, каждый GET и листинг видит объект. Большинство одноузловых совместимых серверов естественным образом ведут себя так же, но это свойство реализации, а не API, и инструменты, написанные до 2020 года, рассчитаны на меньшие гарантии.

Для чего объектное хранилище подходит, а для чего нет#

Хорошо подходит:

  • Бэкапы и архивы. Записываются один раз, читаются редко, инструментами, созданными для этого. Два основных инструмента разобраны в статьях бэкапы restic в S3 и rclone с хранилищем S3.
  • Загрузки пользователей и медиа. Аватары, вложения, изображения. Приложение хранит ключ в своей базе данных и отдаёт файл по URL; диск сервера приложения остаётся небольшим, а загрузки переживают повторный deploy. Код показан в статье S3 из Node и Python, а версия для CMS - в статье вынос медиа WordPress в S3.
  • Статические ресурсы и артефакты сборки. Версионированные имена файлов, запись один раз.
  • Логи и выгрузки. Данные только на дописывание, которые ротацией уходят в новые объекты.

Плохо подходит:

  • Базы данных. База данных постоянно пишет маленькие кусочки больших файлов. Объектное хранилище умеет только заменять объекты целиком. Храните в нём дампы баз данных, а не сами базы.
  • Файлы, которые правятся на месте. Таблица, сохраняемая каждую минуту, - это полная загрузка каждую минуту.
  • Миллионы крошечных файлов. Каждый объект стоит запроса и некоторого количества метаданных. Упаковывайте мелкие файлы в архивы - именно так и делают инструменты бэкапа.
  • Замена файловой системы. Монтирование бакета через rclone mount или аналог работает для просмотра и редкого копирования, но приложения, ожидающие семантики POSIX - блокировок, переименований, частичной записи, - ведут себя на нём плохо.

Надёжность: одна копия - это всё равно одна копия#

Amazon заявляет для S3 Standard надёжность в одиннадцать девяток, потому что хранит каждый объект с избыточностью в нескольких дата-центрах. Эта цифра - свойство устройства хранилища Amazon, а не API S3, и S3-совместимый сервис надёжен ровно настолько, насколько надёжны диски и копии за ним.

Линейка хранилища RE:NODE хранит одну копию ваших данных, на NVMe, в одном месте в Германии. Она не реплицируется. Это делает её хорошим вторым местом для бэкапов - вне машины, которую они защищают, и в формате, который понимает любой инструмент бэкапа, - и плохим единственным местом. Для всего, что вы не можете позволить себе потерять, следуйте правилу 3-2-1: три копии, на двух видах хранилищ, одна совсем в другом месте. Как это выглядит на практике, разобрано в статье размер хранилища S3 и правило 3-2-1, а почему проверка восстановления важнее самой копии - в статье бэкапы, которые реально восстанавливаются.

FAQ#

S3 - это то же самое, что Amazon S3?

S3 начинался как Simple Storage Service от Amazon, а теперь это название обозначает ещё и его API, который реализуют многие другие провайдеры и open-source серверы. Когда люди говорят «S3-хранилище» вне AWS, они обычно имеют в виду S3-совместимое: те же запросы, другой эндпоинт.

Можно ли отредактировать часть файла в объектном хранилище?

Нет. Объекты заменяются целиком. Часть объекта можно прочитать через GET с диапазоном, но запись означает загрузку полной новой версии. Инструменты, которые будто бы редактируют на месте, скачивают, меняют и загружают заново.

Чем объектное хранилище отличается от блочного?

Блочное хранилище - это диск: операционная система создаёт на нём файловую систему и читает и пишет любой байт. Объектное хранилище - это сервис: вы отправляете целые файлы по HTTP и обращаетесь к ним по ключу. Базам данных и операционным системам нужно блочное хранилище; бэкапам и медиа удобнее в объектном.

Зачем нужен регион, если серверу всё равно?

Потому что он входит в подпись запроса. Клиент использует регион, чтобы вычислить ключ подписи, а сервер должен использовать тот же, чтобы её проверить. На эндпоинте, который принимает любое имя региона, выберите одно и настройте с ним каждый клиент.

Нужен ли HTTPS, если запросы подписаны?

Да, для всего, что выходит за пределы одной частной сети. Подпись защищает ваш секретный ключ и целостность подписанных частей, но не конфиденциальность: без TLS содержимое ваших файлов и их имена идут открытым текстом.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000