Зберігання
Навіщо це
Section titled “Навіщо це”У будь-якій системі є дані, які мають пережити віртуальну машину. Це завантажені користувачами файли, журнали, резервні копії, дані бази. Хмара пропонує для них три різні сховища, і різниця між ними визначає і надійність, і рахунок.
Диск віртуальної машини описується двома числами, які ви платите окремо: скільки IOPS і скільки мегабайтів за секунду ви замовили. Об’єктне сховище описується довговічністю у «11 дев’яток» і чотирма статтями рахунку: місце, запити, вилучення з холодних класів і вихідний трафік. Довговічність гарантує, що провайдер не втратить ваші об’єкти. Вона нічого не каже про те, що станеться, коли об’єкти видалите ви самі, а видалення й помилкові права доступу належать до типових причин втрат і витоків.
Тому модуль розбирає механізми: як влаштована консистентність, що саме означає довговічність, звідки беруться мінімальні строки зберігання, як працює тимчасове посилання і чому диск у хмарі оплачується за продуктивність.
Передумови. Регіони й зони доступності (модуль 1), акаунти й бюджети (модуль 2), політики й ролі (модуль 3), вихідний трафік і приватні ендпоінти (модуль 5). Як влаштовано блочний рівень, IOPS і черги запитів, розібрано в курсі ОС, а файлові системи, inode і журналювання в наступному модулі того курсу. Тут ці поняття вважаються відомими.
Три види сховища
Section titled “Три види сховища”Блочне сховище (block storage) віддає віртуальній машині масив блоків за
номерами, як фізичний диск. Файлову систему на ньому створюєте ви, тож із боку
машини це звичайний /dev/nvme1n1. Диск підключається до однієї машини
в межах однієї зони доступності (availability zone).
Файлове сховище (file storage) віддає готову файлову систему по мережі за протоколом NFS або SMB. Її одночасно монтують багато машин, а каталоги, права й блокування підтримує провайдер.
Об’єктне сховище (object storage) не має файлової системи взагалі. Воно
зберігає об’єкти в бакетах (buckets), кожен об’єкт має ключ, тіло й метадані,
а працюють з ним HTTP-запитами PUT, GET, DELETE і LIST.
Об’єктне сховище влаштоване інакше, ніж файлова система з курсу ОС, і це має практичні наслідки:
- «Папок» немає. Ключ
reports/2026/09/a.csvє одним рядком, а слеш у ньому лише договір між клієнтами. «Каталог» є префіксом, якийLISTуміє фільтрувати. - Об’єкт не змінюють частково. Щоб виправити один байт, завантажують об’єкт цілком. Дописати в кінець можна лише там, де сховище має окремий тип об’єкта для дописування.
- Перейменування не існує. Воно виконується як копіювання під новим ключем і видалення старого, тому для великого «каталогу» це мільйони запитів. Щоб мати справжні каталоги, Azure і Google Cloud пропонують ієрархічний простір імен, а Amazon S3 має для цього directory buckets.
- Блокувань немає. Два клієнти, які пишуть в один ключ, дадуть результат за
правилом «останній записав виграв». Для безпечного створення без
перезапису S3 підтримує умовні записи: заголовок
If-None-MatchуPutObjectвідхиляє запис, якщо ключ уже існує.
Дані, які пишуть один раз і читають цілком, найкраще лягають на об’єктне сховище. Диск, на якому працює база, потребує блочного.
Консистентність об’єктного сховища
Section titled “Консистентність об’єктного сховища”Консистентність (consistency) відповідає на питання: якщо запис завершився успішно, чи побачить наступне читання нові дані.
Amazon S3 до 1 грудня 2020 року давав таку гарантію лише частково. Новий
об’єкт було видно відразу, але після перезапису або видалення читання й
LIST могли ще якийсь час повертати старий стан. Щоб із цим жити, Hadoop-екосистема
тримала обхідні шляхи на кшталт S3Guard та EMRFS Consistent View, які
зберігали власний індекс у DynamoDB. Від грудня 2020 року S3 дає строгу
консистентність читання після запису (strong read-after-write) для PUT,
DELETE і LIST в усіх регіонах без додаткової плати й без втрати
продуктивності.
Azure Blob Storage і Cloud Storage мали строгу консистентність із самого початку. Тож для трьох провайдерів сьогодні правило однакове: успішний запис видно всім наступним читанням і переліками.
Чого консистентність не дає:
- Атомарності між ключами. Транзакція з двох об’єктів не існує, тому застосунок, який пише «дані» й «індекс» окремо, має продумати порядок запису і що робити, якщо упаде посередині.
- Захисту від конкурентних записів. Два одночасні
PUTв один ключ залишать той, що прийшов пізніше. Для оптимістичного блокування є умовні запити:If-None-MatchіIf-Matchв S3, ETag у Azure, передумови на generation у Cloud Storage. - Миттєвих змін конфігурації бакета. Налаштування бакета в S3 мають кінцеву консистентність: після першого ввімкнення версіонування документація радить почекати близько 15 хвилин, перш ніж писати й видаляти об’єкти.
Довговічність і чого вона не гарантує
Section titled “Довговічність і чого вона не гарантує”Довговічність (durability) вимірює ймовірність, що об’єкт не буде втрачений. Про доступність (availability), тобто чи відповість сховище зараз, вона нічого не каже. Ці два числа плутають найчастіше.
«Одинадцять дев’яток», 99.999999999%, означають розрахункову річну ймовірність втрати одного об’єкта, що дорівнює 10−11. За арифметикою, якщо зберігати 10 мільйонів об’єктів, чекати першої втрати доведеться близько 10 000 років. Механізм за цією цифрою простий: кілька копій даних у різних пристроях, стійкість до втрати цілої зони доступності, постійна перевірка контрольних сум і відновлення пошкоджених копій.
Числа в провайдерів такі:
| Сховище | Довговічність за рік | Доступність (задум) |
|---|---|---|
| S3 Standard, Standard-IA, Glacier | 99.999999999% (11 дев’яток) | 99.99% для Standard, 99.9% для Standard-IA |
| S3 One Zone-IA | ті самі 11 дев’яток, але одна зона | 99.5%; втрата зони може знищити дані |
| Azure Blob, LRS | щонайменше 11 дев’яток | щонайменше 99.9% на читання |
| Azure Blob, ZRS | щонайменше 12 дев’яток | щонайменше 99.9% на читання |
| Azure Blob, GRS і GZRS | щонайменше 16 дев’яток | 99.9%; читання з другого регіону лише в RA-варіантах |
| Cloud Storage | 11 дев’яток | залежить від типу розташування |
| EBS gp3 (диск, не об’єкти) | 99.8–99.9% за рік | окремий SLA; річна частка відмов тому до 0.2% |
Останній рядок важливий. Диск EBS має довговічність на вісім порядків нижчу за S3: до двох відмов на 1000 томів за рік. Тому знімки (snapshots) є не «додатковою» опцією, а способом отримати довговічність, якої сам диск не має.
Ці цифри є проєктним показником (designed for), а не гарантією: у договорі про рівень послуги (SLA) провайдери обіцяють кредити за недоступність, а не компенсацію за втрату даних. До того ж вони описують стан, який ви залишили в сховищі, а не те, що ви з ним зробили.
Документація Azure каже це прямо: усі репліки відображають той самий поточний стан, тому видалення й перезаписи застосовуються до всіх копій одночасно, а надлишковість захищає від збоїв обладнання, а не від змін даних. Отже, дані ви можете втратити так:
- команда
rm --recursiveабо цикл із помилкою в префіксі; - правило життєвого циклу з помилковим префіксом, яке видаляє те, що не мало;
- зламані облікові дані, якими атакувальник видаляє або шифрує об’єкти;
- закритий акаунт або підписка. У травні 2024 року в австралійського фонду UniSuper через помилку в конфігурації Google Cloud видалив підписку на приватну хмару, і, за спільною заявою компаній, видалення зачепило обидві геолокації. Відновленню допомогли копії в іншого провайдера (детальніше в модулі 7).
Захист працює шарами, і кожен шар закриває свою причину:
| Причина втрати | Що допомагає |
|---|---|
| Випадкове видалення чи перезапис | Версіонування (S3, Blob), soft delete (Blob, Cloud Storage) |
| Зловмисне видалення або шифрування | Object Lock в S3, immutable storage в Azure, retention policy і Bucket Lock у Cloud Storage: об’єкт не можна змінити до кінця строку, навіть адміністратору |
| Втрата зони | Класи з кількома зонами: S3 Standard, Azure ZRS, багаторегіональні бакети |
| Втрата регіону | Реплікація в інший регіон: S3 replication, Azure GRS, dual-region у Cloud Storage |
| Втрата акаунта або компрометація адміністратора | Копія в окремому акаунті або в іншого провайдера |
Реплікація в інший регіон не є резервною копією: вона повторює зміни, зокрема видалення, якщо вони входять у її налаштування. Що саме вона повторює, треба перевіряти окремо.
Класи зберігання і життєвий цикл
Section titled “Класи зберігання і життєвий цикл”Дані з часом охолоджуються: файл, якого вчора торкалися десять разів на день, через рік читають раз на квартал. Провайдери відповідають на це класами зберігання (storage classes): що холодніший клас, то дешевше тримати гігабайт, але дорожче його читати. Крім того, холодні класи мають мінімальний строк зберігання і платні запити.
Класи в трьох провайдерів:
| Провайдер | Клас | Зберігання, $/ГБ на міс. | Мін. строк | Вилучення, $/ГБ |
|---|---|---|---|---|
| AWS | S3 Standard | 0.023 | немає | 0 |
| AWS | S3 Standard-IA | 0.0125 | 30 діб | 0.01 |
| AWS | S3 Glacier Instant Retrieval | 0.004 | 90 діб | 0.03 |
| AWS | S3 Glacier Flexible Retrieval | 0.0036 | 90 діб | залежить від швидкості, дані «офлайн» |
| AWS | S3 Glacier Deep Archive | див. прайс | 180 діб | залежить від швидкості, години |
| Azure | Hot | 0.0208 | немає | 0 |
| Azure | Cool | 0.0152 | 30 діб | 0.01 |
| Azure | Cold | 0.0036 | 90 діб | 0.03 |
| Azure | Archive | 0.00099 | 180 діб | 0.02, до 15 годин на розморожування |
| GCP | Standard | 0.020 | немає | 0 |
| GCP | Nearline | 0.010 | 30 діб | 0.01 |
| GCP | Coldline | 0.004 | 90 діб | 0.02 |
| GCP | Archive | 0.0012 | 365 діб | 0.05 |
Ціни станом на вересень 2026, регіони us-east-1, eastus і us-central1. Мінімальний строк Cool і Cold в Azure застосовується в акаунтах general-purpose v2.
Рахунок за холодний клас складається з чотирьох частин:
- Зберігання за гігабайт на місяць. Це єдина частина, яку показує реклама.
- Запити. Вони теж дорожчають із охолодженням:
PUTу S3 Standard коштує $0.005 за тисячу, у Standard-IA $0.01, у Glacier Instant Retrieval $0.02. Читання з Archive у Cloud Storage коштує $0.05 за тисячу запитів проти $0.0004 у Standard. - Вилучення за гігабайт, прочитаний із класу.
- Дострокове видалення. Якщо видалити, перезаписати або перемістити об’єкт раніше за мінімальний строк, платите за решту строку так, ніби він лежав до кінця.
Два приклади показують, як це б’є по гаманцю.
Короткоживучі дані в холодному класі. 100 ГБ переклали в S3 Glacier Instant Retrieval і видалили через 10 днів. Ви заплатите за мінімальні 90 днів: 100 × $0.004 × 3 місяці = $1.20. У S3 Standard за ті самі 10 днів було б 100 × $0.023 × 10/30 ≈ $0.77.
Дрібні об’єкти. У Standard-IA і Glacier Instant Retrieval мінімальний розмір, за який виставляють рахунок, становить 128 КБ. Мільйон об’єктів по 10 КБ в IA оплачується як 128 000 000 КБ, тобто близько 122 ГіБ, а це близько $1.53 за місяць. У Standard ті самі 9.5 ГіБ коштують близько $0.22. Для дрібних об’єктів холодніший клас дорожчий.
Тому S3 за замовчуванням і не переносить у нові класи об’єкти менші за 128 КБ: кожен перехід є платним запитом ($0.02 за тисячу переходів у Glacier Instant Retrieval), і для дрібних об’єктів він коштує більше, ніж економія. Перенесення 10 мільйонів об’єктів у цей клас коштувало б $200 лише за запити.
Правила, які переносять і видаляють об’єкти самі, називаються життєвим циклом (lifecycle). Кожен провайдер має власні особливості:
- AWS. Класи утворюють «водоспад»: з Standard можна у все, а назад правилом не повернеш. Glacier Deep Archive є пасткою в один бік: з нього можна лише розморозити копію запитом на відновлення. Плата за перехід нараховується від дати, коли виконалася умова правила, а не від фізичного переміщення.
- Azure. Політика керування життєвим циклом (lifecycle management policy) не вміє розморожувати з Archive. Archive не підтримується для ZRS і GZRS акаунтів, тож вибір резервування в одному місці забороняє архів в іншому. Якщо ввімкнено soft delete, блоб вважається видаленим лише після закінчення строку утримання, тож штраф за дострокове видалення в цей період не діє.
- GCP. Штраф за дострокове видалення не нараховується, якщо клас змінив сам життєвий цикл, і не нараховується в бакетах із Autoclass. Тож правила життєвого циклу тут безпечніші, ніж ручна зміна класу.
Коли патерн доступу невідомий, є автоматичні варіанти: S3 Intelligent-Tiering (без плати за вилучення, але з платою за моніторинг кожного об’єкта, а об’єкти менші за 128 КБ не моніторяться), Autoclass у Cloud Storage і smart tier в Azure Blob.
Версіонування
Section titled “Версіонування”Версіонування (versioning) зберігає кожну версію об’єкта. Коли ви
перезаписуєте ключ, нова версія стає поточною, а стара лишається з власним
ідентифікатором. Коли ви видаляєте ключ, сховище не стирає нічого, а додає
маркер видалення (delete marker). Запит GET без версії тепер повертає
«не знайдено», але кожну стару версію можна повернути.
Що це коштує. Кожна версія тримається за повну ціну зберігання. Бакет, у який щодня перезаписують файл 1 ГБ, за рік накопичить 365 ГБ версій. Тож версіонування завжди йде в парі з правилом, яке видаляє неактуальні (noncurrent) версії через певний строк.
У трьох провайдерів відповідні механізми не збігаються:
- S3 вмикає версіонування на бакеті й окремо має Object Lock для незмінності. Версіонування можна лише призупинити, але не вимкнути.
- Azure Blob Storage має три окремі перемикачі з окремими строками: версіонування, soft delete блобів і soft delete контейнерів.
- Cloud Storage має версіонування і soft delete, який увімкнено в усіх бакетах за замовчуванням із утриманням на 7 діб. Тож захист від випадкового видалення тут є вже без вашої участі.
У бакетах з важливими даними захист від видалення вмикають одразу під час створення, а не після першого інциденту.
Доступ: публічні бакети та тимчасові посилання
Section titled “Доступ: публічні бакети та тимчасові посилання”Усі три сховища за замовчуванням приватні. Публічність нового об’єкта є
результатом того, що хтось її свідомо ввімкнув. Захисти теж посилилися:
із квітня 2023 року S3 для нових бакетів автоматично вмикає Block Public
Access і вимикає ACL. Azure-акаунт не дозволяє публічних контейнерів, якщо
не ввімкнути allow_nested_items_to_be_public. У Cloud Storage є
public_access_prevention, який забороняє публічний доступ на рівні бакета.
Публічний доступ усе одно з’являється і призводить до витоків. Типові шляхи такі:
- політика бакета з
"Principal": "*", додана «на хвилинку», щоб застосунок запрацював; - контейнер із рівнем доступу
blobабоcontainer; - прив’язка ролі для
allUsersчиallAuthenticatedUsersу Cloud Storage (у другому випадку «автентифікований» означає будь-кого з обліковим записом Google); - вимкнений Block Public Access на рівні акаунта «для одного проєкту»;
- посилання, у яке вбудовано право доступу, потрапило туди, де його прочитають сторонні.
Останній шлях стосується тимчасових посилань. Presigned URL в AWS, SAS (shared access signature) в Azure і signed URL у Google Cloud діють однаково: сервіс, у якого є доступ до об’єкта, підписує посилання своїми обліковими даними, а клієнт без облікових даних скачує чи завантажує об’єкт напряму, не проходячи через ваш сервер.
Це зручно для завантаження великих файлів, бо трафік не йде через ваш застосунок. Але тимчасове посилання є bearer-токеном: усі, хто його має, діють від імені того, хто підписав, у межах наданих прав і строку. Дізнатися, хто ним користується, майже неможливо.
Що варто знати про кожного провайдера:
| AWS | Azure | GCP | |
|---|---|---|---|
| Назва | presigned URL | SAS: user delegation, service, account | signed URL |
| Хто підписує | ключ IAM-користувача або тимчасові облікові дані ролі | ключ делегування Entra ID (user delegation SAS) або ключ облікового запису (service, account SAS) | акаунт служби або HMAC-ключ |
| Максимальний строк | 7 діб для ключа IAM-користувача; для ролі не довше за сесію ролі (для EC2 зазвичай близько 6 годин); у консолі від 1 хв до 12 год | задається під час створення; для SAS без збереженої політики радять короткі строки | 7 діб; у gcloud без файлу ключа --duration обмежено 12 годинами |
| Як відкликати | посилання перестає діяти, коли відкликано облікові дані, якими його підписано | збережена політика доступу (для service SAS) або ротація ключа облікового запису | відкликання ключа підписувача |
Ще три властивості з документації Azure, які треба знати. Microsoft рекомендує user delegation SAS, бо він захищений обліковими даними Entra, а не ключем облікового запису. Storage не відстежує видані SAS, тому їхню кількість з боку сервісу дізнатися неможливо. І створення SAS не аудитується: хто має право його підписати, той може зробити це непомітно для власника акаунта.
Виходить така схема: користувач автентифікується у вашому застосунку, ваш
бекенд перевіряє права й видає посилання на 5–15 хвилин на один об’єкт
з мінімальною дією (GET або PUT), а не на весь бакет.
Блочні диски: IOPS і пропускна здатність як оплачувані параметри
Section titled “Блочні диски: IOPS і пропускна здатність як оплачувані параметри”Блочний диск у хмарі не лежить у сервері. Він підключається по мережі, тому працює за законами з курсу ОС: IOPS, пропускна здатність (throughput) і глибина черги є окремими числами, і кожне має стелю.
Історично продуктивність диска зростала з його розміром: щоб отримати більше IOPS, треба було купити більший диск. EBS gp2 давав 3 IOPS на гібібайт, а маленькі томи мали «кредити на сплеск» до 3000 IOPS, які закінчувалися. Нове покоління розв’язало це так: ємність, IOPS і пропускна здатність оплачуються окремо. У AWS це gp3, в Azure Premium SSD v2, у Google Cloud Hyperdisk Balanced. У всіх трьох закладено базові 3000 IOPS (Azure: 3000 IOPS і 125 МБ/с, gp3: 3000 і 125 МіБ/с, Hyperdisk Balanced: 3000 і 140 МБ/с), а понад базу ви платите за кожну одиницю.
Що це змінює на практиці. Базі даних на 500 ГіБ потрібно 10 000 IOPS і 250 МБ/с:
- gp2: IOPS прив’язано до розміру, тож потрібен диск на 3334 ГіБ, і за $0.10 за гібібайт це близько $333 на місяць.
- gp3: 500 ГіБ × $0.08 + 7000 додаткових IOPS × $0.005 + 125 додаткових МіБ/с × $0.04 = $80 на місяць. Швидкість і розмір змінюються окремо і без зупинки диска.
Кілька правил, які випливають із цього:
- Замовляйте IOPS за виміром, а не «про запас». Кожен IOPS понад базу коштує щомісяця, навіть якщо ви ним не користуєтеся.
- Стеля є й у самої віртуальної машини. Кожен тип інстансу має власну межу пропускної здатності до дисків, і замовлені IOPS, які машина не може прийняти, ви оплачуєте марно (модуль 4).
- Диск прив’язаний до зони. EBS-том і Premium SSD v2 живуть в одній зоні доступності, тож втрата зони робить диск недоступним. Пережити втрату зони допомагають знімки, регіональні диски (у Google Cloud) чи реплікація рівнем вище, наприклад у базі даних (модуль 7).
- Знімки є вашою довговічністю. Знімок інкрементальний і зберігає лише змінені блоки. У EBS знімки лежать в S3 і коштують $0.05 за гібібайт на місяць.
- Локальні NVMe-диски інстансу тимчасові. Вони швидкі й дешеві, але зникають разом із машиною, тож для кешів і тимчасових файлів вони підходять, а для даних, які треба зберегти, ні.
Файлове сховище
Section titled “Файлове сховище”Amazon EFS, Azure Files і Google Cloud Filestore дають спільну файлову систему по NFS чи SMB для багатьох машин: спільні каталоги, вебконтент, домашні каталоги, застосунки, які очікують POSIX. Провайдер тримає масштабування, резервування між зонами й блокування.
Гігабайт тут коштує помітно дорожче, ніж в об’єктному сховищі, а кожна
операція з метаданими (stat, відкриття файлу) іде по мережі й повільніша, ніж
на локальному диску. Тому файлове сховище обирають, коли застосунок не
може працювати з об’єктами й потребує саме файлової семантики.
Як це в трьох хмарах
Section titled “Як це в трьох хмарах”| Функція | AWS | Azure | GCP |
|---|---|---|---|
| Об’єктне сховище | Amazon S3 | Azure Blob Storage | Cloud Storage |
| Контейнер об’єктів | бакет | контейнер у storage account | бакет |
| Блочне сховище | EBS (gp3, io2) | Managed Disks (Premium SSD v2) | Persistent Disk, Hyperdisk |
| Файлове сховище | EFS, FSx | Azure Files | Filestore |
| Строга консистентність | з 2020 року | завжди | завжди |
| Захист від видалення | versioning, Object Lock, MFA Delete | versioning, soft delete, immutable storage | versioning, soft delete (7 діб), retention policy |
| Тимчасове посилання | presigned URL | SAS | signed URL |
| Заборона публічного доступу | Block Public Access | allow_nested_items_to_be_public |
public_access_prevention |
| Зона чи регіон об’єкта | бакет у регіоні, класи з ≥3 зонами | резервування LRS, ZRS, GRS, GZRS на акаунті | тип розташування: регіон, dual-region, multi-region |
Чим відрізняється і що з цього випливає.
- В Azure налаштування живуть в акаунті, а не в контейнері. Резервування,
ключі доступу й мережеві правила storage account спільні для всіх його блобів,
файлів, черг і таблиць. Різні вимоги до резервування означають різні акаунти.
Ключі акаунта дають повний доступ, тому в продуктивних середовищах їх
вимикають (
shared_access_key_enabled = false) і працюють через Entra ID. - У Google Cloud розташування є властивістю бакета. Регіон, dual-region і multi-region обирають під час створення бакета, і резервування між регіонами вбудовано в цей вибір.
- У S3 «більше зон» є властивістю класу. Standard і Standard-IA живуть у щонайменше трьох зонах, а One Zone-IA в одній і не переживе втрату зони.
- Archive в Azure несумісний із ZRS. Архівувати можна лише в акаунтах LRS, GRS і RA-GRS, тож вибір між стійкістю до втрати зони й архівом ухвалюється в одному налаштуванні.
- Імена бакетів у S3 і Cloud Storage та імена storage account в Azure глобально унікальні, тож вигадана назва може бути вже зайнята.
Приватний бакет із захистом від видалення
Section titled “Приватний бакет із захистом від видалення”variable "bucket_name" { type = string}
resource "aws_s3_bucket" "data" { bucket = var.bucket_name}
resource "aws_s3_bucket_public_access_block" "data" { bucket = aws_s3_bucket.data.id block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true}
resource "aws_s3_bucket_versioning" "data" { bucket = aws_s3_bucket.data.id
versioning_configuration { status = "Enabled" }}variable "storage_account_name" { type = string}
resource "azurerm_resource_group" "data" { name = "rg-storage-demo" location = "eastus"}
resource "azurerm_storage_account" "data" { name = var.storage_account_name resource_group_name = azurerm_resource_group.data.name location = azurerm_resource_group.data.location account_tier = "Standard" account_replication_type = "ZRS" allow_nested_items_to_be_public = false shared_access_key_enabled = false
blob_properties { versioning_enabled = true
delete_retention_policy { days = 14 }
container_delete_retention_policy { days = 14 } }}
resource "azurerm_storage_container" "data" { name = "data" storage_account_id = azurerm_storage_account.data.id container_access_type = "private"}variable "bucket_name" { type = string}
resource "google_storage_bucket" "data" { name = var.bucket_name location = "US-CENTRAL1" uniform_bucket_level_access = true public_access_prevention = "enforced"
versioning { enabled = true }
soft_delete_policy { retention_duration_seconds = 1209600 }}Життєвий цикл: охолодження і видалення
Section titled “Життєвий цикл: охолодження і видалення”Правило однакове в трьох варіантах: через 30 діб перенести в клас для рідкісного доступу, через 120 діб у холодніший, через два роки видалити.
variable "bucket_name" { type = string}
resource "aws_s3_bucket" "logs" { bucket = var.bucket_name}
resource "aws_s3_bucket_lifecycle_configuration" "logs" { bucket = aws_s3_bucket.logs.id
rule { id = "cool-then-expire" status = "Enabled"
filter { prefix = "logs/" }
transition { days = 30 storage_class = "STANDARD_IA" }
transition { days = 120 storage_class = "GLACIER_IR" }
expiration { days = 730 }
noncurrent_version_expiration { noncurrent_days = 30 } }}variable "storage_account_name" { type = string}
resource "azurerm_resource_group" "logs" { name = "rg-logs-demo" location = "eastus"}
resource "azurerm_storage_account" "logs" { name = var.storage_account_name resource_group_name = azurerm_resource_group.logs.name location = azurerm_resource_group.logs.location account_tier = "Standard" account_replication_type = "LRS"}
resource "azurerm_storage_management_policy" "logs" { storage_account_id = azurerm_storage_account.logs.id
rule { name = "cool-then-expire" enabled = true
filters { prefix_match = ["logs/"] blob_types = ["blockBlob"] }
actions { base_blob { tier_to_cool_after_days_since_modification_greater_than = 30 tier_to_cold_after_days_since_modification_greater_than = 120 delete_after_days_since_modification_greater_than = 730 }
version { delete_after_days_since_creation = 30 } } }}variable "bucket_name" { type = string}
resource "google_storage_bucket" "logs" { name = var.bucket_name location = "US-CENTRAL1" uniform_bucket_level_access = true
lifecycle_rule { condition { age = 30 } action { type = "SetStorageClass" storage_class = "NEARLINE" } }
lifecycle_rule { condition { age = 120 } action { type = "SetStorageClass" storage_class = "COLDLINE" } }
lifecycle_rule { condition { age = 730 } action { type = "Delete" } }}У версії для AWS об’єкти менші за 128 КБ у клас IA не потраплять: це типова поведінка S3. Якщо в бакеті багато дрібних файлів, простіше зберігати їх у Standard, а перед архівуванням збирати в більші.
Тимчасове посилання на 15 хвилин
Section titled “Тимчасове посилання на 15 хвилин”aws s3 presign s3://my-bucket/reports/2026-09.pdf --expires-in 900end=$(date -u -d "15 minutes" '+%Y-%m-%dT%H:%MZ')az storage blob generate-sas \ --account-name mystorageacct --container-name reports --name 2026-09.pdf \ --permissions r --expiry "$end" --https-only \ --as-user --auth-mode login --full-urigcloud storage sign-url gs://my-bucket/reports/2026-09.pdf \ --duration=15m \ --impersonate-service-account=signer@my-project.iam.gserviceaccount.comКожна з трьох команд повертає URL із підписом у параметрах запиту. Його можна відкрити в браузері без облікових даних, і він перестане працювати через 15 хвилин. Варіант для Azure використовує user delegation SAS, тому для нього потрібна роль із правом на ключ делегування.
Диск із замовленою продуктивністю
Section titled “Диск із замовленою продуктивністю”500 ГіБ, 10 000 IOPS, 250 МБ/с:
resource "aws_ebs_volume" "db" { availability_zone = "us-east-1a" size = 500 type = "gp3" iops = 10000 throughput = 250 encrypted = true}resource "azurerm_resource_group" "disk" { name = "rg-disk-demo" location = "eastus"}
resource "azurerm_managed_disk" "db" { name = "db-data" location = azurerm_resource_group.disk.location resource_group_name = azurerm_resource_group.disk.name storage_account_type = "PremiumV2_LRS" create_option = "Empty" disk_size_gb = 500 disk_iops_read_write = 10000 disk_mbps_read_write = 250 zone = "1"}resource "google_compute_disk" "db" { name = "db-data" type = "hyperdisk-balanced" zone = "us-central1-a" size = 500 provisioned_iops = 10000 provisioned_throughput = 250}Скільки це коштує
Section titled “Скільки це коштує”Ціни станом на вересень 2026, з офіційних прайс-листів і сторінок цін; регіони us-east-1, eastus, us-central1, Linux, оплата за фактом.
Об’єкти: 1 ТБ (1000 ГБ) у стандартному класі за місяць, 1 млн записів і 10 млн читань.
| AWS S3 Standard | Azure Blob Hot, LRS | GCP Standard | |
|---|---|---|---|
| Зберігання 1000 ГБ | $23.00 | $20.80 | $20.00 |
| 1 млн записів | $5.00 | $5.00 | $5.00 |
| 10 млн читань | $4.00 | $4.00 | $4.00 |
| Разом | $32.00 | $29.80 | $29.00 |
Ціни запитів збіглися: $0.005 за тисячу записів і $0.004 за десять тисяч читань у AWS та Azure, $0.0004 за тисячу читань у GCP.
Вихідний трафік з сервісу в інтернет (модуль 5 розбирає його детально). AWS бере $0.09 за гігабайт за перші 10 ТБ на місяць, перші 100 ГБ на місяць безкоштовні. Azure бере $0.087 за гігабайт після безкоштовних 100 ГБ (маршрут через мережу Microsoft). Читання 1 ТБ на місяць обійдеться приблизно в $81 в AWS і $78 в Azure. Для GCP вартість залежить від рівня мережі і напрямку.
Що ще додається. Вилучення з холодних класів: читання 1 ТБ із S3 Glacier Instant Retrieval коштує $30 понад зберігання. Тимчасові посилання оплачуються як звичайні запити. Плата за вихідний трафік лягає на власника акаунта, навіть коли посилання відкрив сторонній користувач: Azure у своїй документації прямо попереджає, що завантаження 200 ГБ десять разів через SAS дасть 2 ТБ вихідного трафіку в рахунку власника.
Блочні диски: 500 ГіБ, 10 000 IOPS, 250 МБ/с на місяць.
| AWS gp3 | Azure Premium SSD v2 | GCP Hyperdisk Balanced | |
|---|---|---|---|
| Ємність | $0.08 за ГіБ | $0.0803 за ГіБ | $0.08 за ГіБ |
| IOPS понад базові 3000 | $0.005 за IOPS | $0.0051 за IOPS | $0.005 за IOPS |
| Пропускна здатність понад базову | $0.04 за МіБ/с (база 125) | $0.04 за МБ/с (база 125) | $0.04 за МБ/с (база 140) |
| Разом | $80.00 | $80.94 | $79.40 |
Розрахунок для gp3: ємність $40 + 7000 додаткових IOPS × $0.005 = $35 + 125 додаткових МіБ/с × $0.04 = $5. Ціни трьох провайдерів майже збіглися, бо всі три перейшли на одну модель оплати. gp2 за тієї ж потреби IOPS коштував би $333.
Про що забувають. Неприєднані диски й знімки лишаються в рахунку, версії
об’єктів без правила очищення ростуть без меж, а незавершені багаточастинні
завантаження в S3 оплачуються, поки їх не прибере правило
abort_incomplete_multipart_upload.
Розбір: SAS-токен, який відкрив 38 ТБ
Section titled “Розбір: SAS-токен, який відкрив 38 ТБ”Що сталося. Дослідники Microsoft AI опублікували в GitHub репозиторій
robust-models-transfer з відкритим кодом і моделями розпізнавання
зображень. У репозиторії був URL для завантаження моделей із Azure Blob Storage
з токеном SAS. Компанія Wiz Research виявила, що токен видано на весь
storage account з повним контролем (читання, запис, видалення), хоча
потрібне було лише читання окремих файлів. Строк дії токена стояв до 6 жовтня 2051 року.
Що було доступно. За даними Wiz, разом із моделями через токен було видно 38 ТБ приватних даних, зокрема резервні копії робочих станцій двох колишніх співробітників, у яких були секрети, приватні ключі й паролі, та понад 30 000 внутрішніх повідомлень Microsoft Teams від 359 співробітників. Microsoft у своєму повідомленні уточнила, що дані клієнтів не постраждали і що інші внутрішні сервіси не були під загрозою.
Хронологія.
| Дата | Подія |
|---|---|
| 20 липня 2020 | Токен уперше потрапив у GitHub, тоді його строк був до 5 жовтня 2021 |
| 6 жовтня 2021 | Строк продовжили до 6 жовтня 2051 |
| 22 червня 2023 | Wiz повідомила Microsoft Security Response Center |
| 24 червня 2023 | Microsoft відкликала токен і закрила зовнішній доступ |
Механізм. Три налаштування, які легко ввімкнути, склалися в проблему:
- Обсяг. Токен видано на весь акаунт, хоча потрібен був один контейнер для читання.
- Права. Повний контроль замість читання. Це давало змогу не лише зчитати, а й перезаписати файли, зокрема моделі, які інші люди завантажують і запускають.
- Строк. 30 років замість годин. Посилання, яке живе довше за проєкт, фактично є постійним ключем.
За повідомленням MSRC, сканування секретів у GitHub помітило цей URL, але результат помилково позначили хибним спрацюванням. Після інциденту Microsoft розширила виявлення SAS-токенів із надмірними правами.
Що з цього випливає. SAS не можна відстежити: сервіс не веде обліку виданих токенів, а їх створення не аудитується. Тому єдина система захисту складається з правил, які застосовуються до створення:
- видавати user delegation SAS, а не підписаний ключем облікового запису;
- обмежувати обсяг одним блобом чи контейнером, права мінімальні, строк у хвилинах чи годинах;
- вимкнути доступ за ключем облікового запису, щоб токени, які він підписує, не могли існувати;
- для публічних даних використовувати окремий акаунт без приватних даних.
Так само в AWS і Google Cloud: presigned URL і signed URL підписуються обліковими даними сервісу, тож надмірні права ролі, що підписує, стають надмірними правами в кожному посиланні.
Класичний публічний бакет. У 2017 році дослідник UpGuard знайшов відкритий для скачування бакет S3 із записами клієнтів Verizon, який налаштував підрядник NICE Systems. UpGuard оцінила витік у 14 мільйонів записів, Verizon у 6 мільйонів акаунтів. Виявлено 8 червня, Verizon повідомили 13 червня, доступ закрили 22 червня.
Типові помилки розуміння
Section titled “Типові помилки розуміння”- «11 дев’яток означає, що дані не зникнуть». Це проєктний показник проти апаратних збоїв. Видалення, перезапис і скомпрометовані облікові дані він не покриває.
- «Реплікація в інший регіон є бекапом». Вона повторює й помилкове видалення. Бекап має бути окремою копією, недосяжною для тих облікових даних, які можуть зіпсувати основну.
- «S3 має кінцеву консистентність». Це було правдою до грудня 2020 року. Старі статті й обхідні шляхи на кшталт S3Guard тепер не потрібні.
- «Холодний клас завжди дешевший». Він дешевший лише для даних, які лежать довго, читаються рідко і не є дрібними. Для короткоживучих і дрібних об’єктів він дорожчий.
- «Тимчасове посилання безпечне, бо тимчасове». Воно діє для всіх, хто його має, і 7 діб чи 30 років є суто налаштуванням.
- «Диск у хмарі швидкий, бо це SSD». Швидкість диска є параметром, який ви замовляєте й оплачуєте, і його обмежує ще й тип віртуальної машини.
- «У бакеті немає папок, отже це не важливо». Це важливо для ціни: перейменування каталогу означає копіювання й видалення кожного об’єкта.
Перевір себе
Джерела
Section titled “Джерела”- Amazon S3 data consistency model і оголошення строгої консистентності, 1 грудня 2020
- Storage classes, S3 User Guide і Lifecycle transitions: обмеження та плата
- Presigned URLs, S3 User Guide
- S3 Block Public Access за замовчуванням з квітня 2023
- Conditional writes в S3
- EBS General Purpose SSD volumes
- Ціни AWS: S3, EBS, офіційний прайс-лист у форматі JSON:
pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonS3/current/us-east-1/index.json - Azure Storage redundancy
- Access tiers for blob data
- Shared access signatures overview
- Manage concurrency in Blob Storage
- Ціни Azure: Retail Prices API, Blob Storage
- Cloud Storage: introduction, signed URLs, ціни і ціни дисків
- Wiz Research, 38TB of data accidentally exposed by Microsoft AI researchers, і Microsoft Security Response Center, Microsoft mitigated exposure of internal information in a storage account due to overly-permissive SAS token, вересень 2023
- The Register, 14M Verizon customers’ details out, липень 2017
- Курс ОС: диски і блочний рівень і файлові системи