← назад к разделу

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

S3 как место для резервных копий

S3 — удобный целевик для резервных копий любых систем: дампы PostgreSQL, снапшоты MongoDB и Elasticsearch, конфигурационные файлы, зашифрованные секреты.

Почему S3 хорошо подходит для этой роли:

  • Надёжность 99.999999999% (11 девяток) — данные хранятся в нескольких зонах доступности внутри одного региона.
  • Холодные классы хранения — Glacier Deep Archive стоит около $1 за терабайт в месяц; ежедневные бэкапы годичной давности хранить почти бесплатно.
  • Версионирование защищает от случайного удаления и вирусов-шифровальщиков: «удалённый» объект на самом деле получает метку удаления, старая версия остаётся.
  • Репликация в другой регион обеспечивает восстановление при катастрофах.

Типичная структура бакета с резервными копиями выглядит так:

s3://backup-bucket/
  ├── pg/          ← дампы PostgreSQL
  ├── mongo/       ← дампы MongoDB
  ├── es/          ← снапшоты Elasticsearch
  └── app/         ← экспорты приложения

На бакете включают: версионирование, lifecycle-политику (переход в Glacier через 30 дней, удаление старых версий через 90), репликацию в другой регион.

Кросс-региональная репликация

AWS даёт 11 девяток надёжности, но главный враг данных — человеческая ошибка: случайно удалили бакет, скомпрометировали учётную запись.

Cross-Region Replication (CRR) решает обе проблемы. Каждый объект, помещённый в исходный бакет, асинхронно копируется в бакет-приёмник в другом регионе (или аккаунте). Если что-то случится с продакшн-аккаунтом — резервная копия недосягаема для атакующего.

Настройка через AWS CLI:

{
  "Role": "arn:aws:iam::ACCOUNT:role/replication-role",
  "Rules": [{
    "Status": "Enabled",
    "Destination": {
      "Bucket": "arn:aws:s3:::backup-dr-bucket",
      "StorageClass": "STANDARD_IA"
    },
    "DeleteMarkerReplication": { "Status": "Enabled" }
  }]
}

Важный момент: репликация работает только для новых объектов. Данные, которые уже лежат в бакете, не реплицируются автоматически — для них нужен aws s3 sync или S3 Batch Replication.

Версионирование и MFA Delete

Версионирование включают на уровне бакета. После включения каждый PUT создаёт новую версию объекта, а DELETE добавляет метку удаления — физически объект остаётся.

Для критичных бакетов с резервными копиями добавляют MFA Delete: удаление объектов требует одноразового кода с MFA-устройства root-аккаунта. Даже если учётка разработчика скомпрометирована — уничтожить бэкапы не получится.

aws s3api put-bucket-versioning \
  --bucket backup-bucket \
  --versioning-configuration Status=Enabled,MFADelete=Enabled \
  --mfa "arn:aws:iam::ACCOUNT:mfa/user 123456"

Object Lock — ещё жёстче: режим WORM (write-once-read-many) делает удаление физически невозможным на заданный срок, даже для администратора. Используется в compliance-бакетах для финансовых и медицинских данных.

Lifecycle-политики для разных случаев

Lifecycle управляет переходами между классами хранения и удалением объектов. Несколько типичных наборов:

Пользовательский контент (аватарки, загрузки):

- prefix: "tmp/"
  Expiration: 7 days

- prefix: "users/"
  NoncurrentVersionExpiration: 30 days
  AbortIncompleteMultipartUpload: 7 days

Журналы и аудит:

- prefix: "audit/"
  Transitions:
    - 30 days  → STANDARD_IA
    - 90 days  → GLACIER_FLEXIBLE
    - 365 days → DEEP_ARCHIVE
  Expiration: 2555 days   # 7 лет для compliance

Резервные копии PostgreSQL:

