你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

将 Azure 容器存储与本地 NVMe 配合使用

Azure 容器存储是一项基于云的卷管理、部署和业务流程服务,专为容器原生构建。 本文介绍如何将 Azure 容器存储配置为将临时磁盘与本地 NVMe 用作 Kubernetes 工作负载的后端存储。 最后,你将得到一个使用本地 NVMe 作为其存储的 Pod。

什么是临时磁盘?

当应用程序需要亚毫秒存储延迟且不需要数据持续性时,可以将临时磁盘与 Azure 容器存储配合使用以满足性能要求。 临时意味着磁盘部署在托管 AKS 群集的本地虚拟机 (VM) 上,而不是保存到 Azure 存储服务。 如果停止/解除分配 VM,这些磁盘上的数据将会丢失。

有两种类型的临时磁盘可用:本地 NVMe 和临时 SSD。 NVMe 专为存储和 CPU 之间的高速数据传输而设计。 当应用程序需要比临时 SSD 更高的 IOPS 或吞吐量,或者需要更多的存储空间时,可以选择 NVMe。 请注意,Azure 容器存储仅支持本地 NVMe 的同步数据复制。

由于这些磁盘的临时特性,Azure 容器存储在使用临时磁盘时默认支持使用通用临时卷。 不过,即使数据不具有持久性,某些用例也可能需要持久卷;例如,如果希望使用现有的 YAML 文件或部署模板,而这些文件或模板已硬编码为使用持久卷,并且工作负载支持应用程序级复制以实现持久性,就会出现这种情况。 在这种情况下,可以更新 Azure 容器存储安装,并在持久卷声明定义中添加注释 acstor.azure.com/accept-ephemeral-storage=true,以支持从临时磁盘存储池创建持久卷。

先决条件

  • 如果没有 Azure 订阅,请在开始之前创建一个免费帐户

  • 本文需要 Azure CLI 的最新版本(2.35.0 或更高版本)。 请参阅如何安装 Azure CLI。 如果你在 Azure Cloud Shell 中使用 Bash 环境,则表示已安装最新版本。 如果你打算在本地(而不是 Azure Cloud Shell 中)运行命令,请务必使用管理员权限运行命令。 有关详细信息,请参阅开始使用 Azure Cloud Shell

  • 你将需要 Kubernetes 命令行客户端 kubectl。 如果你使用的是 Azure Cloud Shell,则它已安装,或者可以通过运行 az aks install-cli 命令在本地安装它。

  • 如果尚未安装 Azure 容器存储,请按照将 Azure 容器存储与 Azure Kubernetes 服务配合使用中的说明进行操作。

  • 检查 Azure 容器存储区域是否支持你的目标区域。

选择一个支持本地 NVMe 的 VM 类型

本地 NVMe 磁盘仅在某些类型的 VM 中可用,例如存储优化 VM SKUGPU 加速 VM SKUs。 如果计划使用本地 NVMe 容量,请选择这些 VM SKU 中的一个。

运行以下命令来获取与节点池一起使用的 VM 类型。 将 <resource group><cluster name> 替换为自己的值。 无需为 PoolNameVmSize 提供值,因此请如下所示保留查询。

az aks nodepool list --resource-group <resource group> --cluster-name <cluster name> --query "[].{PoolName:name, VmSize:vmSize}" -o table

下面是输出的示例。

PoolName    VmSize
----------  ---------------
nodepool1   standard_l8s_v3

我们建议每个 VM 至少有四个虚拟 CPU (vCPU),每个节点池至少有三个节点。

创建和附加通用临时卷

按照以下步骤创建并附加通用临时卷。

1.创建存储池

首先,通过在 YAML 清单文件中定义存储池来创建存储池,这是 Kubernetes 群集的存储的逻辑分组。

如果使用 az aks createaz aks update 命令启用 Azure 容器存储,你可能已有存储池。 使用 kubectl get sp -n acstor 获取存储池的列表。 如果已有要使用的存储池,可以跳过本部分,然后转到显示可用的存储类

