Ответ
В моей работе с AWS S3 обновление объектов — это операция полной перезаписи. S3 — это объектное хранилище, а не файловая система, поэтому частичные обновления (как в блочных хранилищах) не поддерживаются.
Ключевые аспекты процесса:
- Полная перезапись: При загрузке нового объекта с тем же ключом (путем) старый объект полностью заменяется.
- Идемпотентность: Операция PUT на один и тот же ключ всегда дает одинаковый результат — последний загруженный объект.
Важные особенности и практики:
-
Версионность (Versioning):
# Включение версионности для бакета aws s3api put-bucket-versioning --bucket my-bucket --versioning-configuration Status=Enabled # После включения старые версии сохраняются и могут быть восстановлены aws s3api list-object-versions --bucket my-bucket --prefix path/to/file.txtПри версионности «удаление» — это лишь добавление маркера удаления, а старые версии остаются и продолжают накапливать стоимость хранения.
-
Метаданные и теги:
# Обновление объекта с изменением метаданных aws s3 cp local_file.txt s3://my-bucket/path/file.txt --metadata "environment=production,owner=devops-team" --metadata-directive REPLACE # Обновление тегов объекта aws s3api put-object-tagging --bucket my-bucket --key path/file.txt --tagging 'TagSet=[{Key=CostCenter,Value=123}]'Метаданные и теги не обновляются автоматически при перезаписи объекта — их нужно указывать явно.
-
Согласованность (Consistency Model):
- Новые объекты (PUTs): Обеспечивается сильная согласованность в рамках одного региона. После успешного ответа
200 OKвсе последующие запросы GET вернут новый объект. - Перезапись и удаление (PUTs и DELETEs): Обеспечивается eventual consistency. После обновления может быть короткое окно, когда разные запросы GET могут вернуть старую или новую версию.
- Новые объекты (PUTs): Обеспечивается сильная согласованность в рамках одного региона. После успешного ответа
-
Атомарные условные операции: Для реализации механизмов блокировки или оптимистичной блокировки (например, при обновлении конфигурационных файлов из нескольких процессов) используются условные заголовки.
# Загрузка только если объект не существует aws s3api put-object --bucket my-bucket --key config.json --body new_config.json --header "x-amz-acl: bucket-owner-full-control" --header "x-amz-metadata-directive: REPLACE" # Или с If-None-Match="*" через низкоуровневый API
Типичный DevOps-сценарий — обновление конфигурации приложения:
- Я собираю новый артефакт (например, скомпилированный файл конфигурации).
- Загружаю его в S3 с уникальным ключом, включающим хэш или версию:
s3://my-app-config/config-v2.1.5.json. - Обновляю системный параметр (например, в AWS SSM Parameter Store или в манифесте Kubernetes), указывающий на новый ключ S3.
- Приложение, загружающее конфиг из S3, начинает использовать новую версию. Старая версия остается в S3 для отката.
Такой подход обеспечивает атомарность обновления, версионность и возможность отката без риска "перезаписать на лету" файл, который в данный момент читается.