- prefix: "pg/"
  Transitions:
    - 7 days  → STANDARD_IA      # быстрое восстановление первой недели
    - 30 days → GLACIER_INSTANT  # доступ за минуты
    - 90 days → DEEP_ARCHIVE     # долгосрочное хранение
  Expiration: 365 days
  NoncurrentVersionExpiration: 30 days
  AbortIncompleteMultipartUpload: 1 day

Правило AbortIncompleteMultipartUpload стоит добавлять везде: незавершённые составные загрузки незаметно накапливаются и тоже биллятся.

Из чего складывается стоимость S3

AWS S3 выставляет счёт по трём статьям.

Хранение

Оплата за гигабайт в месяц. Класс хранения определяет цену:

Класс$/ГБ/месяц (us-east-1)Применение
Standard$0.023Активные данные
Standard-IA$0.0125Резервные копии, доступ раз в месяц
Glacier Instant$0.004Архив с возможностью быстрого доступа
Glacier Flexible$0.0036Compliance, доступ за часы
Deep Archive$0.00099Холодный архив, доступ за сутки

100 ТБ на Standard — около $2300 в месяц. На Deep Archive — около $100 в месяц.

Запросы

PUT/COPY/POST/LIST: ~$0.005 за 1000 запросов. GET: ~$0.0004 за 1000 запросов.

Для большинства приложений это незаметные суммы. Но если приложение пишет каждое событие отдельным файлом — счёт растёт. Миллион операций LIST в день = $5/день = $150 в месяц.

Типичная ошибка: писать миллион файлов по 1 КБ вместо одного файла в 1 ГБ. Стоимость хранения одинакова, а расходы на запросы — в миллион раз больше.

Исходящий трафик

Самая коварная статья. Трафик из S3 в интернет: ~$0.09 за ГБ.

100 ТБ в месяц = $9000. Для публичных бакетов с медиаконтентом эта статья часто превышает стоимость самого хранения.

Способы снизить:

  • CloudFront перед S3 — кэширование на граничных серверах снижает исходящий трафик из S3; трафик CloudFront → пользователь дешевле ($0.085/ГБ при объёме свыше 10 ТБ).
  • VPC Endpoint для трафика из EC2 в том же регионе — бесплатно. Для backend-сервисов, работающих в AWS, это нужно включать всегда.

Альтернативы AWS S3

ПровайдерИсходящий трафикОсобенность
AWS S3$0.09/ГБСтандарт
Backblaze B2$0.01/ГБS3-совместимый API, дешёвый трафик
Cloudflare R2бесплатноS3-совместимый API, нет платы за трафик
Wasabiбесплатно (с ограничениями)Дешёвое хранение
Yandex Object Storage~$0.005–0.01/ГБРоссийская юрисдикция

Cloudflare R2 — особенно интересен для публичного контента с большим трафиком: S3-совместимый API позволяет переключиться через endpointOverride в SDK без переписывания кода.

Мониторинг

Метрики CloudWatch

S3 автоматически отправляет метрики в CloudWatch:

МетрикаЧто значитПовод для сигнала
BucketSizeBytesРазмер бакета (раз в день)Внезапный скачок
NumberOfObjectsЧисло объектов (раз в день)Рост на тысячи в день
AllRequests / 4xxErrors / 5xxErrorsЗапросы и ошибкиОшибок > 0.1%
BytesDownloadedИсходящий трафикОснова для оценки затрат

Журналы доступа

Server access logging пишет каждый запрос в текстовый файл в другой бакет: IP, время, действие, ключ объекта, статус, размер, задержка, user-agent.

aws s3api put-bucket-logging --bucket production-bucket \
  --bucket-logging-status '{
    "LoggingEnabled": {
      "TargetBucket": "audit-bucket",
      "TargetPrefix": "logs/production-bucket/"
    }
  }'

Альтернатива — CloudTrail data events: формат JSON, чуть большая задержка, зато интегрируется с остальными событиями CloudTrail.

S3 Inventory

S3 Inventory формирует ежедневный (или еженедельный) отчёт по всем объектам бакета в формате CSV или Parquet. Колонки: ключ, размер, класс хранения, дата изменения, статус шифрования.

