Create a static volume with Azure disks in Azure Kubernetes Service (AKS)

Container-based applications often need to access and persist data in an external data volume. If a single pod needs access to storage, you can use Azure disks to present a native volume for application use. This article shows you how to manually create an Azure disk and attach it to a pod in AKS.

Note

An Azure disk can only be mounted to a single pod at a time. If you need to share a persistent volume across multiple pods, use Azure Files.

For more information on Kubernetes volumes, see Storage options for applications in AKS.

Before you begin

This article assumes that you have an existing AKS cluster with 1.21 or later version. If you need an AKS cluster, see the AKS quickstart using the Azure CLI, using Azure PowerShell, or using the Azure portal.

If you want to interact with Azure disks on an AKS cluster with 1.20 or previous version, see the Kubernetes plugin for Azure disks.

The Azure Disks CSI driver has a limit of 32 volumes per node. The volume count will change based on the size of the node/node pool. Run the following command to determine the number of volumes that can be allocated per node:

kubectl get CSINode <nodename> -o yaml

Storage class static provisioning

The following table describes the Storage Class parameters for the Azure disk CSI driver static provisioning:

Name Meaning Available Value Mandatory Default value
volumeHandle Azure disk URI /subscriptions/{sub-id}/resourcegroups/{group-name}/providers/microsoft.compute/disks/{disk-id} Yes N/A
volumeAttributes.fsType File system type ext4, ext3, ext2, xfs, btrfs for Linux, ntfs for Windows No ext4 for Linux, ntfs for Windows
volumeAttributes.partition Partition number of the existing disk (only supported on Linux) 1, 2, 3 No Empty (no partition)
- Make sure partition format is like -part1
volumeAttributes.cachingMode Disk host cache setting None, ReadOnly, ReadWrite No ReadOnly

Create an Azure disk

When you create an Azure disk for use with AKS, you can create the disk resource in the node resource group. This approach allows the AKS cluster to access and manage the disk resource. If instead you created the disk in a separate resource group, you must grant the Azure Kubernetes Service (AKS) managed identity for your cluster the Contributor role to the disk's resource group. In this exercise, you're going to create the disk in the same resource group as your cluster.

  1. Identify the resource group name using the az aks show command and add the --query nodeResourceGroup parameter. The following example gets the node resource group for the AKS cluster name myAKSCluster in the resource group name myResourceGroup:

    $ az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
    
    MC_myResourceGroup_myAKSCluster_eastus
    
  2. Create a disk using the az disk create command. Specify the node resource group name obtained in the previous command, and then a name for the disk resource, such as myAKSDisk. The following example creates a 20GiB disk, and outputs the ID of the disk after it's created. If you need to create a disk for use with Windows Server containers, add the --os-type windows parameter to correctly format the disk.

    az disk create \
      --resource-group MC_myResourceGroup_myAKSCluster_eastus \
      --name myAKSDisk \
      --size-gb 20 \
      --query id --output tsv
    

    Note

    Azure disks are billed by SKU for a specific size. These SKUs range from 32GiB for S4 or P4 disks to 32TiB for S80 or P80 disks (in preview). The throughput and IOPS performance of a Premium managed disk depends on both the SKU and the instance size of the nodes in the AKS cluster. See Pricing and Performance of Managed Disks.

    The disk resource ID is displayed once the command has successfully completed, as shown in the following example output. This disk ID is used to mount the disk in the next section.

    /subscriptions/<subscriptionID>/resourceGroups/MC_myAKSCluster_myAKSCluster_eastus/providers/Microsoft.Compute/disks/myAKSDisk
    

Mount disk as a volume

  1. Create a pv-azuredisk.yaml file with a PersistentVolume. Update volumeHandle with disk resource ID from the previous step. For example:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-azuredisk
    spec:
      capacity:
        storage: 20Gi
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Retain
      storageClassName: managed-csi
      csi:
        driver: disk.csi.azure.com
        readOnly: false
        volumeHandle: /subscriptions/<subscriptionID>/resourceGroups/MC_myAKSCluster_myAKSCluster_eastus/providers/Microsoft.Compute/disks/myAKSDisk
        volumeAttributes:
          fsType: ext4
    
  2. Create a pvc-azuredisk.yaml file with a PersistentVolumeClaim that uses the PersistentVolume. For example:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-azuredisk
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 20Gi
      volumeName: pv-azuredisk
      storageClassName: managed-csi
    
  3. Use the kubectl commands to create the PersistentVolume and PersistentVolumeClaim, referencing the two YAML files created earlier:

    kubectl apply -f pv-azuredisk.yaml
    kubectl apply -f pvc-azuredisk.yaml
    
  4. To verify your PersistentVolumeClaim is created and bound to the PersistentVolume, run the following command:

    $ kubectl get pvc pvc-azuredisk
    
    NAME            STATUS   VOLUME         CAPACITY    ACCESS MODES   STORAGECLASS   AGE
    pvc-azuredisk   Bound    pv-azuredisk   20Gi        RWO                           5s
    
  5. Create a azure-disk-pod.yaml file to reference your PersistentVolumeClaim. For example:

    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine
        name: mypod
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 250m
            memory: 256Mi
        volumeMounts:
          - name: azure
            mountPath: /mnt/azure
      volumes:
        - name: azure
          persistentVolumeClaim:
            claimName: pvc-azuredisk
    
  6. Run the following command to apply the configuration and mount the volume, referencing the YAML configuration file created in the previous steps:

    kubectl apply -f azure-disk-pod.yaml
    

Next steps

To learn about our recommended storage and backup practices, see Best practices for storage and backups in AKS.