AKS Storage

AKS supports multiple storage options for persistent data: Azure Disk for block storage and Azure Files for shared file storage. Understanding when to use each storage type and how to configure them is essential for running stateful applications on AKS.

Storage Overview

Kubernetes abstracts storage through PersistentVolumes (PVs) and PersistentVolumeClaims (PVCs). On AKS, these map to Azure storage services:

graph TB APP[Application Pod] --> PVC[PersistentVolumeClaim] PVC --> PV[PersistentVolume] PV --> STORAGE[Azure Storage] STORAGE --> DISK[Azure Disk<br/>Block Storage] STORAGE --> FILES[Azure Files<br/>Shared File Storage] style APP fill:#e1f5ff style PVC fill:#fff4e1 style PV fill:#e8f5e9 style DISK fill:#f3e5f5

Azure Disk CSI Driver

The Azure Disk Container Storage Interface (CSI) driver provides block storage using Azure managed disks. Azure Disks are network-attached block storage devices that persist independently of VM lifecycles.

Architecture

graph TB POD[Pod] --> PVC[PVC: 20Gi] PVC --> SC[StorageClass: managed-premium] SC --> CSI[Azure Disk CSI Driver] CSI --> DISK[Azure Disk<br/>Premium SSD, 20Gi] DISK --> NODE[Worker Node] POD -->|Mount| NODE style POD fill:#e1f5ff style DISK fill:#fff4e1 style CSI fill:#e8f5e9

Storage Classes

Define storage classes for different Azure Disk types:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-premium
provisioner: disk.csi.azure.com
parameters:
  skuname: Premium_LRS
  cachingMode: ReadWrite
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Delete

Azure Disk Types:

TypeUse CaseIOPSThroughputCost
Standard HDDDevelopment/Testing50060 MB/sLow
Standard SSDGeneral purpose2,000150 MB/sMedium
Premium SSDProduction workloads7,500250 MB/sHigh
Ultra DiskHigh-performance160,0002,000 MB/sVery High

Creating Persistent Volumes

Dynamic Provisioning (Recommended):

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: managed-premium
  resources:
    requests:
      storage: 100Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: secretpassword
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: mysql-pvc

Access Modes:

  • ReadWriteOnce - Single node read/write (Azure Disk default)
  • ReadOnlyMany - Multiple nodes read-only (not supported by Azure Disk)
  • ReadWriteMany - Multiple nodes read/write (not supported by Azure Disk, use Azure Files)

Volume Expansion

Azure Disks can be expanded:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: managed-premium-expandable
provisioner: disk.csi.azure.com
parameters:
  skuname: Premium_LRS
allowVolumeExpansion: true  # Enable expansion

Expand a PVC:

# Edit PVC to increase size
kubectl patch pvc mysql-pvc -p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'

# Verify expansion
kubectl get pvc mysql-pvc

Volume Snapshots

Create snapshots for backups:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: disk-snapshot-class
driver: disk.csi.azure.com
deletionPolicy: Retain
---
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: mysql-snapshot
spec:
  volumeSnapshotClassName: disk-snapshot-class
  source:
    persistentVolumeClaimName: mysql-pvc

Azure Files CSI Driver

Azure Files provides shared file storage that can be accessed by multiple pods simultaneously. Azure Files supports SMB protocol and is network-attached storage.

Architecture

graph TB POD1[Pod 1] --> PVC1[PVC: azurefile] POD2[Pod 2] --> PVC2[PVC: azurefile] POD3[Pod 3] --> PVC3[PVC: azurefile] PVC1 --> FILES[Azure Files Share] PVC2 --> FILES PVC3 --> FILES FILES --> SMB[SMB Server<br/>Multi-Zone] style POD1 fill:#e1f5ff style POD2 fill:#e1f5ff style POD3 fill:#e1f5ff style FILES fill:#fff4e1

Storage Class for Azure Files

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: azurefile
provisioner: file.csi.azure.com
parameters:
  skuName: Premium_LRS
  storageAccount: mystorageaccount
volumeBindingMode: Immediate
allowVolumeExpansion: true
reclaimPolicy: Delete

Using Azure Files

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: shared-storage
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: azurefile
  resources:
    requests:
      storage: 100Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: app
        image: nginx:latest
        volumeMounts:
        - name: shared
          mountPath: /shared
      volumes:
      - name: shared
        persistentVolumeClaim:
          claimName: shared-storage

Azure Files Use Cases:

  • Shared configuration files
  • Content management systems
  • Shared application data
  • Log aggregation
  • Multi-pod read/write access

Azure Files Tiers:

  • Standard - General purpose, up to 100 TiB
  • Premium - High performance, up to 100 TiB

Multi-Zone Storage Considerations

Zonal Azure Disks

Azure Disks are zonal resources:

graph TB subgraph zone1[Availability Zone 1] N1[Node 1] --> DISK1[Azure Disk 1] P1[Pod 1] --> DISK1 end subgraph zone2[Availability Zone 2] N2[Node 2] --> DISK2[Azure Disk 2] P2[Pod 2] --> DISK2 end style DISK1 fill:#e1f5ff style DISK2 fill:#fff4e1

Considerations:

  • Azure Disks are tied to a specific availability zone
  • Pods must be scheduled in the same zone as the disk
  • Use WaitForFirstConsumer binding mode
  • Replicate data across zones for high availability

Azure Files Multi-Zone

Azure Files provides multi-zone availability:

graph TB FILES[Azure Files Share<br/>Regional] --> Z1[Zone 1] FILES --> Z2[Zone 2] FILES --> Z3[Zone 3] subgraph zone1[Zone 1] N1[Node 1] --> Z1 P1[Pod 1] --> N1 end subgraph zone2[Zone 2] N2[Node 2] --> Z2 P2[Pod 2] --> N2 end style FILES fill:#e1f5ff style P1 fill:#fff4e1 style P2 fill:#e8f5e9

Benefits:

  • Accessible from all availability zones
  • Automatic replication
  • High availability
  • Perfect for shared storage

Best Practices

  1. Use Premium SSD for Production - Best price/performance for general use

  2. Enable Encryption - Always encrypt Azure Disks and Azure Files

  3. Use WaitForFirstConsumer - For Azure Disk to ensure proper zone placement

  4. Plan for Multi-Zone - Use Azure Files for shared data, replicate Azure Disks for critical data

  5. Monitor Storage Usage - Set up Azure Monitor alerts for disk usage

  6. Use Snapshots - Regular Azure Disk snapshots for backups

  7. Right-Size Volumes - Start small, expand as needed

  8. Use Azure Files for Shared Data - When multiple pods need access

  9. Consider Ultra Disk - For high-performance workloads

  10. Tag Resources - Tag volumes for cost allocation

Common Issues

Volume Not Attaching

Problem: Pod stuck in Pending, volume not attaching

Solutions:

  • Check Azure Disk CSI driver status
  • Verify service principal permissions
  • Check Network Security Group rules
  • Verify disk is in same zone as node
  • Review Azure Activity Log

Azure Files Mount Timeout

Problem: Azure Files mount fails or times out

Solutions:

  • Verify storage account exists
  • Check Network Security Group rules (port 445)
  • Verify network connectivity
  • Check Azure Files CSI driver logs
  • Review Azure Activity Log

Volume Expansion Fails

Problem: Volume expansion doesn’t work

Solutions:

  • Verify storage class allows expansion
  • Check Azure Disk type supports expansion
  • Ensure pod is running (expansion requires mounted volume)
  • Check Azure Disk CSI driver version
  • Review Azure Activity Log

See Also