Полезно для проверки, что lifecycle-политика работает как ожидается, и для поиска «сирот» — объектов, у которых нет записей в базе данных.

Типичные проблемы и защита

Компрометация учётки и удаление данных

Сценарий: атакующий получил учётную запись с правами s3:DeleteObject и удалил всё содержимое.

Защита:

  • Versioning — объекты не удалены физически, только добавлены метки удаления. Восстановление через aws s3api list-object-versions.
  • MFA Delete — массовое удаление требует MFA-токен root-аккаунта.
  • Object Lock — физическое удаление невозможно на заданный срок.
  • Репликация в другой аккаунт — резервная копия недосягаема для скомпрометированной учётки.

Объекты ушли в Deep Archive по ошибке

Lifecycle-политика с неточным фильтром применилась к горячим данным. Чтение из Deep Archive занимает до 12 часов и стоит денег.

Защита: всегда проверяйте lifecycle-политику на небольшом тестовом префиксе перед применением ко всему бакету.

Восстановление: запрос restore-object, ожидание (до 12 часов), потом копирование в Standard.

Бакет случайно стал публичным

Ошибочные правки в bucket policy сделали весь бакет доступным извне. Возможна утечка данных и огромный счёт за исходящий трафик.

Защита: Block Public Access на уровне аккаунта — глобальный переключатель, который не позволяет ни одному бакету стать публичным, даже если кто-то изменил политику. Включайте на корневом аккаунте всегда.

Миллионы мелких файлов — неожиданный счёт

Каждое событие логируется отдельным PUT. Через месяц — миллионы файлов и заметные расходы на запросы.

Решение: накапливать события локально и сбрасывать в S3 пакетами раз в несколько минут или по достижении порогового размера. Amazon Kinesis Data Firehose делает это автоматически.

Чек-лист production-бакета

Минимальный набор настроек, который должен быть на каждом бакете в продакшне:

  • Block Public Access включён (на уровне аккаунта тоже)
  • Versioning включён
  • SSE-S3 или SSE-KMS (для новых бакетов включено по умолчанию с 2023 года, для старых — проверить)
  • Lifecycle-политика: прерывание незавершённых составных загрузок через 7 дней, удаление старых версий, переход в холодные классы
  • Сигнал CloudWatch на резкий рост размера и числа объектов
  • Журналы доступа или CloudTrail data events для аудита
  • Кросс-региональная репликация для критичных бакетов
  • VPC Endpoint для трафика из EC2/EKS
  • MFA Delete на бакетах с резервными копиями
  • IAM с минимальными правамиs3:* без ограничений недопустим

Коротко

  • S3 — надёжное место для резервных копий баз данных и файлов; Glacier Deep Archive снижает стоимость долгосрочного хранения до $1/ТБ в месяц.
  • Версионирование защищает от случайного удаления и вирусов-шифровальщиков — объект удаляется только физически, когда истечёт версия.
  • Cross-Region Replication копирует новые объекты в другой регион или аккаунт; для уже существующих объектов нужен aws s3 sync.
  • MFA Delete блокирует массовое удаление даже при компрометации учётки.
  • Стоимость S3 складывается из хранения, запросов и исходящего трафика; трафик — самая коварная статья ($0.09/ГБ в интернет).
  • VPC Endpoint делает трафик из EC2 в S3 внутри одного региона бесплатным.
  • Cloudflare R2 — S3-совместимый вариант без платы за исходящий трафик; переключение через endpointOverride.
  • CloudWatch, журналы доступа и S3 Inventory покрывают основные потребности в мониторинге.

Что почитать дальше

  • Fundamentals — устройство S3: бакет, объект, ключ, классы хранения.
  • Spring + AWS SDK v2 для S3 — работа с S3 из Java-приложения.
  • Эксплуатация Elasticsearch — S3 как цель для снапшотов Elasticsearch.