Chapter 4: Storage
Azure Storage is the foundation for persisting data in the cloud. It is durable (99.999999999%, eleven nines), highly available, and massively scalable.
Storage Account
Almost all Azure storage services live inside a Storage Account. It is the top-level namespace and billing unit.
# Create a general-purpose v2 storage account (recommended default)
az storage account create \
--name mystorageacct \
--resource-group myapp-rg \
--location eastus \
--sku Standard_LRS \
--kind StorageV2 \
--access-tier Hot
Redundancy Options
| SKU | Full Name | Copies | Protection |
|---|---|---|---|
LRS | Locally Redundant Storage | 3 in 1 data centre | Hardware failure |
ZRS | Zone-Redundant Storage | 3 across 3 AZs | Data centre failure |
GRS | Geo-Redundant Storage | 6 (3 primary + 3 secondary region) | Regional outage (read from secondary on failover) |
GZRS | Geo-Zone-Redundant Storage | 6 (3 across AZs + 3 secondary region) | AZ + regional outage |
RA-GRS | Read-Access GRS | Same as GRS | Secondary always readable |
RA-GZRS | Read-Access GZRS | Same as GZRS | Secondary always readable |
General guidance:
- Dev/test →
LRS(cheapest) - Production web apps →
ZRS - Business-critical data →
GRSorGZRS - Need read replica in another region →
RA-GRSorRA-GZRS
Access Tiers (Blob Storage)
| Tier | Access cost | Storage cost | Use Case |
|---|---|---|---|
| Hot | Low | Higher | Frequently accessed data |
| Cool | Medium | Lower | Infrequently accessed, stored 30+ days |
| Cold | Higher | Lower | Rarely accessed, stored 90+ days |
| Archive | Highest (rehydration needed) | Lowest | Long-term backup, stored 180+ days |
Blob Storage
Blob (Binary Large OBject) Storage is Azure's object store, the equivalent of AWS S3. Store any unstructured data: images, videos, backups, logs, static website files, and more.
Concepts
Storage Account (mystorageacct)
└── Container (images) ← like a bucket or folder
├── photo1.jpg ← Block Blob (most common)
├── video.mp4 ← Block Blob (large file, streamed)
└── logfile.txt ← Block Blob
- Block Blob: Standard blob for files. Max size 190.7 TiB.
- Append Blob: Optimised for append operations (logging).
- Page Blob: Random read/write access; used for VM disks.
Working with Blobs
# Get connection string (or use --account-key / --sas-token / --auth-mode login)
export STORAGE_CONN=$(az storage account show-connection-string \
--name mystorageacct \
--resource-group myapp-rg \
--query connectionString \
--output tsv)
# Create a container
az storage container create \
--name images \
--connection-string $STORAGE_CONN \
--public-access blob # blob = individual blobs public; container = list + blobs; off = private
# Upload a file
az storage blob upload \
--container-name images \
--name photo1.jpg \
--file ./photo1.jpg \
--connection-string $STORAGE_CONN
# Upload a whole directory
az storage blob upload-batch \
--source ./assets \
--destination images \
--connection-string $STORAGE_CONN
# List blobs in a container
az storage blob list \
--container-name images \
--connection-string $STORAGE_CONN \
--output table
# Download a blob
az storage blob download \
--container-name images \
--name photo1.jpg \
--file ./downloaded.jpg \
--connection-string $STORAGE_CONN
# Generate a SAS token (time-limited, permission-scoped URL)
az storage blob generate-sas \
--container-name images \
--name photo1.jpg \
--permissions r \
--expiry 2025-12-31 \
--connection-string $STORAGE_CONN \
--output tsv
# Delete a blob
az storage blob delete \
--container-name images \
--name photo1.jpg \
--connection-string $STORAGE_CONN
Static Website Hosting
Serve a single-page application (SPA) or static site directly from Blob Storage:
# Enable static website hosting
az storage blob service-properties update \
--account-name mystorageacct \
--static-website \
--index-document index.html \
--404-document 404.html
# Upload your site
az storage blob upload-batch \
--source ./dist \
--destination '$web' \
--connection-string $STORAGE_CONN
# Get the website URL
az storage account show \
--name mystorageacct \
--resource-group myapp-rg \
--query "primaryEndpoints.web" \
--output tsv
Lifecycle Management
Automatically tier or delete blobs after a set number of days:
{
"rules": [
{
"name": "MoveToArchive",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": { "blobTypes": ["blockBlob"], "prefixMatch": ["backups/"] },
"actions": {
"baseBlob": {
"tierToCool": { "daysAfterModificationGreaterThan": 30 },
"tierToArchive": { "daysAfterModificationGreaterThan": 90 },
"delete": { "daysAfterModificationGreaterThan": 365 }
}
}
}
}
]
}
az storage account management-policy create \
--account-name mystorageacct \
--resource-group myapp-rg \
--policy @lifecycle-policy.json
Azure Files
Azure Files is a managed cloud file share using the SMB (Server Message Block) or NFS protocol. Mount it on Windows, Linux, or macOS, just like a network drive.
Use cases: Lift-and-shift of on-premises file servers, shared config/logs for VMs, persistent storage for containers.
# Create a file share (quota in GB)
az storage share create \
--name myfileshare \
--quota 100 \
--connection-string $STORAGE_CONN
# Mount on Linux
# Get the mount command from the portal, or build it:
sudo mkdir /mnt/myfileshare
sudo mount -t cifs //mystorageacct.file.core.windows.net/myfileshare /mnt/myfileshare \
-o vers=3.0,username=mystorageacct,password=<storage-key>,dir_mode=0777,file_mode=0777,serverino
# Mount on Windows (PowerShell)
$connectTestResult = Test-NetConnection -ComputerName mystorageacct.file.core.windows.net -Port 445
net use Z: \\mystorageacct.file.core.windows.net\myfileshare /user:Azure\mystorageacct <storage-key>
# Upload a file to a share
az storage file upload \
--share-name myfileshare \
--source ./config.env \
--path config/config.env \
--connection-string $STORAGE_CONN
Azure File Sync
Azure File Sync caches cloud file shares on Windows Server machines on-premises. Users access files locally at LAN speeds; Azure holds the full dataset.
Queue Storage
Azure Queue Storage is a simple, durable message queue for asynchronous communication between application components. Max message size is 64 KB; queue can hold unlimited messages.
# Create a queue
az storage queue create \
--name myqueue \
--connection-string $STORAGE_CONN
# Send a message
az storage message put \
--queue-name myqueue \
--content '{"orderId": "12345", "action": "process"}' \
--connection-string $STORAGE_CONN
# Receive messages (makes them invisible for 30s by default)
az storage message get \
--queue-name myqueue \
--connection-string $STORAGE_CONN
# Delete a message after processing
az storage message delete \
--queue-name myqueue \
--id <message-id> \
--pop-receipt <pop-receipt> \
--connection-string $STORAGE_CONN
# Peek (read without locking)
az storage message peek \
--queue-name myqueue \
--connection-string $STORAGE_CONN
For complex messaging needs (guaranteed ordering, topics/subscriptions, dead-lettering) use Azure Service Bus instead.
Table Storage
Azure Table Storage is a NoSQL key-value store. Each row has a PartitionKey and RowKey (together form the primary key), plus up to 252 custom properties.
When to use: Simple, high-volume structured data that doesn't need relational queries. Very cheap.
# Create a table
az storage table create \
--name events \
--connection-string $STORAGE_CONN
# Insert an entity
az storage entity insert \
--table-name events \
--entity PartitionKey=2024 RowKey=evt001 EventName="UserSignup" UserId="u123" \
--connection-string $STORAGE_CONN
# Query entities
az storage entity query \
--table-name events \
--filter "PartitionKey eq '2024'" \
--connection-string $STORAGE_CONN
For richer querying and indexing, prefer Azure Cosmos DB Table API or Azure SQL.
Shared Access Signatures (SAS)
A SAS token grants time-limited, permission-scoped access to a storage resource without sharing your account keys.
# Account SAS: access to all services
az storage account generate-sas \
--account-name mystorageacct \
--services blob \
--resource-types container,object \
--permissions rwld \
--expiry 2025-12-31T00:00:00Z \
--output tsv
# Service SAS: access to a specific container
az storage container generate-sas \
--name images \
--permissions rl \
--expiry 2025-06-30 \
--connection-string $STORAGE_CONN \
--output tsv
SAS vs Managed Identity vs Connection String
| Method | Use When |
|---|---|
| Connection string | Dev/test only (contains account key) |
| Account key | Avoid in production (full access) |
| SAS token | Share limited access with third parties |
| Managed Identity | Applications running in Azure (no secrets needed, preferred) |
Azure Managed Disks
Managed Disks are block storage volumes attached to Azure VMs (not directly accessible via the storage APIs).
# Create a standalone managed disk
az disk create \
--resource-group myapp-rg \
--name myDataDisk \
--size-gb 256 \
--sku Premium_SSD
# Attach to a VM
az vm disk attach \
--resource-group myapp-rg \
--vm-name mywebvm \
--name myDataDisk
Storage Summary
| Service | Type | Protocol | Best For |
|---|---|---|---|
| Blob Storage | Object | HTTP/REST | Files, images, backups, static sites |
| Azure Files | File share | SMB / NFS | Lift-and-shift file servers |
| Queue Storage | Message queue | HTTP/REST | Simple async decoupling |
| Table Storage | Key-value NoSQL | HTTP/REST | Simple structured data |
| Managed Disks | Block | OS-level | VM operating system and data volumes |
Next Steps
Continue to 05-networking.md to learn about Virtual Networks, security, and connectivity.