Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
If multiple pods need concurrent access to the same storage volume, you can use Azure Files to connect using the Server Message Block (SMB) or NFS protocol. This article shows you how to dynamically and statically create an Azure Files share for use by multiple pods in an Azure Kubernetes Service (AKS) cluster using Azure Files.
Note
The Azure File CSI driver only permits the mounting of SMB file shares using key-based (NTLM v2) authentication, and therefore doesn't support the maximum security profile of Azure File share settings. On the other hand, mounting NFS file shares doesn't require key-based authentication.
Note
We recommend FIO when running benchmarking tests. For more information, see benchmarking tools and tests.
Prerequisites
- Azure CLI version 2.0.59 or later installed and configured. Find the version using the
az --versioncommand. To install or upgrade, see Install Azure CLI. - The Azure Files CSI driver enabled on your AKS cluster.
- An Azure storage account.
- When choosing between Standard and Premium file shares, it's important you understand the provisioning model and requirements of the expected usage pattern you plan to run on Azure Files. For more information, see Choosing an Azure Files performance tier based on usage patterns.
Use built-in storage classes to create dynamic PVs with Azure Files
Storage classes define how a unit of storage is dynamically created with a persistent volume. A storage account is automatically created in the node resource group for use with the storage class to hold the Azure Files file share. When you use CSI drivers on AKS, there are two extra built-in StorageClasses that use the Azure Files CSI storage drivers (the other CSI storage classes are created with the cluster alongside the in-tree default storage classes):
azurefile-csi: Uses Azure Standard Storage to create an Azure file share.azurefile-csi-premium: Uses Azure Premium Storage to create an Azure file share.
The reclaim policy on both storage classes ensures that the underlying Azure Files file share is deleted when the respective PV is deleted. The storage classes also configure the file shares to be expandable, you just need to edit the persistent volume claim (PVC) with the new size.
You can select one of the following Azure storage redundancy SKUs for the skuname parameter in the storage class definition:
- Standard_LRS: Standard locally redundant storage
- Standard_GRS: Standard geo-redundant storage
- Standard_ZRS: Standard zone-redundant storage
- Standard_RAGRS: Standard read-access geo-redundant storage
- Standard_RAGZRS: Standard read-access geo-zone-redundant storage
- Premium_LRS: Premium locally redundant storage
- Premium_ZRS: Premium zone-redundant storage
Note
Azure Files supports Azure Premium file shares. The minimum file share capacity is 100 GiB. We recommend using Azure Premium file shares instead of Standard file shares because Premium file shares offer higher performance, low-latency disk support for I/O-intensive workloads.
Create custom storage classes for dynamic PVs with Azure Files
The default storage classes are suitable for most scenarios. In some cases, you might want to have your own storage class customized with your own parameters. For example, you might want to configure the mountOptions of the file share.
Create a file named
azure-file-sc.yamland paste in the following example manifest:kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: my-azurefile provisioner: file.csi.azure.com reclaimPolicy: Delete volumeBindingMode: Immediate allowVolumeExpansion: true mountOptions: - dir_mode=0640 - file_mode=0640 - uid=0 - gid=0 - mfsymlinks - cache=strict # https://linux.die.net/man/8/mount.cifs - nosharesock parameters: skuName: Standard_LRSCreate the storage class using the
kubectl applycommand:kubectl apply -f azure-file-sc.yamlYour output should resemble the following example output:
storageclass.storage.k8s.io/my-azurefile created
Storage class parameters for dynamic PVs with Azure Files
The following table includes parameters you can use to define a custom storage class for your persistent volume claims (PVCs) with Azure Files:
| Name | Meaning | Available values | Required | Default value |
|---|---|---|---|---|
accountAccessTier |
Access tier for storage account | Standard account can choose Hot or Cool, and Premium account can only choose Premium. |
No | Empty. Use default setting for different storage account types. |
accountQuota |
Limits the quota for an account. You can specify a maximum quota in GB (102400 GB by default). If the account exceeds the specified quota, the driver skips selecting the account. | No | 102400 |
|
allowBlobPublicAccess |
Allow or disallow public access to all blobs or containers for storage account created by driver. | true or false |
No | false |
disableDeleteRetentionPolicy |
Specify whether disable DeleteRetentionPolicy for storage account created by driver. | true or false |
No | false |
folderName |
Specify folder name in Azure file share. | Existing folder name in Azure file share. | No | If folder name doesn't exist in file share, the mount fails. |
getLatestAccount |
Determines whether to get the latest account key based on the creation time. This driver gets the first key by default. | true or false |
No | false |
location |
Specify the Azure region of the Azure storage account. | For example, eastus. |
No | If empty, driver uses the same location name as current AKS cluster. |
matchTags |
Match tags when driver tries to find a suitable storage account. | true or false |
No | false |
networkEndpointType |
Specify network endpoint type for the storage account created by driver. If privateEndpoint is specified, a private endpoint is created for the storage account. For other cases, a service endpoint is created by default. |
"",privateEndpoint |
No | "" |
protocol |
Specify file share protocol. | smb, nfs |
No | smb |
requireInfraEncryption |
Specify whether or not the service applies a secondary layer of encryption with platform managed keys for data at rest for storage account created by driver. | true or false |
No | false |
resourceGroup |
Specify the resource group for the Azure Disks. | Existing resource group name | No | If empty, driver uses the same resource group name as current AKS cluster. |
selectRandomMatchingAccount |
Determines whether to randomly select a matching account. By default, the driver always selects the first matching account in alphabetical order (Note: This driver uses account search cache, which results in uneven distribution of file creation across multiple accounts). | true or false |
No | false |
server |
Specify Azure storage account server address. | Existing server address, for example accountname.privatelink.file.core.windows.net. |
No | If empty, driver uses default accountname.file.core.windows.net or other sovereign cloud account address. |
shareAccessTier |
Access tier for file share | General purpose v2 account can choose between TransactionOptimized (default), Hot, and Cool. Premium storage account type for file shares only. |
No | Empty. Use default setting for different storage account types. |
shareName |
Specify Azure file share name. | Existing or new Azure file share name. | No | If empty, driver generates an Azure file share name. |
shareNamePrefix |
Specify Azure file share name prefix created by driver. | Share name can only contain lowercase letters, numbers, hyphens, and length should be fewer than 21 characters. | No | |
skuName |
Azure Files storage account type (alias: storageAccountType) |
Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS, Standard_RAGZRS,Premium_LRS, Premium_ZRS, StandardV2_LRS, StandardV2_ZRS, StandardV2_GRS, StandardV2_GZRS, PremiumV2_LRS, PremiumV2_ZRS |
No | Standard_LRS Minimum file share size for Premium account type is 100 GB. ZRS account type is supported in limited regions. NFS file share only supports Premium account type. Standard V2 SKU names are for Azure Files provisioned v2 model. |
storageAccount |
Specify an Azure storage account name. | storageAccountName | No | When a specific storage account name is not provided, the driver will look for a suitable storage account that matches the account settings within the same resource group. If it fails to find a matching storage account, it will create a new one. However, if a storage account name is specified, the storage account must already exist. |
storageEndpointSuffix |
Specify Azure storage endpoint suffix. | core.windows.net, core.chinacloudapi.cn, etc. |
No | If empty, driver uses default storage endpoint suffix according to cloud environment. For example, core.windows.net. |
tags |
Tags are created in new storage account. | Tag format: 'foo=aaa,bar=bbb' | No | "" |
| --- | The following parameters are only for SMB protocol | --- | --- | --- |
subscriptionID |
Specify Azure subscription ID where Azure file share is created. | Azure subscription ID | No | If not empty, resourceGroup must be provided. |
storeAccountKey |
Specify whether to store account key to Kubernetes secret. | true or false false means driver uses kubelet identity to get account key. |
No | true |
secretName |
Specify secret name to store account key. | No | ||
secretNamespace |
Specify the namespace of secret to store account key. Note: If secretNamespace isn't specified, the secret is created in the same namespace as the pod. |
default,kube-system, etc. |
No | PVC namespace, for example csi.storage.k8s.io/pvc/namespace |
useDataPlaneAPI |
Specify whether to use data plane API for file share create/delete/resize, which could solve the SRP API throttling issue because the data plane API has almost no limit, while it would fail when there's firewall or Vnet settings on storage account. | true or false |
No | false |
| --- | The following parameters are only for NFS protocol | --- | --- | --- |
mountPermissions |
Mounted folder permissions. The default is 0777. If set to 0, driver doesn't perform chmod after mount |
0777 |
No | |
rootSquashType |
Specify root squashing behavior on the share. The default is NoRootSquash |
AllSquash, NoRootSquash, RootSquash |
No | |
| --- | The following parameters are only for VNet setting (for example: NFS, private endpoint) | --- | --- | --- |
fsGroupChangePolicy |
Indicates how the driver changes volume's ownership. Pod securityContext.fsGroupChangePolicy is ignored. |
OnRootMismatch (default), Always, None |
No | OnRootMismatch |
subnetName |
Subnet name | Existing subnet name of the agent node. | No | If empty, driver uses the subnetName value in Azure cloud config file. |
vnetName |
Virtual network name | Existing virtual network name. | No | If empty, driver will update all the subnets under the cluster virtual network. |
vnetResourceGroup |
Specify VNet resource group where virtual network is defined. | Existing resource group name. | No | If empty, driver uses the vnetResourceGroup value in Azure cloud config file. |
Note
If the storage account is created by the driver, then you only need to specify networkEndpointType: privateEndpoint parameter in storage class. The CSI driver creates the private endpoint and private DNS zone (named privatelink.file.core.windows.net) together with the account. If you bring your own storage account, then you need to create the private endpoint for the storage account. If you're using Azure Files storage in a network isolated cluster, you must create a custom storage class with "networkEndpointType: privateEndpoint". You can use the following example manifest as a reference:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azurefile-csi
provisioner: file.csi.azure.com
allowVolumeExpansion: true
parameters:
skuName: Premium_LRS # available values: Premium_LRS, Premium_ZRS, Standard_LRS, Standard_GRS, Standard_ZRS, Standard_RAGRS, Standard_RAGZRS
networkEndpointType: privateEndpoint
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
- dir_mode=0777 # modify this permission if you want to enhance the security
- file_mode=0777
- mfsymlinks
- cache=strict # https://linux.die.net/man/8/mount.cifs
- nosharesock # reduce probability of reconnect race
- actimeo=30 # reduce latency for metadata-heavy workload
- nobrl # disable sending byte range lock requests to the server and for applications which have challenges with posix locks
Create a PVC with Azure Files
A PVC uses the storage class object to dynamically provision an Azure file share. You can use the example YAML manifest in this section to create a PVC that's 100 GB in size with ReadWriteMany access. For more information on access modes, see Kubernetes PV access modes.
Create a file named
azure-file-pvc.yamland paste in the following YAML. Make sure thestorageClassNamematches the name of your existing storage class.apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-azurefile spec: accessModes: - ReadWriteMany storageClassName: my-azurefile resources: requests: storage: 100GiNote
If using the
Premium_LRSSKU for your storage class, the minimum value forstoragemust be100Gi.Create the PVC using the
kubectl applycommand.kubectl apply -f azure-file-pvc.yamlView the status of the PVC using the
kubectl getcommand:kubectl get pvc my-azurefileYour output should resemble the following example output, which shows that the PVC is in a
Boundstate, and a PV was dynamically created to satisfy the claim:NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE my-azurefile Bound pvc-aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb 100Gi RWX my-azurefile 5m
Use a PVC with Azure Files in a pod
The example YAML manifest in this section creates a pod that uses the PVC my-azurefile to mount the Azure Files file share at the /mnt/azure path. For Windows Server containers, specify a mountPath using the Windows path convention, such as 'D:'.
Create a file named
azure-pvc-files.yaml, and paste in the following YAML. Make sure theclaimNamematches the name of your existing PVC.kind: Pod apiVersion: v1 metadata: name: mypod spec: containers: - name: mypod image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine resources: requests: cpu: 100m memory: 128Mi limits: cpu: 250m memory: 256Mi volumeMounts: - mountPath: /mnt/azure name: volume readOnly: false volumes: - name: volume persistentVolumeClaim: claimName: my-azurefileCreate the pod using the
kubectl applycommand.kubectl apply -f azure-pvc-files.yamlView the status of the pod using the
kubectl describecommand:kubectl describe pod mypodYour output should resemble the following example output, which shows that the pod is running and the volume is mounted at the correct path:
Containers: mypod: Container ID: docker://BB22CC33DD44EE55FF66AA77BB88CC99DD00EE11 Image: mcr.microsoft.com/oss/nginx/nginx:1.15.5-alpine Image ID: docker-pullable://nginx@sha256:AA11BB22CC33DD44EE55FF66AA77BB88CC99DD00 State: Running Started: Fri, 01 Mar 2019 23:56:16 +0000 Ready: True Mounts: /mnt/azure from volume (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-8rv4z (ro) [...] Volumes: volume: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: my-azurefile ReadOnly: false [...]
Mount options for Azure Files
The location to configure mount options (mountOptions) depends on whether you're provisioning dynamic or static persistent volumes:
- If you're dynamically provisioning a volume with a storage class, specify the mount options on the storage class object (kind: StorageClass).
- If you're statically provisioning a volume, specify the mount options on the PV object (kind: PersistentVolume).
- If you're mounting the file share as an inline volume, specify the mount options on the Pod object (kind: Pod).
For more information, see Mount options.
The default value for fileMode and dirMode is 0777 for Kubernetes versions 1.13.0 and above. The following example sets 0777:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: my-azurefile
provisioner: file.csi.azure.com # replace with "kubernetes.io/azure-file" if aks version is less than 1.21
allowVolumeExpansion: true
mountOptions:
- dir_mode=0777
- file_mode=0777
- uid=0
- gid=0
- mfsymlinks
- cache=strict
- actimeo=30
- nobrl # disable sending byte range lock requests to the server and for applications which have challenges with posix locks
parameters:
skuName: Premium_LRS
Recommended mount options for SMB shares
Recommended mount options for SMB shares are provided in the following storage class example:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azurefile-csi
provisioner: file.csi.azure.com
allowVolumeExpansion: true
parameters:
skuName: Premium_LRS # available values: Premium_LRS, Premium_ZRS, Standard_LRS, Standard_GRS, Standard_ZRS, Standard_RAGRS, Standard_RAGZRS
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
- dir_mode=0777 # modify this permission if you want to enhance the security
- file_mode=0777 # modify this permission if you want to enhance the security
- mfsymlinks # support symbolic links
- cache=strict # https://linux.die.net/man/8/mount.cifs
- nosharesock # reduces probability of reconnect race
- actimeo=30 # reduces latency for metadata-heavy workload
- nobrl # disable sending byte range lock requests to the server and for applications which have challenges with posix locks
If you're using premium (SSD) file shares and your workload is metadata heavy, enroll to use the metadata caching feature to improve performance.
For more information, see Improve performance for SMB Azure file shares.
Recommended mount options for NFS shares
Recommended mount options for NFS shares are provided in the following storage class example:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azurefile-csi-nfs
provisioner: file.csi.azure.com
parameters:
protocol: nfs
skuName: Premium_LRS # available values: Premium_LRS, Premium_ZRS
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
mountOptions:
- nconnect=4 # improves performance by enabling multiple connections to share
- noresvport # improves availability
- actimeo=30 # reduces latency for metadata-heavy workloads
Increase read-ahead size to improve read throughput.
While Azure Files supports setting nconnect up to the maximum setting of 16, we recommend configuring the mount options with the optimal setting of nconnect=4. Currently, there are no gains beyond four channels for the Azure Files implementation of nconnect.
Create a volume snapshot from a PVC with Azure Files
The Azure Files CSI driver supports creating snapshots of persistent volumes and the underlying file shares.
Create a volume snapshot class using the
kubectl applycommand:kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/azurefile-csi-driver/master/deploy/example/snapshot/volumesnapshotclass-azurefile.yamlYour output should resemble the following example output:
volumesnapshotclass.snapshot.storage.k8s.io/csi-azurefile-vsc createdCreate a volume snapshot from the dynamic PVC you created earlier in this tutorial using the
kubectl applycommand:kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/azurefile-csi-driver/master/deploy/example/snapshot/volumesnapshot-azurefile.yamlYour output should resemble the following example output:
volumesnapshot.snapshot.storage.k8s.io/azurefile-volume-snapshot createdView the status of the volume snapshot using the
kubectl describecommand:kubectl describe volumesnapshot azurefile-volume-snapshotYour output should resemble the following example output, which shows that the volume snapshot isn't ready to use because the driver is still creating the snapshot of the underlying Azure file share:
Name: azurefile-volume-snapshot Namespace: default Labels: <none> Annotations: API Version: snapshot.storage.k8s.io/v1beta1 Kind: VolumeSnapshot Metadata: Creation Timestamp: 2020-08-27T22:37:41Z Finalizers: snapshot.storage.kubernetes.io/volumesnapshot-as-source-protection snapshot.storage.kubernetes.io/volumesnapshot-bound-protection Generation: 1 Resource Version: 955091 Self Link: /apis/snapshot.storage.k8s.io/v1beta1/namespaces/default/volumesnapshots/azurefile-volume-snapshot UID: 00aa00aa-bb11-cc22-dd33-44ee44ee44ee Spec: Source: Persistent Volume Claim Name: pvc-azurefile Volume Snapshot Class Name: csi-azurefile-vsc Status: Bound Volume Snapshot Content Name: snapcontent-00aa00aa-bb11-cc22-dd33-44ee44ee44ee Ready To Use: false Events: <none>
Resize a persistent volume with Azure Files
Note
Shrinking persistent volumes is currently not supported. Trying to patch an existing PVC with a smaller size than the current one leads to the following error message:
The persistentVolumeClaim "pvc-azurefile" is invalid: spec.resources.requests.storage: Forbidden: field can not be less than previous value.
You can request a larger volume for a PVC by editing the PVC object to specify a larger size. This change triggers the expansion of the underlying volume that backs the PV. A new PV is never created to satisfy the claim. Instead, an existing volume is resized.
In AKS, the built-in managed-csi storage class already supports expansion, so you can use the dynamic PVC you created earlier in this tutorial. The PVC requested a 100 GiB file share.
Verify the current size of the PVC and the filesystem inside the pod using the
kubectl execcommand to run thedf -hcommand inside the pod:kubectl exec -it nginx-azurefile -- df -h /mnt/azurefileYour output should resemble the following example output, which shows that the filesystem is 100 GB in size:
Filesystem Size Used Avail Use% Mounted on //a123b4c567de89fghi01jk2.file.core.windows.net/pvc-00aa00aa-bb11-cc22-dd33-44ee44ee44ee 100G 128K 100G 1% /mnt/azurefileExpand the PVC by increasing the
spec.resources.requests.storagefield using thekubectl patchcommand. In this example, we increase the file share to 200 GiB:kubectl patch pvc pvc-azurefile --type merge --patch '{"spec": {"resources": {"requests": {"storage": "200Gi"}}}}'Your output should resemble the following example output, which shows that the PVC was patched successfully:
persistentvolumeclaim/pvc-azurefile patchedVerify the PVC was successfully resized and the new size is reflected in the pod by using the
kubectl get pvccommand and thedf -hcommand inside the pod:kubectl get pvc pvc-azurefileYour output should resemble the following example output, which shows that the PVC is still in a
Boundstate, and the capacity was updated to 200 GiB:NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE pvc-azurefile Bound pvc-00aa00aa-bb11-cc22-dd33-44ee44ee44ee 200Gi RWX azurefile-csi 64mVerify the new size of the filesystem inside the pod using the
kubectl execcommand to run thedf -hcommand inside the pod:kubectl exec -it nginx-azurefile -- df -h /mnt/azurefileYour output should resemble the following example output, which shows that the filesystem is now 200 GB in size:
Filesystem Size Used Avail Use% Mounted on //a123b4c567de89fghi01jk2.file.core.windows.net/pvc-bbbbbbbb-1111-2222-3333-cccccccccccc 200G 128K 200G 1% /mnt/azurefile
Use a persistent volume with private Azure Files storage (private endpoint)
If your Azure Files resources are protected with a private endpoint, you must create your own storage class. Make sure that you've configured your DNS settings to resolve the private endpoint IP address to the FQDN of the connection string. When you create the storage class using the Azure Files CSI driver, you need to specify the networkEndpointType parameter with the value privateEndpoint, and provide the following parameters:
resourceGroup: The resource group where the storage account is deployed.storageAccount: The storage account name.server: The FQDN of the storage account's private endpoint.
Create a file named
private-azure-file-sc.yamland then paste in the following manifest. Make sure you replace the placeholders for<resourceGroup>and<storageAccountName>.apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: private-azurefile-csi provisioner: file.csi.azure.com allowVolumeExpansion: true parameters: resourceGroup: <resourceGroup> storageAccount: <storageAccountName> server: <storageAccountName>.file.core.windows.net reclaimPolicy: Delete volumeBindingMode: Immediate mountOptions: - dir_mode=0777 - file_mode=0777 - uid=0 - gid=0 - mfsymlinks - cache=strict # https://linux.die.net/man/8/mount.cifs - nosharesock # reduce probability of reconnect race - actimeo=30 # reduce latency for metadata-heavy workloadCreate the storage class using the
kubectl applycommand:kubectl apply -f private-azure-file-sc.yamlYour output should resemble the following example output:
storageclass.storage.k8s.io/private-azurefile-csi createdCreate a file named
private-pvc.yamland paste in the following manifest. Make sure thestorageClassNamematches the name of your existing storage class.apiVersion: v1 kind: PersistentVolumeClaim metadata: name: private-azurefile-pvc spec: accessModes: - ReadWriteMany storageClassName: private-azurefile-csi resources: requests: storage: 100GiCreate the PVC using the
kubectl applycommand.kubectl apply -f private-pvc.yaml
Use Azure Files with Windows containers
The Azure Files CSI driver also supports Windows nodes and containers. To use Windows containers, follow the Windows containers quickstart to add a Windows node pool. After you have a Windows node pool, you can use the built-in storage classes like azurefile-csi or create a custom one. The example Windows-based stateful set in this section saves timestamps into a file data.txt every second, which is mounted to an Azure file share using the Azure Files CSI driver.
Create the stateful set using the
kubectl applycommand:kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/azurefile-csi-driver/master/deploy/example/windows/statefulset.yamlYour output should resemble the following example output:
statefulset.apps/busybox-azurefile createdValidate the timestamps are being written to the file share using the following
kubectl execcommands to run thecatcommand inside the pod:kubectl exec -it busybox-azurefile-0 -- cat c:\\mnt\\azurefile\\data.txt # on Linux/MacOS Bash kubectl exec -it busybox-azurefile-0 -- cat c:\mnt\azurefile\data.txt # on Windows Powershell/CMDYour output should resemble the following example output, which shows that timestamps are being written to the file share every second:
2020-08-27 22:11:01Z 2020-08-27 22:11:02Z 2020-08-27 22:11:04Z (...)
Use NFS protocol with Azure Files
Azure Files supports the NFS v4.1 protocol. NFS version 4.1 support for Azure Files provides you with a fully managed NFS file system as a service built on a highly available and highly durable distributed resilient storage platform.
This option is optimized for random access workloads with in-place data updates and provides full POSIX file system support. This section shows you how to use NFS shares with the Azure File CSI driver on an AKS cluster.
Prerequisites for using NFS shares with Azure Files
- Your AKS cluster control plane identity (that is, your AKS cluster name) is added to the Contributor role on the VNet and NetworkSecurityGroup.
- Your AKS cluster's service principal or managed service identity (MSI) must be added to the Contributor role to the storage account.
Note
You can use a private endpoint instead of allowing access to the selected VNet.
Optimize read and write size options
This section provides information about how to approach performance tuning NFS with the Azure Files CSI driver with the rsize and wsize options. The rsize and wsize options set the maximum transfer size of an NFS operation. If rsize or wsize aren't specified on mount, the client and server negotiate the largest size supported by the two. Currently, both Azure Files and modern Linux distributions support read and write sizes as large as 1,048,576 Bytes (1 MiB).
Optimal performance is based on efficient client-server communication. Increasing or decreasing the mount read and write option size values can improve NFS performance. The default size of the read/write packets transferred between client and server are 8 KB for NFS version 2, and 32 KB for NFS version 3 and 4. These defaults might be too large or too small. Reducing the rsize and wsize might improve NFS performance in a congested network by sending smaller packets for each NFS-read reply and write request. However, this can increase the number of packets needed to send data across the network, increasing total network traffic and CPU utilization on the client and server.
It's important that you perform testing to find an rsize and wsize that sustain efficient packet transfer and don't decrease throughput and increase latency.
The following example manifest configures the mountOptions section in a storage class to a maximum rsize and wsize of 256-KiB:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azurefile-csi-nfs
provisioner: file.csi.azure.com
allowVolumeExpansion: true
parameters:
protocol: nfs
mountOptions:
- nconnect=4
- noresvport
- actimeo=30
- rsize=262144
- wsize=262144
For a list of supported mountOptions, see NFS mount options.
Create NFS file share storage class
Note
vers, minorversion, sec are configured by the Azure File CSI driver. Specifying a value in your manifest for these properties isn't supported.
Create a file named
nfs-sc.yamland paste in the following manifest. Make sure to specifyprotocol: nfsin the parameters section, and adjust themountOptionsas needed for your workload.apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: azurefile-csi-nfs provisioner: file.csi.azure.com allowVolumeExpansion: true parameters: protocol: nfs mountOptions: - nconnect=4 - noresvport - actimeo=30After editing and saving the file, create the storage class using the
kubectl applycommand.kubectl apply -f nfs-sc.yamlYour output should resemble the following example output:
storageclass.storage.k8s.io/azurefile-csi-nfs created
Create a stateful set with an NFS-backed file share
Create a file named
nfs-ss.yamland paste in the following manifest. This configuration saves timestamps into a filedata.txt.apiVersion: apps/v1 kind: StatefulSet metadata: name: statefulset-azurefile labels: app: nginx spec: podManagementPolicy: Parallel # default is OrderedReady serviceName: statefulset-azurefile replicas: 1 template: metadata: labels: app: nginx spec: nodeSelector: "kubernetes.io/os": linux containers: - name: statefulset-azurefile image: mcr.microsoft.com/oss/nginx/nginx:1.19.5 command: - "/bin/bash" - "-c" - set -euo pipefail; while true; do echo $(date) >> /mnt/azurefile/outfile; sleep 1; done volumeMounts: - name: persistent-storage mountPath: /mnt/azurefile updateStrategy: type: RollingUpdate selector: matchLabels: app: nginx volumeClaimTemplates: - metadata: name: persistent-storage spec: storageClassName: azurefile-csi-nfs accessModes: ["ReadWriteMany"] resources: requests: storage: 100GiCreate the stateful set using the
kubectl applycommand.kubectl apply -f nfs-ss.yamlYour output should resemble the following example output:
statefulset.apps/statefulset-azurefile createdValidate the contents of the volume using the following
kubectl execcommand to run thedf -hcommand inside the pod:kubectl exec -it statefulset-azurefile-0 -- df -hYour output should resemble the following example output, which shows that the NFS file share is mounted at the correct path with the correct size:
Filesystem Size Used Avail Use% Mounted on ... /dev/sda1 29G 11G 19G 37% /etc/hosts accountname.file.core.windows.net:/accountname/pvc-cccccccc-2222-3333-4444-dddddddddddd 100G 0 100G 0% /mnt/azurefile ...Because the NFS file share is in a Premium storage account, the minimum file share size is 100 GiB. If you create a PVC with a small storage size, you might encounter an error similar to the following: failed to create file share ... size (5)....
Encryption in Transit (EiT) for NFS file shares (preview)
Note
The EiT feature is now available in preview starting with AKS version 1.33. Please note that Ubuntu 20.04, Azure Linux, arm64 and Windows nodes aren't currently supported.
The feature is supported for the following Linux distributions in these supported regions.
Encryption in Transit (EiT) ensures that all read and writes to the NFS file shares within the VNET are encrypted, providing an extra layer of security.
By setting encryptInTransit: "true" in the storage class parameters, you can enable data encryption in transit for NFS Azure file shares. For example:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azurefile-csi-nfs
provisioner: file.csi.azure.com
allowVolumeExpansion: true
parameters:
protocol: nfs
encryptInTransit: "true"
mountOptions:
- nconnect=4
- noresvport
- actimeo=30
Use managed identity to access Azure Files storage (preview)
Azure Files now supports managed identity based authentication for SMB access. This enables your applications to securely access Azure Files without storing or managing credentials.
Note
Managed identity support for Azure Files in AKS is available in preview starting with AKS version 1.34 on Linux nodes.
Prerequisites for using managed identity to access Azure Files storage
- Ensure the user-assigned Kubelet identity has the
Storage File Data SMB MI Adminrole on the storage account.- If you use your own storage account, you need to assign
Storage File Data SMB MI Adminrole to the user-assigned Kubelet identity on that storage account. - If the storage account is created by the CSI driver, grant
Storage File Data SMB MI Adminrole to the resource group where the storage account resides. - If you just leverage the default built-in user-assigned Kubelet identity, it already has the required
Storage File Data SMB MI Adminrole on the managed node resource group.
- If you use your own storage account, you need to assign
Enable managed identity for dynamic PVs with Azure Files
To enable managed identity for dynamically provisioned volumes, you need to create a new storage class with mountWithManagedIdentity: "true" and deploy your stateful set using this storage class.
The following example manifest configures a storage class to use managed identity to access Azure Files:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: azurefile-csi
provisioner: file.csi.azure.com
parameters:
resourceGroup: EXISTING_RESOURCE_GROUP_NAME # optional, node resource group by default if it's not provided
storageAccount: EXISTING_STORAGE_ACCOUNT_NAME # optional, a new account will be created if it's not provided
mountWithManagedIdentity: "true"
# optional, clientID of the managed identity, kubelet identity would be used by default if it's not provided
clientID: "xxxxx-xxxx-xxx-xxx-xxxxxxx"
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: true
mountOptions:
- dir_mode=0777 # modify this permission if you want to enhance the security
- file_mode=0777
- uid=0
- gid=0
- mfsymlinks
- cache=strict # https://linux.die.net/man/8/mount.cifs
- nosharesock # reduce probability of reconnect race
- actimeo=30 # reduce latency for metadata-heavy workload
- nobrl # disable sending byte range lock requests to the server
Enable managed identity for static PVs with Azure Files
To enable managed identity for static volumes, you need to create a PV with mountWithManagedIdentity: "true" and mount the PV to your application pod.
The following example manifest configures a PV to use managed identity to access Azure Files:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-azurefile
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: azurefile-csi
mountOptions:
- dir_mode=0777 # modify this permission if you want to enhance the security
- file_mode=0777
- uid=0
- gid=0
- mfsymlinks
- cache=strict # https://linux.die.net/man/8/mount.cifs
- nosharesock # reduce probability of reconnect race
- actimeo=30 # reduce latency for metadata-heavy workload
- nobrl # disable sending byte range lock requests to the server
csi:
driver: file.csi.azure.com
# make sure volumeHandle is unique for every identical share in the cluster
volumeHandle: "{resource-group-name}#{account-name}#{file-share-name}"
volumeAttributes:
resourceGroup: EXISTING_RESOURCE_GROUP_NAME # optional, node resource group by default if it's not provided
storageAccount: EXISTING_STORAGE_ACCOUNT_NAME # optional, a new account will be created if it's not provided
shareName: EXISTING_FILE_SHARE_NAME
mountWithManagedIdentity: "true"
# optional, clientID of the managed identity, kubelet identity would be used by default if it's empty
clientID: "xxxxx-xxxx-xxx-xxx-xxxxxxx"
Create a static PV with Azure Files
The following sections provide instructions for creating a static PV with Azure Files. A static PV is a persistent volume that an administrator creates manually. This PV is available for use by pods in the cluster. To use a static PV, you create a PVC that references the PV, and then create a pod that references the PVC.
Storage class parameters for static PVs with Azure Files
The following table includes parameters you can use to define a custom storage class for your static PVCs with Azure Files:
| Name | Meaning | Available values | Required | Default value |
|---|---|---|---|---|
volumeAttributes.resourceGroup |
Specify an Azure resource group name. | myResourceGroup | No | If empty, driver uses the same resource group name as current cluster. |
volumeAttributes.storageAccount |
Specify an existing Azure storage account name. | storageAccountName | Yes | |
volumeAttributes.shareName |
Specify an Azure file share name. | fileShareName | Yes | |
volumeAttributes.folderName |
Specify a folder name in Azure file share. | folderName | No | If folder name doesn't exist in file share, mount would fail. |
volumeAttributes.protocol |
Specify file share protocol. | smb, nfs |
No | smb |
volumeAttributes.server |
Specify Azure storage account server address | Existing server address, for example accountname.privatelink.file.core.windows.net. |
No | If empty, driver uses default accountname.file.core.windows.net or other sovereign cloud account address. |
| --- | The following parameters are only for SMB protocol | --- | --- | --- |
volumeAttributes.secretName |
Specify a secret name that stores storage account name and key. | No | ||
volumeAttributes.secretNamespace |
Specify a secret namespace. | default,kube-system, etc. |
No | PVC namespace (csi.storage.k8s.io/pvc/namespace) |
nodeStageSecretRef.name |
Specify a secret name that stores storage account name and key. | Existing secret name. | No | If empty, driver uses kubelet identity to get account key. |
nodeStageSecretRef.namespace |
Specify a secret namespace. | Kubernetes namespace | No | |
| --- | The following parameters are only for NFS protocol | --- | --- | --- |
volumeAttributes.fsGroupChangePolicy |
Indicates how the driver changes a volume's ownership. Pod securityContext.fsGroupChangePolicy is ignored. |
OnRootMismatch (default), Always, None |
No | OnRootMismatch |
volumeAttributes.mountPermissions |
Specify mounted folder permissions. The default is 0777 |
No |
Create an Azure file share
Before you can use an Azure Files file share as a Kubernetes volume, you must create an Azure Storage account and the file share.
Get the node resource group name of your AKS cluster using the
az aks showcommand with the--query nodeResourceGroupparameter.az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsvThe output of the command resembles the following example:
MC_myResourceGroup_myAKSCluster_eastusCreate a storage account using the
az storage account createcommand with the--skuparameter. The following command creates a storage account using theStandard_LRSSKU. Make sure to replace the following placeholders:myAKSStorageAccountwith the name of the storage accountnodeResourceGroupNamewith the name of the resource group that the AKS cluster nodes are hosted inlocationwith the name of the region to create the resource in. It should be the same region as the AKS cluster nodes.
az storage account create --name myAKSStorageAccount --resource-group nodeResourceGroupName --location location --sku Standard_LRSExport the connection string as an environment variable, which you use to create the file share, using the [
az storage account show-connection-string][az-storage-account-show-connection-string] command. Make sure to replacestorageAccountNameandresourceGroupNamewith your storage account name and resource group name.export AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string --name storageAccountName --resource-group resourceGroupName -o tsv)Note
Connection strings must be protected using key rotation or storage in an Azure Key Vault. For more information about connection strings, see Configure Azure Storage connection strings and Manage storage account access keys. For production environments, Microsoft recommends using Microsoft Entra ID authentication. For more information, see Authorize access to data in Azure Storage.
Create the file share using the
az storage share createcommand. Make sure to replaceshareNamewith your share name.az storage share create --name shareName --connection-string $AZURE_STORAGE_CONNECTION_STRINGExport the storage account key as an environment variable using the [
az storage account keys list][az-storage-account-keys-list] command. Make sure to replacestorageAccountNameandresourceGroupNamewith your storage account name and resource group name.STORAGE_KEY=$(az storage account keys list --resource-group nodeResourceGroupName --account-name myAKSStorageAccount --query "[0].value" -o tsv)Echo the storage account name and key using the following command. Make note of the storage account key, which you use to create a Kubernetes secret in the next step.
echo Storage account key: $STORAGE_KEY
Create a Kubernetes secret
Kubernetes needs credentials to access the file share created in the previous step. These credentials are stored in a Kubernetes secret, which is referenced when you create a Kubernetes pod.
Create the secret using the
kubectl create secretcommand. The following example creates a secret named azure-secret and populates the azurestorageaccountname and azurestorageaccountkey from the previous step. To use an existing Azure storage account, provide the account name and key.kubectl create secret generic azure-secret --from-literal=azurestorageaccountname=myAKSStorageAccount --from-literal=azurestorageaccountkey=$STORAGE_KEY
Mount file share as a persistent volume
Create a new file named
azurefiles-pv.yamland copy in the following contents. Undercsi, updateresourceGroup,volumeHandle, andshareName. For mount options, the default value forfileModeanddirModeis 0777.apiVersion: v1 kind: PersistentVolume metadata: annotations: pv.kubernetes.io/provisioned-by: file.csi.azure.com name: azurefile spec: capacity: storage: 5Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: azurefile-csi csi: driver: file.csi.azure.com volumeHandle: "{resource-group-name}#{account-name}#{file-share-name}" # make sure this volumeid is unique for every identical share in the cluster volumeAttributes: shareName: aksshare nodeStageSecretRef: name: azure-secret namespace: default mountOptions: - dir_mode=0777 - file_mode=0777 - uid=0 - gid=0 - mfsymlinks - cache=strict - nosharesock - nobrl # disable sending byte range lock requests to the server and for applications which have challenges with posix locksCreate the PV using the
kubectl createcommand.kubectl create -f azurefiles-pv.yamlCreate a new file named azurefiles-mount-options-pvc.yaml and paste in the following contents. Make sure the
storageClassNamematches the name of your existing storage class, and thevolumeNamematches the name of the PV you created in the previous step.apiVersion: v1 kind: PersistentVolumeClaim metadata: name: azurefile spec: accessModes: - ReadWriteMany storageClassName: azurefile-csi volumeName: azurefile resources: requests: storage: 5GiCreate the PVC using the
kubectl applycommand.kubectl apply -f azurefiles-mount-options-pvc.yamlVerify your PVC is created and bound to the PV using the
kubectl getcommand.kubectl get pvc azurefileYour output should resemble the following example output, which shows that the PVC is in a
Boundstate, and it's bound to the PV named azurefile:NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE azurefile Bound azurefile 5Gi RWX azurefile 5sUpdate your container spec to reference your PVC and your pod in the YAML file. For example:
... volumes: - name: azure persistentVolumeClaim: claimName: azurefileA pod spec can't be updated in place, so delete the pod using the
kubectl deletecommand and recreate it using thekubectl applycommand.kubectl delete pod mypod kubectl apply -f azure-files-pod.yaml
Mount file share as an inline volume
Note
To avoid performance issue, we recommend you use a persistent volume instead of an inline volume when numerous pods are accessing the same file share. Inline volume can only access secrets in the same namespace as the pod. To specify a different secret namespace, use a persistent volume.
To mount the Azure Files file share into your pod, you configure the volume in the container spec.
Create a new file named
azure-files-pod.yamland copy in the following contents. If you changed the name of the file share or secret name, update theshareNameandsecretName. You can also update themountPath, which is the path where the Files share is mounted in the pod. For Windows Server containers, specify amountPathusing the Windows path convention, such as 'D:'.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 readOnly: false volumes: - name: azure csi: driver: file.csi.azure.com volumeAttributes: secretName: azure-secret # required shareName: aksshare # required mountOptions: 'dir_mode=0777,file_mode=0777,cache=strict,actimeo=30,nosharesock,nobrl' # optionalCreate the pod using the
kubectl applycommand.kubectl apply -f azure-files-pod.yamlView the status of the pod using the
kubectl describecommand:kubectl describe pod mypod