在 Azure Kubernetes 服务 (AKS) 中通过 Azure 文件存储创建并使用卷

永久性卷表示已经过预配可以用于 Kubernetes Pod 的存储块。 永久性卷可供一个或多个 Pod 使用,并可动态或静态预配。 如果多个 Pod 需要同时访问同一存储卷,则可以使用 Azure 文件存储通过服务器消息块 (SMB) 协议进行连接。 本文介绍如何动态创建 Azure 文件共享以供 Azure Kubernetes 服务 (AKS) 群集中的多个 Pod 使用。

本文介绍如何:

  • 通过安装容器存储接口 (CSI) 驱动程序并动态创建一个或多个要附加到 Pod 的 Azure 文件共享来使用动态永久性卷 (PV)。
  • 通过创建一个或多个 Azure 文件共享来使用静态 PV,或者使用现有 Azure 文件共享并将其附加到 Pod。

有关 Kubernetes 卷的详细信息,请参阅 AKS 中应用程序的存储选项

准备阶段

  • 需要一个 Azure 存储帐户
  • 确保已安装且已配置 Azure CLI 版本 2.0.59。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI
  • 在标准文件共享和高级文件共享之间进行选择时,请务必了解计划针对 Azure 文件存储运行的预期使用模式的预配模型和要求。 有关详细信息,请参阅根据使用模式选择 Azure 文件存储性能层

动态预配卷

本部分为想要预配一个或多个永久性卷的群集管理员提供指导,这些卷中包含 Azure 文件存储上的一个或多个共享的详细信息。 永久性卷声明 (PVC) 使用存储类对象来动态预配 Azure 文件存储文件共享。

动态 PersistentVolume 的存储类参数

下表包含可用于为 PersistentVolumeClaim 定义自定义存储类的参数。

