Blob Storage: файлы и объекты
Как хранить в облаке файлы, бэкапы, логи и картинки — без единого сервера и за копейки.
Azure Blob Storage — объектное хранилище: вы кладёте в него файлы (их называют «блобами»), а Azure выдаёт на каждый HTTPS-адрес. Ни дисков, ни файловой системы, ни машины, которую надо патчить.
Зачем нужно отдельное хранилище
Первое, что делает новичок в облаке: поднимает виртуальную машину, подключает к ней диск и складывает пользовательские файлы туда. Через полгода выясняется неприятное. Диск на терабайт стоит в разы дороже, чем терабайт в Blob Storage. Бэкапить его надо самому. Упала машина — файлы недоступны, хотя с ними всё в порядке. А раздать видео миллиону зрителей эта машина всё равно не сможет: она захлебнётся сетью раньше, чем процессором.
Blob Storage закрывает ровно эту боль. Он:
- масштабируется до петабайт — вы не «выбираете размер», вы просто пишете;
- хранит минимум три копии каждого байта и сам молча чинит битые;
- отдаёт файлы напрямую по HTTPS — ваше приложение в раздаче вообще не участвует;
- стоит от долей цента за гигабайт в месяц.
Типичные жильцы: аватарки и вложения пользователей, бэкапы баз, логи, видео, датасеты для машинного обучения, артефакты сборок, статические сайты. Правило простое: если файл не нужно менять посередине — ему место в блобе.
Иерархия: аккаунт → контейнер → блоб
В Azure всё живёт внутри подписки и группы ресурсов, а дальше начинается собственная иерархия хранилища.
| Уровень | Что это |
| Storage account (аккаунт хранилища) | Точка входа и единица тарификации. Задаёт регион, тип репликации, уровень доступа по умолчанию. Его имя становится частью адреса. |
| Container (контейнер) | Плоская «папка верхнего уровня»: avatars, backups, logs. Уровень публичности настраивается именно тут. |
| Blob (блоб) | Сам файл. Имя может содержать слэши — но это часть имени, а не настоящая вложенность. |
Адрес любого файла складывается предсказуемо:
https://<account>.blob.core.windows.net/<container>/<blob>
https://ccdemostore7.blob.core.windows.net/avatars/users/42/photo.png
Раз имя аккаунта попадает в публичное доменное имя, оно уникально на весь Azure: 3–24 символа, только строчные латинские буквы и цифры. myapp-storage не пройдёт (дефис запрещён), ccdemostore7 — пройдёт, если никто не занял.
Три типа блобов
| Block blob | Обычные файлы: картинки, архивы, видео. Собирается из блоков, поэтому большой файл заливается параллельно и докачивается после обрыва. Ваш выбор в 95% случаев. |
| Append blob | Только дозапись в конец. Логи и аудит: несколько процессов пишут одновременно, ничего не затирая. |
| Page blob | Произвольный доступ страницами по 512 байт. Под ним живут диски виртуальных машин. Руками почти никогда не создают. |
Репликация: сколько копий и где они лежат
| LRS | 3 копии в одном дата-центре. Дешевле всего. Сгорел ЦОД — данных нет. |
| ZRS | 3 копии в трёх зонах доступности одного региона. Переживает падение целого ЦОД. |
| GRS | LRS + асинхронная копия во втором регионе за сотни километров. Читать вторую копию нельзя — только после аварийного переключения. |
| RA-GRS | То же, но вторую копию можно читать всегда. Удобно для географически разнесённого чтения. |
Для логов и временных артефактов честно хватает LRS — не платите за георепликацию мусора. Для бэкапов, которые вы обязаны предъявить после катастрофы, берите GRS.
Уровни доступа: Hot, Cool, Cold, Archive
Главная экономическая идея объектного хранилища звучит так: чем реже вы читаете данные, тем дешевле их хранить — но тем дороже каждое обращение. Azure даёт четыре уровня (tier) и разрешает переключать их у отдельного блоба.
| Уровень | Хранение | Чтение | Минимальный срок | Когда доступен файл |
| Hot | дорого | почти бесплатно | нет | мгновенно |
| Cool | примерно вдвое дешевле | платно за гигабайт | 30 дней | мгновенно |
| Cold | ещё в два раза дешевле | дороже, чем Cool | 90 дней | мгновенно |
| Archive | копейки | дорого + регидратация | 180 дней | офлайн: часы ожидания |
Обратите внимание на две колонки, из-за которых чаще всего попадают на деньги. Минимальный срок — если удалить или перевести блоб раньше, вам всё равно выставят счёт за оставшиеся дни (early deletion fee). А Archive офлайн в буквальном смысле: чтобы прочитать файл, его надо «регидратировать» — перевести в Hot или Cool и подождать от часа (High priority) до 15 часов (Standard).
Посчитаем экономику на пальцах. Цифры ниже — порядок величин для LRS в европейском регионе; точные ставки смотрите в калькуляторе Azure, но соотношение между уровнями меняется редко. Сценарий: храним 1 ТБ архива, из которого за месяц реально скачиваем 50 ГБ.
GB = 1024 # 1 ТБ в гигабайтах
read_gb = 50 # столько гигабайт реально читаем за месяц
storage_price = {"Hot": 0.0184, "Cool": 0.0100, "Cold": 0.0045, "Archive": 0.00099}
read_price = {"Hot": 0.0, "Cool": 0.01, "Cold": 0.03, "Archive": 0.02}
for tier, price in storage_price.items():
storage = GB * price
access = read_gb * read_price[tier]
total = storage + access
print(f"{tier:8} хранение ${storage:7.2f} + доступ ${access:6.2f} = ${total:7.2f} в месяц")
Результат:
Hot хранение $ 18.84 + доступ $ 0.00 = $ 18.84 в месяц
Cool хранение $ 10.24 + доступ $ 0.50 = $ 10.74 в месяц
Cold хранение $ 4.61 + доступ $ 1.50 = $ 6.11 в месяц
Archive хранение $ 1.01 + доступ $ 1.00 = $ 2.01 в месяц
Разница между Hot и Archive — почти десятикратная. Но поменяйте условие: скачивать не 50 ГБ, а 800 ГБ в месяц — и Archive мгновенно станет самым дорогим вариантом, да ещё и с многочасовой задержкой. Поэтому уровень выбирают не «по красоте названия», а по частоте чтения.
Практика: поднимаем хранилище из CLI
Три команды — и у вас есть боевое хранилище.
az group create \
--name rg-storage-demo \
--location westeurope
az storage account create \
--name ccdemostore7 \
--resource-group rg-storage-demo \
--location westeurope \
--sku Standard_LRS \
--kind StorageV2 \
--access-tier Hot \
--allow-blob-public-access false
az storage container create \
--name avatars \
--account-name ccdemostore7 \
--auth-mode login
Разберём флаги, которые реально важны:
--kind StorageV2— современный универсальный аккаунт. Всегда он; V1 остался для совместимости.--sku Standard_LRS— тип репликации, тот самый выбор из таблицы выше. Есть иPremium_LRS(SSD, низкая задержка, дорого).--allow-blob-public-access false— запрет анонимного доступа на уровне всего аккаунта. Ставьте его сразу: это страховка от того, что кто-то из коллег случайно откроет контейнер наружу.--auth-mode login— работать от имени вашей учётной записи Azure AD (Entra ID), а не по ключу аккаунта. Ключ — это пароль ко всему хранилищу целиком, и он неизбежно утекает в git.
Загрузка и просмотр файлов
# один файл
az storage blob upload \
--account-name ccdemostore7 \
--container-name avatars \
--name users/42/photo.png \
--file ./photo.png \
--auth-mode login
# целая папка одной командой
az storage blob upload-batch \
--account-name ccdemostore7 \
--destination avatars \
--source ./local-avatars \
--auth-mode login
# что там лежит
az storage blob list \
--account-name ccdemostore7 \
--container-name avatars \
--auth-mode login \
--output table
# скачать обратно
az storage blob download \
--account-name ccdemostore7 \
--container-name avatars \
--name users/42/photo.png \
--file ./restored.png \
--auth-mode login
Для больших объёмов вместо az storage берут утилиту azcopy — она жмёт из машины все доступные мегабиты и умеет синхронизировать директории.
Статический сайт прямо из блоба
Blob Storage умеет притворяться веб-сервером. Ни VM, ни App Service, ни nginx — просто включаете флаг, и Azure заводит служебный контейнер $web, содержимое которого отдаётся по HTTP.
az storage blob service-properties update \
--account-name ccdemostore7 \
--static-website true \
--index-document index.html \
--404-document 404.html \
--auth-mode login
az storage blob upload-batch \
--account-name ccdemostore7 \
--destination '$web' \
--source ./dist \
--auth-mode login
# узнать адрес сайта
az storage account show \
--name ccdemostore7 \
--resource-group rg-storage-demo \
--query "primaryEndpoints.web" \
--output tsv
Результат:
https://ccdemostore7.z6.web.core.windows.net/
Собранный фронтенд на React или Vue выкладывается сюда за секунды и стоит центы. Одно «но»: свой домен и HTTPS-сертификат Blob Storage сам не выдаст — сверху ставят Azure CDN или Front Door. Заодно получаете кеш на краю сети и защиту от всплесков трафика.
Правила жизненного цикла: экономия на автопилоте
Руками перекладывать миллионы блобов между уровнями невозможно. Для этого есть политика жизненного цикла — JSON, который Azure применяет раз в сутки.
{
"rules": [
{
"name": "logs-tiering",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["logs/"]
},
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToArchive": { "daysAfterModificationGreaterThan": 90 },
"delete": { "daysAfterModificationGreaterThan": 365 }
}
}
}
}
]
}
Читается как фраза: «логи месяц лежат горячими, потом три месяца охлаждаются, потом уезжают в архив, а через год удаляются». Одна такая политика на проекте с активным логированием экономит больше, чем месяц оптимизации кода.
Как это работает
Плоское пространство имён. Внутри контейнера нет папок. users/42/photo.png — это целиком имя блоба, где слэши ничем не отличаются от букв. Портал Azure рисует «дерево», просто группируя блобы по общему префиксу. Отсюда следствие: «переименовать папку» нельзя — можно только скопировать каждый блоб под новым именем и удалить старые. Если вам нужна настоящая файловая иерархия с атомарным переименованием (это важно для Spark и аналитики), включают опцию hierarchical namespace — так рождается Azure Data Lake Storage Gen2.
Каждая операция — HTTP-запрос. Загрузка — это PUT, чтение — GET. У каждого блоба есть ETag, и вы можете отправить заголовок If-Match: «перезапиши, только если версия та же». Так делается оптимистическая блокировка без всякой базы данных.
Доступ без ключей. Раздавать ключ аккаунта клиентам нельзя. Вместо этого выдают SAS-токен (Shared Access Signature) — подписанную ссылку с ограничением по времени и правам:
https://ccdemostore7.blob.core.windows.net/avatars/users/42/photo.png
?sv=2023-11-03&se=2026-07-14T18%3A00%3A00Z&sp=r&sig=Xf9%2B...
Здесь sp=r — только чтение, se — момент истечения. Браузер пользователя скачивает файл напрямую из хранилища, ваш сервер не тратит на это ни байта трафика.
Из чего складывается счёт. Три слагаемых: хранение (гигабайты × дни), транзакции (каждая операция чтения/записи — доли цента за 10 000 операций) и исходящий трафик из региона наружу. Входящий трафик бесплатен всегда.
Частые ошибки
- Публичный контейнер «на пять минут». Anonymous read у контейнера с пользовательскими данными — классическая утечка, которую находят сканеры интернета за часы. Держите
--allow-blob-public-access falseи раздавайте SAS-ссылки. - Archive для файлов, которые читают. Кто-то увидел цену в 20 раз ниже и перевёл туда всё подряд. Дальше приложение падает с ошибкой «This operation is not permitted on an archived blob», а восстановление терабайта занимает полдня и стоит дороже, чем год хранения в Hot.
- Плата за досрочное удаление. Залили в Cool, через неделю передумали и стёрли — счёт придёт как за 30 дней. В Archive — как за 180. Прежде чем массово менять уровень, посмотрите на минимальный срок.
- Миллионы крошечных блобов. Хранение мегабайта логов почти ничего не стоит, а вот 50 миллионов операций записи — уже заметная строка в счёте. Пакуйте мелочь в архивы, пишите логи батчами.
- Ключ аккаунта в репозитории. Ключ даёт полный доступ ко всему хранилищу и не имеет срока жизни. Используйте Managed Identity для сервисов и
--auth-mode loginдля людей. - Нет lifecycle-политики. Самая тихая утечка бюджета: терабайты логов трёхлетней давности в Hot, за которые вы платите каждый месяц.
Итоги
- Blob Storage — объектное хранилище: аккаунт → контейнер → блоб, у каждого файла свой HTTPS-адрес.
- Имя аккаунта уникально на весь Azure: 3–24 строчных латинских символа и цифры.
- Block blob — для файлов, append — для логов, page — для дисков VM.
- Hot / Cool / Cold / Archive: чем дешевле хранение, тем дороже чтение и длиннее минимальный срок. Archive — офлайн, регидратация занимает часы.
- Политика жизненного цикла автоматически охлаждает и удаляет старые данные — это самая простая крупная экономия.
- Публичный доступ выключайте на уровне аккаунта, а клиентам выдавайте SAS-ссылки с ограниченным сроком.
- Статический сайт поднимается из контейнера
$webодной командой; домен и HTTPS добавляет CDN или Front Door.