按照以下步骤使用本地 NVMe 创建存储池。

  1. 使用最喜爱的文本编辑器创建 YAML 清单文件,例如 code acstor-storagepool.yaml

  2. 粘贴以下代码并保存文件。 存储池名称值可以是所需的任何内容。

    apiVersion: containerstorage.azure.com/v1
    kind: StoragePool
    metadata:
      name: ephemeraldisk-nvme
      namespace: acstor
    spec:
      poolType:
        ephemeralDisk:
          diskType: nvme
    
  3. 应用 YAML 清单文件以创建存储池。

    kubectl apply -f acstor-storagepool.yaml 
    

    存储池创建完成后,将会看到如下消息:

    storagepool.containerstorage.azure.com/ephemeraldisk-nvme created
    

    还可以运行此命令来检查存储池的状态。 将 <storage-pool-name> 替换为存储池名称值。 在本示例中,该值为 ephemeraldisk-nvme

    kubectl describe sp <storage-pool-name> -n acstor
    

创建存储池后,Azure 容器存储将使用命名约定 acstor-<storage-pool-name> 代表你创建存储类。

2.显示可用的存储类

当存储池可供使用时,必须选择存储类来定义在创建和部署卷时如何动态创建存储。

运行 kubectl get sc 以显示可用的存储类。 应会看到名为 acstor-<storage-pool-name> 的存储类。

$ kubectl get sc | grep "^acstor-"
acstor-azuredisk-internal   disk.csi.azure.com               Retain          WaitForFirstConsumer   true                   65m
acstor-ephemeraldisk-nvme        containerstorage.csi.azure.com   Delete          WaitForFirstConsumer   true                   2m27s

重要

请勿使用标记为内部的存储类。 它是 Azure 容器存储正常运行所需的内部存储类。

3.使用通用临时卷部署 Pod

使用 Fio(灵活 I/O 测试器)创建 Pod 来进行基准测试和工作负载模拟 - Fio 使用通用临时卷。

  1. 使用最喜爱的文本编辑器创建 YAML 清单文件,例如 code acstor-pod.yaml

  2. 粘贴以下代码并保存文件。

    kind: Pod
    apiVersion: v1
    metadata:
      name: fiopod
    spec:
      nodeSelector:
        acstor.azure.com/io-engine: acstor
      containers:
        - name: fio
          image: nixery.dev/shell/fio
          args:
            - sleep
            - "1000000"
          volumeMounts:
            - mountPath: "/volume"
              name: ephemeralvolume
      volumes:
        - name: ephemeralvolume
          ephemeral:
            volumeClaimTemplate:
              metadata:
                labels:
                  type: my-ephemeral-volume
              spec:
                accessModes: [ "ReadWriteOnce" ]
                storageClassName: acstor-ephemeraldisk-nvme # replace with the name of your storage class if different
                resources:
                  requests:
                    storage: 1Gi
    

    更改卷的存储大小时,请确保该大小应小于单个节点临时磁盘的可用容量。 请参阅检查节点临时磁盘容量

  3. 应用 YAML 清单文件以部署 Pod。

    kubectl apply -f acstor-pod.yaml
    

    应该会看到与下面类似的输出:

    pod/fiopod created
    
  4. 检查 Pod 是否正在运行,以及临时卷声明是否已成功绑定到 Pod:

    kubectl describe pod fiopod
    kubectl describe pvc fiopod-ephemeralvolume
    
  5. 检查 fio 测试以查看其当前状态:

    kubectl exec -it fiopod -- fio --name=benchtest --size=800m --filename=/volume/test --direct=1 --rw=randrw --ioengine=libaio --bs=4k --iodepth=16 --numjobs=8 --time_based --runtime=60
    

现在,你已部署了使用本地 NVMe 作为存储的 Pod,并且可以将其用于 Kubernetes 工作负载。

创建并附加永久性卷

若要从临时磁盘存储池创建持久卷,必须在持久卷声明 (PVC) 中包含注释作为保障措施,以确保即使数据是临时的,你也打算使用持久卷。 此外,在创建持久卷声明之前,需要在群集上启用 --ephemeral-disk-volume-type 标记,并将其设置为 PersistentVolumeWithAnnotation 值。

按照以下步骤创建并附加永久性卷。

1.更新 Azure 容器存储安装

运行以下命令来更新 Azure 容器存储安装,以允许从临时磁盘存储池创建持久卷。

az aks update -n <cluster-name> -g <resource-group> --enable-azure-container-storage ephemeralDisk --storage-pool-option NVMe --ephemeral-disk-volume-type PersistentVolumeWithAnnotation 