名称 含义 可用值 必需 默认值
accountAccessTier 存储帐户的访问层 标准帐户可以选择 HotCool,高级帐户只能选择 Premium 空白。 对不同的存储帐户类型使用默认设置。
accountQuota 限制帐户的配额。 可以 GB 为单位指定最大配额(默认值为 102400GB)。 如果帐户超过指定的配额,驱动程序将跳过选择该帐户的步骤。 102400
allowBlobPublicAccess 允许或禁止公共访问驱动程序创建的存储帐户的所有 Blob 或容器。 truefalse false
disableDeleteRetentionPolicy 指定是否为驱动程序创建的存储帐户禁用 DeleteRetentionPolicy。 truefalse false
enableLargeFileShares 指定是否使用启用了大文件共享的存储帐户。 如果此标志设置为 true,并且没有启用了大文件共享的存储帐户,则会创建一个启用了大文件共享的新存储帐户。 此标志应与标准 sku 一起使用,因为使用高级 sku 创建的存储帐户默认启用 largeFileShares 选项。 truefalse false
folderName 在 Azure 文件共享中指定文件夹名称。 Azure 文件共享中的现有文件夹名称。 如果文件共享中不存在文件夹名称,则装载失败。
getLatestAccount 确定是否根据创建时间获取最新的帐户密钥。 默认情况下,此驱动程序将获取第一个密钥。 truefalse false
location 指定 Azure 存储帐户的 Azure 区域。 例如,eastus 如果为空,驱动程序将使用与当前 AKS 群集相同的位置名称。
matchTags 驱动程序尝试查找合适的存储帐户时匹配标记。 truefalse false
networkEndpointType 为驱动程序创建的存储帐户指定网络终结点类型。 如果指定 privateEndpoint,则为存储帐户创建专用终结点。 对于其他情况,默认创建服务终结点。 "",privateEndpoint ""
protocol 指定文件共享协议。 smbnfs smb
requireInfraEncryption 指定服务是否使用平台托管密钥为驱动程序创建的存储帐户的静态数据应用第二层加密。 truefalse false
resourceGroup 指定 Azure 磁盘的资源组。 现有资源组名称 如果为空,驱动程序将使用与当前 AKS 群集相同的资源组名称。
selectRandomMatchingAccount 确定是否随机选择匹配帐户。 默认情况下,驱动程序始终按字母顺序选择第一个匹配的帐户(注意:此驱动程序使用帐户搜索缓存,这会导致多个帐户之间的文件创建分布不均匀)。 truefalse false
server 指定 Azure 存储帐户服务器地址。 现有服务器地址,例如 accountname.privatelink.file.core.chinacloudapi.cn 如果为空,驱动程序使用默认的 accountname.file.core.chinacloudapi.cn 或其他主权云帐户地址。
shareAccessTier 文件共享的访问层 常规用途 v2 帐户可以在 TransactionOptimized(默认)、HotCool 之间进行选择。 仅适用于文件共享的高级存储帐户类型。 空白。 对不同的存储帐户类型使用默认设置。
shareName 指定 Azure 文件共享名称。 现有或新的 Azure 文件共享名称。 如果为空,驱动程序将生成一个 Azure 文件共享名称。
shareNamePrefix 指定由驱动程序创建的 Azure 文件共享名称前缀。 共享名只能包含小写字母、数字、连字符,长度应少于 21 个字符。
skuName Azure 文件存储存储帐户类型(别名:storageAccountType Standard_LRSStandard_ZRSStandard_GRSStandard_RAGRSStandard_RAGZRS,Premium_LRSPremium_ZRS StandardSSD_LRS
高级帐户类型的最小文件共享大小为 100 GB。
ZRS 帐户类型在有限区域内受支持。
NFS 文件共享仅支持高级帐户类型。
storageAccount 指定 Azure 存储帐户名称。 storageAccountName 否- 如果未提供特定的存储帐户名称,驱动程序将查找与同一资源组中的帐户设置匹配的合适存储帐户。 如果驱动程序找不到匹配的存储帐户,则将创建新的存储帐户。 但是,如果指定了存储帐户名称,则存储帐户必须已经存在。
storageEndpointSuffix 指定 Azure 存储终结点后缀。 core.chinacloudapi.cncore.chinacloudapi.cn 如果为空,驱动程序将根据云环境使用默认存储终结点后缀。 例如 core.chinacloudapi.cn
标记 标记是在新的存储帐户中创建的。 标记格式:“foo=aaa,bar=bbb” ""
--- 以下参数仅适用于 SMB 协议 --- ---
subscriptionID 指定在其中创建 Azure 文件共享的 Azure 订阅 ID。 Azure 订阅 ID 如果不为空,则必须提供 resourceGroup
storeAccountKey 指定是否将帐户密钥存储到 Kubernetes 机密。 truefalse
false 表示驱动程序使用 kubelet 标识获取帐户密钥。
true
secretName 指定用于存储帐户密钥的机密名称。
secretNamespace 指定用于存储帐户密钥的机密的命名空间。

注意:
如果未指定 secretNamespace,则会在 Pod 所在的同一命名空间中创建机密。
defaultkube-system 等。 PVC 命名空间,例如 csi.storage.k8s.io/pvc/namespace
useDataPlaneAPI 指定是否使用数据平面 API进行文件共享的创建/删除/调整大小,这可以解决 SRP API 限制问题,因为数据平面 API 几乎没有限制,当存储帐户上存在防火墙或 Vnet 设置,将会失败。 truefalse false
--- 以下参数仅适用于 NFS 协议 --- ---
mountPermissions 装载的文件夹权限。 默认为 0777。 如果设置为 0,则驱动程序在装载后不会执行 chmod 0777
rootSquashType 指定共享上的根压缩行为。 默认值为 NoRootSquash AllSquashNoRootSquashRootSquash
--- 以下参数仅适用于 VNet 设置。 例如,NFS、专用终结点 --- ---
fsGroupChangePolicy 指示驱动程序如何更改卷的所有权。 Pod securityContext.fsGroupChangePolicy 将被忽略。 OnRootMismatch(默认)、AlwaysNone OnRootMismatch
subnetName 子网名称 代理节点的现有子网名称。 如果为空,驱动程序将使用 Azure 云配置文件中的 subnetName 值。
vnetName 虚拟网络名称 现有虚拟网络名称。 如果为空,驱动程序将使用 Azure 云配置文件中的 vnetName 值。
vnetResourceGroup 指定在其中定义虚拟网络的 VNet 资源组。 现有资源组名称。 如果为空,驱动程序将使用 Azure 云配置文件中的 vnetResourceGroup 值。

创建存储类

存储类定义如何创建 Azure 文件共享。 系统会在节点资源组中自动创建一个存储帐户,以便与存储类一起用来保存 Azure 文件存储文件共享。 为 skuName 选择以下 Azure 存储冗余 SKU 之一

  • Standard_LRS:标准本地冗余存储 (LRS)
  • Standard_GRS:标准异地冗余存储 (GRS)
  • Standard_ZRS:标准区域冗余存储 (ZRS)
  • Standard_RAGRS:标准读取访问异地冗余存储 (RA-GRS)

注意

最小的高级文件共享为 100 GB。

有关 Azure 文件存储的 Kubernetes 存储类的详细信息,请参阅 Kubernetes 存储类

  1. 创建名为 azure-file-sc.yaml 的文件,并将其复制到以下示例清单中。 有关 mountOptions 的详细信息,请参阅装载选项部分。

    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
    
  2. 使用 kubectl apply 命令创建存储类。

    kubectl apply -f azure-file-sc.yaml
    

创建永久性卷声明

永久性卷声明 (PVC) 使用存储类对象来动态预配 Azure 文件共享。 可以使用以下 YAML 创建大小为 100 GB、访问权限为 ReadWriteMany 的永久性卷声明。 有关访问模式的详细信息,请参阅 Kubernetes 永久性卷

  1. 创建名为 azure-file-pvc.yaml 的文件,并将其复制到以下 YAML 中。 请确保 storageClassName 与上一步骤中创建的存储类匹配。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-azurefile
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: my-azurefile
      resources:
        requests:
          storage: 100Gi
    

    注意

    如果将 Premium_LRS SKU 用于存储类,则 storage 最小值必须为 100Gi

  2. 使用 kubectl apply 命令创建永久性卷声明。

    kubectl apply -f azure-file-pvc.yaml
    

    完成此步骤后,文件共享即创建完毕。 同时还会创建一个包含连接信息和凭据的 Kubernetes 机密。 可以使用 kubectl get 命令查看 PVC 的状态:

    kubectl get pvc my-azurefile
    

    该命令的输出类似于以下示例:

    NAME           STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
    my-azurefile   Bound     pvc-8436e62e-a0d9-11e5-8521-5a8664dc0477   100Gi       RWX            my-azurefile      5m
    

使用永久性卷

以下 YAML 创建的 Pod 使用永久性卷声明 my-azurefile 将 Azure 文件存储文件共享装载到 /mnt/azure 路径。 对于 Windows Server 容器,请使用 Windows 路径约定指定 mountPath,例如“D:”

  1. 创建名为 azure-pvc-files.yaml 的文件,并将其复制到以下 YAML 中。 请确保 claimName 与上一步骤中创建的 PVC 匹配。

    kind: Pod
    apiVersion: v1
    metadata:
      name: mypod
    spec:
      containers:
        - name: mypod
          image: mcr.azk8s.cn/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-azurefile
    
  2. 使用 kubectl apply 命令创建 Pod。

    kubectl apply -f azure-pvc-files.yaml
    

    现有一个正在运行的 Pod,其中的 Azure 文件存储文件共享已装载到 /mnt/azure 目录中。 使用 kubectl describe 命令检查 Pod 时,可以看到此配置。 以下精简示例输出显示容器中装载的卷。

    Containers:
      mypod:
        Container ID:   docker://053bc9c0df72232d755aa040bfba8b533fa696b123876108dec400e364d2523e
        Image:          mcr.azk8s.cn/oss/nginx/nginx:1.15.5-alpine
        Image ID:       docker-pullable://nginx@sha256:d85914d547a6c92faa39ce7058bd7529baacab7e0cd4255442b04577c4d1f424
        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
    [...]
    

装载选项

对于 Kubernetes 版本 1.13.0 及更高版本,fileModedirMode 的默认值为 0777。 如果使用存储类动态创建永久性卷,则可以在存储类对象上指定装载选项。 有关详细信息,请参阅装载选项。 以下示例设置 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

使用 Azure 标记

有关使用 Azure 标记的详细信息,请参阅在 Azure Kubernetes 服务 (AKS) 中使用 Azure 标记

静态预配卷

本部分为想要创建一个或多个永久性卷的群集管理员提供指导,其中包含供工作负载使用的现有 Azure 文件存储共享的详细信息。

PersistentVolume 的静态预配参数

下表包含可用于定义 PersistentVolume 的参数。

名称 含义 可用值 必需 默认值
volumeAttributes.resourceGroup 指定 Azure 资源组名称。 myResourceGroup 如果为空,驱动程序将使用与当前群集相同的资源组名称。
volumeAttributes.storageAccount 指定现有的 Azure 存储帐户名称。 storageAccountName
volumeAttributes.shareName 指定 Azure 文件共享名称。 fileShareName
volumeAttributes.folderName 在 Azure 文件共享中指定文件夹名称。 folderName 如果文件共享中不存在文件夹名称,装载将失败。
volumeAttributes.protocol 指定文件共享协议。 smbnfs smb
volumeAttributes.server 指定 Azure 存储帐户服务器地址 现有服务器地址,例如 accountname.privatelink.file.core.chinacloudapi.cn 如果为空,驱动程序使用默认的 accountname.file.core.chinacloudapi.cn 或其他主权云帐户地址。
--- 以下参数仅适用于 SMB 协议 --- --- ---
volumeAttributes.secretName 指定用于存储帐户名称和密钥的机密名称。
volumeAttributes.secretNamespace 指定机密命名空间。 defaultkube-system 等。 PVC 命名空间 (csi.storage.k8s.io/pvc/namespace)
nodeStageSecretRef.name 指定用于存储帐户名称和密钥的机密名称。 现有机密名称。 如果为空,驱动程序则使用 kubelet 标识获取帐户密钥。
nodeStageSecretRef.namespace 指定机密命名空间。 Kubernetes 命名空间
--- 以下参数仅适用于 NFS 协议 --- --- ---
volumeAttributes.fsGroupChangePolicy 指示驱动程序如何更改卷的所有权。 Pod securityContext.fsGroupChangePolicy 将被忽略。 OnRootMismatch(默认)、AlwaysNone OnRootMismatch
volumeAttributes.mountPermissions 指定装载的文件夹权限。 默认值为 0777

创建 Azure 文件共享

必须先创建 Azure 存储帐户和文件共享,然后才能将 Azure 文件存储文件共享用作 Kubernetes 卷。

  1. 使用具有 --query nodeResourceGroup 参数的 az aks show 命令获取资源组名称。

    az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv
    

    该命令的输出类似于以下示例:

    MC_myResourceGroup_myAKSCluster_chinaeast2
    
  2. 使用具有 --sku 参数的 az storage account create 命令创建存储帐户。 以下命令使用 Standard_LRS SKU 创建存储帐户。 确保替换以下占位符:

    • myAKSStorageAccount 替换为存储帐户的名称
    • nodeResourceGroupName 替换为托管 AKS 群集节点的资源组的名称
    • location 替换为要在其中创建资源的区域的名称。 它应与 AKS 群集节点为同一区域。
    az storage account create -n myAKSStorageAccount -g nodeResourceGroupName -l location --sku Standard_LRS
    
  3. 使用以下命令将连接字符串导出为环境变量,该命令用于创建文件共享。

    export AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string -n storageAccountName -g resourceGroupName -o tsv)
    
  4. 使用 az storage share create 命令创建文件共享。 确保将 shareName 替换为你的共享名。

    az storage share create -n shareName --connection-string $AZURE_STORAGE_CONNECTION_STRING
    
  5. 运行以下命令,将存储帐户密钥导出为环境变量。

    STORAGE_KEY=$(az storage account keys list --resource-group nodeResourceGroupName --account-name myAKSStorageAccount --query "[0].value" -o tsv)
    
  6. 运行以下命令以回显存储帐户名称和密钥。 复制这些信息,创建 Kubernetes 卷时需要用到这些值。

    echo Storage account key: $STORAGE_KEY
    

