Use Azure Files Storage

You can provide persistent storage for MKE workloads on Microsoft Azure by using Azure Files. You can either pre-provision Azure Files shares to be consumed by Kubernetes Pods, or you can use the Azure Kubernetes integration to dynamically provision Azure Files shares as needed.

This guide assumes that you have already provisioned an MKE environment on Microsoft Azure and that you have provisioned a cluster after meeting all of the prerequisites listed in Install MKE on Azure.

To complete the steps in this topic, you must download and configure the client bundle.

Manually provision Azure Files shares

You can use existing Azure Files shares or manually provision new ones to provide persistent storage for Kubernetes Pods. You can manually provision Azure Files shares in the Azure Portal, using ARM Templates, or using the Azure CLI. The following example uses the Azure CLI to manually provision an Azure Files share.


To manually provision an Azure Files share:

Note

The Azure Kubernetes driver does not support Azure Storage accounts created using Azure Premium Storage.

  1. Create an Azure Storage account:

    1. Create the following environment variables, replacing <region> with the required region:

      REGION=<region>
      SA=mystorageaccount
      RG=myresourcegroup
      
    2. Create the Azure Storage account:

      az storage account create \
      --name $SA \
      --resource-group $RG \
      --location $REGION \
      --sku Standard_LRS
      
  2. Provision an Azure Files share:

    1. Create the following environment variables, adjusting the size of this share to satisfy the user requirements.

      FS=myfileshare
      SIZE=5
      
    2. Obtain the Azure collection string, which you can also obtain from the Azure Portal:

      export AZURE_STORAGE_CONNECTION_STRING=`az storage account show-connection-string --name $SA --resource-group $RG -o tsv`
      
    3. Provision the Azure Files share:

      az storage share create \
      --name $FS \
      --quota $SIZE \
      --connection-string $AZURE_STORAGE_CONNECTION_STRING
      

To configure a Kubernetes Secret:

After creating an Azure Files share, you must load the Azure Storage account access key into MKE as a Kubernetes Secret. This provides access to the file share when Kubernetes attempts to mount the share into a Pod. You can find this Secret either in the Azure Portal or by using the Azure CLI, as in the following example.

  1. Create the following environment variables, if you have not done so already:

    SA=mystorageaccount
    RG=myresourcegroup
    FS=myfileshare
    
  2. Obtain the Azure Storage account access key, which you can also obtain from the Azure Portal:

    STORAGE_KEY=$(az storage account keys list --resource-group $RG --account-name $SA --query "[0].value" -o tsv)
    
  3. Load the Azure Storage account access key into MKE as a Kubernetes Secret:

    kubectl create secret generic azure-secret \
    --from-literal=azurestorageaccountname=$SA \
    --from-literal=azurestorageaccountkey=$STORAGE_KEY
    

To mount the Azure Files share into a Kubernetes Pod:

The following example creates a standalone Kubernetes Pod, though you can use the same syntax to create DaemonSets, Deployments, and StatefulSets.

  1. Create the following environment variable:

    FS=myfileshare
    
  2. Mount the Azure Files share into a Kubernetes Pod:

    cat <<EOF | kubectl create -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: mypod-azurefile
    spec:
      containers:
      - image: nginx
        name: mypod
        volumeMounts:
          - name: mystorage
            mountPath: /data
      volumes:
      - name: mystorage
        azureFile:
          secretName: azure-secret
          shareName: $FS
          readOnly: false
    EOF
    

Dynamically provision Azure Files shares

Kubernetes can dynamically provision Azure Files shares using the Azure Kubernetes integration, configured at the time of your MKE installation. For Kubernetes to determine which APIs to use when provisioning storage, you must create Kubernetes StorageClass objects specific to each storage back end.

Note

The Azure Kubernetes plugin only supports using the Standard StorageClass. File shares that use the Premium StorageClass will fail to mount.

To define the Azure Files StorageClass:

  1. Create the storage class:

    cat <<EOF | kubectl create -f -
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: standard
    provisioner: kubernetes.io/azure-file
    mountOptions:
      - dir_mode=0777
      - file_mode=0777
      - uid=1000
      - gid=1000
    parameters:
      skuName: Standard_LRS
      storageAccount: <existingstorageaccount> # Optional
      location: <existingstorageaccountlocation> # Optional
    EOF
    
  2. Verify which storage classes have been provisioned:

    kubectl get storageclasses
    

    Example output:

    NAME       PROVISIONER                AGE
    azurefile  kubernetes.io/azure-file   1m
    

To create an Azure Files share using a PersistentVolumeClaim:

After you create a storage class, you can use Kubernetes Objects to dynamically provision Azure Files shares. This is done using Kubernetes PersistentVolumesClaims.

Kubernetes uses an existing Azure Storage account, if one exists inside of the Azure Resource Group. If an Azure Storage account does not exist, Kubernetes creates one.

The following example uses the standard storage class and creates a 5 Gi Azure File share. Alter these values to fit your use case.

  1. Create a PersistentVolumeClaim:

    cat <<EOF | kubectl create -f -
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: azure-file-pvc
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: standard
      resources:
        requests:
          storage: 5Gi
    EOF
    
  2. Verify the creation of the PersistentVolumeClaim:

    kubectl get pvc
    

    Example output:

    NAME             STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    azure-file-pvc   Bound     pvc-f7ccebf0-70e0-11e9-8d0a-0242ac110007   5Gi        RWX            standard       22s
    
  3. Verify the creation of the PerstentVolume:

    kubectl get pv
    

    Example output:

    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                    STORAGECLASS   REASON    AGE
    pvc-f7ccebf0-70e0-11e9-8d0a-0242ac110007   5Gi        RWX            Delete           Bound     default/azure-file-pvc   standard                 2m
    

To attach the new Azure Files share to a Kubernetes Pod:

You can now mount the Kubernetes PersistentVolume into a Kubernetes Pod. The file share can be consumed by any Kubernetes object type, including a Deployment, DaemonSet, or StatefulSet. However, the following example simply mounts the PersistentVolume into a standalone Pod.

Attach the new Azure Files share to a Kubernetes Pod:

cat <<EOF | kubectl create -f -
kind: Pod
apiVersion: v1
metadata:
  name: mypod
spec:
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: storage
  volumes:
    - name: storage
      persistentVolumeClaim:
       claimName: azure-file-pvc
EOF

Troubleshoot Azure Files shares

When creating a PersistentVolumeClaim, the volume can get stuck in a Pending state if the persistent-volume-binder service account does not have the relevant Kubernetes RBAC permissions.


To resolve this issue:

  1. Review the status of the PVC:

    kubectl get pvc
    

    Example output:

    NAME             STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    azure-file-pvc   Pending                                      standard       32s
    
  2. Describe the PVC:

    kubectl describe pvc azure-file-pvc
    

    The storage account creates a Kubernetes Secret to store the Azure Files storage account key. If the persistent-volume-binder service account does not have the correct permissions, a warning such as the following will display:

    Warning    ProvisioningFailed  7s (x3 over 37s)  persistentvolume-controller
    Failed to provision volume with StorageClass "standard": Couldn't create secret
    secrets is forbidden: User "system:serviceaccount:kube-system:persistent-volume-binder"
    cannot create resource "secrets" in API group "" in the namespace "default": access denied
    
  3. Grant the persistent-volume-binder service account the relevant RBAC permissions by creating the following RBAC ClusterRole:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      labels:
        subjectName: kube-system-persistent-volume-binder
      name: kube-system-persistent-volume-binder:cluster-admin
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: persistent-volume-binder
      namespace: kube-system
    

See also