2.创建存储池

通过在 YAML 清单文件中定义存储池来创建存储池,这是 Kubernetes 群集的存储的逻辑分组。

如果使用 az aks createaz aks update 命令启用 Azure 容器存储,你可能已有存储池。 使用 kubectl get sp -n acstor 获取存储池的列表。 如果已有要使用的存储池,可以跳过本部分,然后转到显示可用的存储类

按照以下步骤使用本地 NVMe 创建存储池。

  1. 使用最喜爱的文本编辑器创建 YAML 清单文件,例如 code acstor-storagepool.yaml

  2. 粘贴以下代码并保存文件。 存储池名称值可以是所需的任何内容。

    apiVersion: containerstorage.azure.com/v1
    kind: StoragePool
    metadata:
      name: ephemeraldisk-nvme
      namespace: acstor
    spec:
      poolType:
        ephemeralDisk:
          diskType: nvme
    
  3. 应用 YAML 清单文件以创建存储池。

    kubectl apply -f acstor-storagepool.yaml 
    

    存储池创建完成后,将会看到如下消息:

    storagepool.containerstorage.azure.com/ephemeraldisk-nvme created
    

    还可以运行此命令来检查存储池的状态。 将 <storage-pool-name> 替换为存储池名称值。 在本示例中,该值为 ephemeraldisk-nvme

    kubectl describe sp <storage-pool-name> -n acstor
    

创建存储池后,Azure 容器存储将使用命名约定 acstor-<storage-pool-name> 代表你创建存储类。

3.显示可用的存储类

当存储池可供使用时,必须选择存储类来定义在创建和部署卷时如何动态创建存储。

运行 kubectl get sc 以显示可用的存储类。 应会看到名为 acstor-<storage-pool-name> 的存储类。

$ kubectl get sc | grep "^acstor-"
acstor-azuredisk-internal   disk.csi.azure.com               Retain          WaitForFirstConsumer   true                   65m
acstor-ephemeraldisk-nvme        containerstorage.csi.azure.com   Delete          WaitForFirstConsumer   true                   2m27s

重要

请勿使用标记为内部的存储类。 它是 Azure 容器存储正常运行所需的内部存储类。

4.创建永久性卷声明

持久卷声明用于基于存储类自动预配存储。 按照以下步骤使用新的存储类创建 PVC。

  1. 使用最喜爱的文本编辑器创建 YAML 清单文件,例如 code acstor-pvc.yaml

  2. 粘贴以下代码并保存文件。 PVC name 值可以是所需的任何内容。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: ephemeralpvc
      annotations:
        acstor.azure.com/accept-ephemeral-storage: "true"
    spec:
      accessModes:
        - ReadWriteOnce
      storageClassName: acstor-ephemeraldisk-nvme # replace with the name of your storage class if different
      resources:
        requests:
          storage: 100Gi
    

    更改卷的存储大小时,请确保该大小应小于单个节点临时磁盘的可用容量。 请参阅检查节点临时磁盘容量

  3. 应用 YAML 清单文件以创建 PVC。

    kubectl apply -f acstor-pvc.yaml
    

    此时会看到与下面类似的输出:

    persistentvolumeclaim/ephemeralpvc created
    

    可以通过运行以下命令来验证 PVC 的状态:

    kubectl describe pvc ephemeralpvc
    

创建 PVC 后,即可供 Pod 使用。

5.部署 Pod 并附加永久性卷

使用 Fio(灵活 I/O 测试器)创建 Pod 以进行基准测试和工作负载模拟,并为永久性卷指定装载路径。 对于 claimName,可使用创建永久性卷声明时使用的名称值。

  1. 使用最喜爱的文本编辑器创建 YAML 清单文件,例如 code acstor-pod.yaml

  2. 粘贴以下代码并保存文件。

    kind: Pod
    apiVersion: v1
    metadata:
      name: fiopod
    spec:
      nodeSelector:
        acstor.azure.com/io-engine: acstor
      volumes:
        - name: ephemeralpv
          persistentVolumeClaim:
            claimName: ephemeralpvc
      containers:
        - name: fio
          image: nixery.dev/shell/fio
          args:
            - sleep
            - "1000000"
          volumeMounts:
            - mountPath: "/volume"
              name: ephemeralpv
    
  3. 应用 YAML 清单文件以部署 Pod。

    kubectl apply -f acstor-pod.yaml
    

    应该会看到与下面类似的输出:

    pod/fiopod created
    
  4. 检查 Pod 是否正在运行,以及永久性卷声明是否已成功绑定到 Pod:

    kubectl describe pod fiopod
    kubectl describe pvc ephemeralpvc
    
  5. 检查 fio 测试以查看其当前状态:

    kubectl exec -it fiopod -- fio --name=benchtest --size=800m --filename=/volume/test --direct=1 --rw=randrw --ioengine=libaio --bs=4k --iodepth=16 --numjobs=8 --time_based --runtime=60
    