创建 Kubernetes 机密

Kubernetes 需要使用凭据访问上一步骤中创建的文件共享。 这些凭据存储在 Kubernetes 机密中,创建 Kubernetes Pod 时将引用它。

  1. 使用 kubectl create secret 命令创建机密。 以下示例创建一个名为 azure-secret 的机密并填充上一步骤中的 azurestorageaccountname 和 azurestorageaccountkey。 若要使用现有 Azure 存储帐户,请提供帐户名称和密钥。

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

将文件共享装载为永久性卷

  1. 新建名为 azurefiles-pv.yaml 的文件,并将以下内容复制到其中。 在 csi 下,更新 resourceGroupvolumeHandleshareName。 对于装载选项,fileModedirMode 的默认值为 0777

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      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:
          resourceGroup: resourceGroupName  # optional, only set this when storage account is not in the same resource group as node
          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 locks
    
  2. 使用 kubectl create 命令创建永久性卷。

    kubectl create -f azurefiles-pv.yaml
    
  3. 新建名为“azurefiles-mount-options-pvc.yaml”的文件,并将以下内容复制到其中。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: azurefile
    spec:
      accessModes:
        - ReadWriteMany
      storageClassName: azurefile-csi
      volumeName: azurefile
      resources:
        requests:
          storage: 5Gi
    
  4. 使用 kubectl apply 命令创建 PersistentVolumeClaim。

    kubectl apply -f azurefiles-mount-options-pvc.yaml
    
  5. 使用 kubectl get 命令验证 PersistentVolumeClaim 是否已创建并绑定到 PersistentVolume。

    kubectl get pvc azurefile
    

    命令的输出如下例所示:

    NAME        STATUS   VOLUME      CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    azurefile   Bound    azurefile   5Gi        RWX            azurefile      5s
    
  6. 更新容器规范以引用 PersistentVolumeClaim 以及 YAML 文件中的 Pod。 例如:

    ...
      volumes:
      - name: azure
        persistentVolumeClaim:
          claimName: azurefile
    
  7. 由于无法就地更新 Pod 规范,因此请使用 kubectl delete 命令删除 Pod,然后使用 kubectl apply 命令重新创建 Pod。

    kubectl delete pod mypod
    
    kubectl apply -f azure-files-pod.yaml
    

装载文件共享作为内联卷

注意

为了避免性能问题,建议在大量 Pod 访问同一文件共享时使用永久性卷而不是内联卷。 内联卷只能访问与 Pod 相同的命名空间中的机密。 若要指定其他机密命名空间,请使用永久性卷

若要将 Azure 文件存储文件共享装载到 Pod 中,请在容器规范中配置卷。

  1. 新建名为 azure-files-pod.yaml 的文件,并将以下内容复制到其中。 如果更改了文件共享名称或机密名称,请更新 shareNamesecretName。 也可以更新 mountPath,这是文件共享在 Pod 中的装载路径。 对于 Windows Server 容器,请使用 Windows 路径约定指定 mountPath,例如“D:”
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  nodeSelector:
    kubernetes.io/os: linux
  containers:
    - image: 'mcr.azk8s.cn/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'  # optional
  1. 使用 kubectl apply 命令创建 Pod。

    kubectl apply -f azure-files-pod.yaml
    

    现在你有一个正在运行的 Pod,其中 Azure 文件存储文件共享装载在 /mnt/azure 处。 可以使用 kubectl describe 命令验证是否已成功装载共享。

    kubectl describe pod mypod
    

后续步骤

有关 Azure 文件存储 CSI 驱动程序参数,请参阅 CSI 驱动程序参数

如需相关的最佳做法,请参阅 AKS 中的存储和备份最佳做法