现在,你已部署了使用本地 NVMe 的 Pod,并且可以将其用于 Kubernetes 工作负载。

管理卷和存储池

在本部分中,你将了解如何检查单个节点的临时磁盘的可用容量、如何扩展或删除存储池,以及如何优化性能。

检查节点临时磁盘容量

在单个节点上分配临时卷。 配置临时卷的大小时,大小应小于单个节点临时磁盘的可用容量。

运行以下命令,检查单个节点临时磁盘的可用容量。

$ kubectl get diskpool -n acstor
NAME                                CAPACITY      AVAILABLE     USED        RESERVED    READY   AGE
ephemeraldisk-nvme-diskpool-jaxwb   75660001280   75031990272   628011008   560902144   True    21h
ephemeraldisk-nvme-diskpool-wzixx   75660001280   75031990272   628011008   560902144   True    21h
ephemeraldisk-nvme-diskpool-xbtlj   75660001280   75031990272   628011008   560902144   True    21h

在此示例中,单个节点临时磁盘的可用容量为 75031990272 字节或 69 GiB。

展开存储池

你可以扩展由本地 NVMe 支持的存储池,以实现快速纵向扩展且无需停机。 目前不支持收缩存储池。

由于临时磁盘支持的存储池使用 AKS 群集节点上的本地存储资源 (VM),因此展开存储池需要将另一个节点添加到群集。 按照这些说明展开存储池。

  1. 运行以下命令,将节点添加到 AKS 群集。 将 、 和 替换为自己的值<cluster-name><nodepool name><resource-group-name>。 若要获取节点池的名称,请运行 kubectl get nodes

    az aks nodepool add --cluster-name <cluster name> --name <nodepool name> --resource-group <resource group> --node-vm-size Standard_L8s_v3 --node-count 1 --labels acstor.azure.com/io-engine=acstor
    
  2. 运行 kubectl get nodes,你将看到节点已添加到群集。

  3. 运行 kubectl get sp -A,应看到存储池的容量已增加。

删除存储池

如果要删除存储池,请运行以下命令。 将 <storage-pool-name> 替换为存储池名称。

kubectl delete sp -n acstor <storage-pool-name>

优化使用本地 NVMe 时的性能

根据工作负载的性能要求,可以从三个不同的性能层中进行选择:基本、标准和高级。 你的选择将影响 Azure 容器存储组件在安装节点中使用的 vCPU 数量。 如果不更新性能层,则默认配置是“标准”。

这三个层提供不同的 IOPS 范围。 下表包含有关每个层的预期内容的指导。 我们使用了 FIO(一种常用的基准测试工具),以通过以下配置获得这些数字:

  • AKS:节点 SKU - Standard_L16s_v3;
  • FIO:块大小 - 4KB;队列深度 - 32;Numjobs - 分配给容器存储组件的核心数量;访问模式 - 随机;辅助角色集大小 - 32G
vCPU 的数量 100% 读取 IOPS 100% 写入 IOPS
Basic VM 核心总数的 12.5% 最多 120,000 最多 90,000
Standard(默认值) VM 核心总数的 25% 最多 220,000 最多 180,000
Premium VM 核心总数的 50% 最多 550,000 最多 360,000

注意

RAM 和巨页消耗将在所有层中保持一致:1 GiB 的 RAM 和 2 GiB 的巨页。

确定最符合需求的性能层后,可以运行以下命令来更新 Azure 容器存储安装的性能层。 将 <performance tier> 替换为基本、标准或高级。

az aks update -n <cluster-name> -g <resource-group> --enable-azure-container-storage <storage-pool-type> --ephemeral-disk-nvme-perf-tier <performance-tier>

另请参阅