使用云盘静态存储卷

云盘存储卷适用于非共享数据,I/O和延迟要求较高的应用场景。对于已有云盘,您可以通过静态存储卷的方式挂载到Pod上,以此满足持久化存储需求。本文介绍如何使用云盘静态存储卷,并验证云盘的持久化存储。

使用场景

云盘适用于以下存储场景:

  • 对磁盘I/O要求高的应用,且没有共享数据的需求,如MySQL、Redis等数据存储服务。

  • 高速写日志。

  • 持久化存储数据,不会因Pod生命周期的结束而消失。

如果您已有云盘,可采用静态存储卷的方式为Pod挂载云盘。该方式需要手动创建PV(存储卷)和PVC(存储声明),可以保证PV在容器启动前已经就绪。更多信息,请参见云盘存储卷

前提条件

  • 集群中已安装CSI组件。

    说明
    • 您可以在集群管理页的左侧导航栏选择运维管理 > 组件管理,在存储页签下确认csi-plugincsi-provisioner组件的安装情况。如需升级CSI组件来享受某些特定能力,请参见升级csi-plugincsi-provisioner

    • 如果您的集群目前使用Flexvolume组件,由于Flexvolume已废弃,请先迁移到CSI组件。具体操作,请参见迁移FlexvolumeCSI

  • 待挂载的云盘满足以下要求。

    • 云盘的计费方式为按量付费,状态为待挂载

    • 云盘与ECS节点处于同一可用区,且云盘类型与ECS实例规格相匹配。

      重要

      云盘不支持跨可用区挂载,且某些类型的云盘不支持挂载到某些规格的ECS实例,因此需要确保待挂载云盘的Pod所调度到的ECS节点的可用区和规格能够和已有云盘相匹配,否则云盘会挂载失败。关于云盘类型和ECS实例规格的匹配关系,请参见实例规格族

注意事项

  • 云盘为非共享存储,未开启多重挂载的云盘只能同时被一个Pod挂载。关于多重挂载更多信息,请参见使用NVMe云盘多重挂载及Reservation

  • 云盘只能挂载到相同可用区的Pod上,不支持跨可用区挂载。

  • Pod重建时会重新挂载原有云盘,如果由于其他限制导致Pod无法调度到原可用区,则Pod会因为无法挂载云盘而一直处于Pending状态。

  • 推荐使用StatefulSet挂载云盘或者单独为Pod挂载云盘,不推荐使用Deployment。

    说明

    未开启多重挂载时,一个云盘只能挂载到一个Pod上,为Deployment挂载云盘时,Replica必须配置为1,即无法为每个Pod配置独立的存储卷,并且不能保证挂载、卸载的优先顺序。此外,由于Deployment的升级策略,重启Pod时,新的Pod可能会一直无法挂载云盘。因此不推荐为Deployment挂载云盘。

  • 使用云盘存储卷时,如果在应用的YAML中配置了securityContext.fsgroup,在挂载完成后,kubelet会执行chmodchown操作,导致挂载时间延长。

    说明

    配置了securityContext.fsgroup后,挂载云盘时会自动调整卷内文件的所有者,根据文件数量,这可能导致较长的准备时间。对于1.20及以上版本的Kubernetes集群,您可以将fsGroupChangePolicy配置为OnRootMismatch,实现仅在首次启动容器时才会调整文件的所有者,后续Pod升级或重建等场景下,挂载时长会恢复正常。若仍不能满足需求,建议利用initContainer自行实现调整权限相关操作。

挂载云盘静态存储卷(kubectl)

步骤一:创建PV

  1. 连接集群。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群CloudShell上通过kubectl管理Kubernetes集群

  2. 修改以下YAML内容,并保存为disk-pv.yaml。

    请替换YAML中的如下内容:

    • <YOUR-DISK-ID>:已有云盘ID,例如d-uf628m33r5rsbi******

    • <YOUR-DISK-SIZE>:已有云盘的大小,例如20Gi

    • <YOUR-DISK-ZONE-ID>:已有云盘所在的可用区,例如cn-shanghai-f

    • <YOUR-DISK-CATEGORY>:已有云盘的类型,例如cloud_essd

      各类型云盘的取值如下:

      • ESSD Entry云盘:cloud_essd_entry

      • ESSD AutoPL云盘:cloud_auto

      • ESSD云盘:cloud_essd

      • SSD云盘:cloud_ssd

      • 高效云盘:cloud_efficiency

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: "<YOUR-DISK-ID>"
      annotations:
        csi.alibabacloud.com/volume-topology: '{"nodeSelectorTerms":[{"matchExpressions":[{"key":"node.csi.alibabacloud.com/disktype.<YOUR-DISK-CATEGORY>","operator":"In","values":["available"]}]}]}'
    spec:
      capacity:
        storage: "<YOUR-DISK-SIZE>"
      claimRef:
        apiVersion: v1
        kind: PersistentVolumeClaim
        namespace: default
        name: disk-pvc
      accessModes:
        - ReadWriteOnce
      persistentVolumeReclaimPolicy: Retain
      csi:
        driver: diskplugin.csi.alibabacloud.com
        volumeHandle: "<YOUR-DISK-ID>"
      nodeAffinity:
        required:
          nodeSelectorTerms:
          - matchExpressions:
            - key: topology.diskplugin.csi.alibabacloud.com/zone
              operator: In
              values:
              - "<YOUR-DISK-ZONE-ID>"
      storageClassName: alicloud-disk-topology-alltype
      volumeMode: Filesystem

    相关参数说明如下:

    参数

    说明

    csi.alibabacloud.com/volume-topology

    注解。用于配置成功挂载该云盘所需的额外节点约束。推荐填写云盘类型,以确保Pod调度到支持该类型云盘的ECS节点。

    claimRef

    指定PV所能绑定的PVC。如果希望PV可被任意PVC绑定,请删除该配置。

    accessModes

    访问模式。仅支持ReadWriteOnce,表示卷只能被一个Pod以读写方式挂载。

    persistentVolumeReclaimPolicy

    PV的回收策略。

    • Delete:删除PVC时,PV和云盘会一起删除。

    • Retain:删除PVC时,PV和云盘不会被删除,需要您手动删除。

    driver

    取值为diskplugin.csi.alibabacloud.com,表示使用阿里云云盘CSI插件。

    nodeAffinity

    节点亲和性配置。由于云盘不支持跨可用区挂载,通过该配置可以保证Pod调度到云盘所在可用区对应的ECS节点。

    storageClassName

    该配置对静态卷无意义,无需预先创建对应的StorageClass,但需要确保PVPVC中的该配置项取值保持一致。

  3. 创建PV。

    kubectl create -f disk-pv.yaml
  4. 查看PV。

    kubectl get pv

    预期返回:

    NAME                     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM              STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
    d-uf628m33r5rsbi******   20Gi       RWO            Retain           Available   default/disk-pvc   disk           <unset>                          1m36s

步骤二:创建PVC

  1. 将以下YAML内容保存为disk-pvc.yaml。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: disk-pvc
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: "<YOUR-DISK-SIZE>"
      storageClassName: alicloud-disk-topology-alltype
      volumeName: "<YOUR-DISK-ID>"

    相关参数说明如下:

    参数

    说明

    accessModes

    访问模式。仅支持ReadWriteOnce,表示卷只能被一个Pod以读写方式挂载。

    storage

    分配给Pod的存储容量。设置的值不能超过云盘本身容量。

    storageClassName

    该配置对静态卷无意义,无需预先创建对应的StorageClass,但需要确保PVPVC中的该配置项取值保持一致。

    volumeName

    指定PVC所能绑定的PV。如果希望PVC可绑定任意PV,请删除该参数。

  2. 创建PVC。

    kubectl create -f disk-pvc.yaml
  3. 查看PVC。

    kubectl get pvc

    预期返回如下,可以看到PVC已关联云盘PV。

    NAME       STATUS   VOLUME                   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
    disk-pvc   Bound    d-uf628m33r5rsbi******   20Gi       RWO            disk           <unset>                 64s

步骤三:创建应用并挂载云盘

  1. 使用以下YAML内容,创建disk-test.yaml文件。

    以下YAML示例可以创建包含1PodStatefulSet,Pod通过名为disk-pvcPVC申请存储资源,挂载路径为/data

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: disk-test
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6
            ports:
            - containerPort: 80
            volumeMounts:
            - name: pvc-disk
              mountPath: /data
          volumes:
            - name: pvc-disk
              persistentVolumeClaim:
                claimName: disk-pvc
  2. 创建StatefulSet并挂载云盘。

    kubectl create -f disk-test.yaml
  3. 查看StatefulSetPod的部署情况。

    kubectl get pod -l app=nginx

    预期返回如下,示例使用的StatefulSet副本数为1,因此创建了一个Pod。

    NAME          READY   STATUS    RESTARTS   AGE
    disk-test-0   1/1     Running   0          14s
  4. 查看挂载路径,确认已挂载云盘。

    kubectl exec disk-test-0 -- df -h /data

    预期返回:

    Filesystem      Size  Used Avail Use% Mounted on
    /dev/vdb         20G   24K   20G   1% /data

挂载云盘静态存储卷(控制台)

步骤一:创建存储卷(PV)

  1. 登录容器服务管理控制台,在左侧导航栏选择集群列表

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择存储 > 存储卷

  3. 存储卷页面,单击创建

  4. 在弹出的对话框中,完成参数配置,然后单击创建

    参数

    描述

    示例

    存储卷类型

    选择云盘

    云盘

    访问模式

    仅支持ReadWriteOnce

    ReadWriteOnce

    云盘ID

    单击选择云盘,选择与节点处于同一地域可用区下的待挂载的云盘。

    d-uf628m33r5rsbi******

    文件系统类型

    选择以何种数据类型将数据存储到云盘上,支持的类型包括ext4ext3xfsvfat。默认为ext4

    ext4

    创建完成后,在存储卷页面可以看到新创建的PV。

步骤二:创建存储声明(PVC)

  1. 在集群管理页左侧导航栏,选择存储 > 存储声明

  2. 存储声明页面,单击创建

  3. 在弹出的对话框中,完成参数配置,然后单击创建

    参数

    描述

    示例

    存储声明类型

    选择云盘

    云盘

    名称

    PVC名称,自定义输入。格式要求请参考界面提示。

    diks-pvc

    分配模式

    选择已有存储卷

    已有存储卷

    已有存储卷

    选择步骤一创建的存储卷。

    d-uf690053kttkprgx****, 20Gi

    总量

    分配给Pod的存储容量。设置的值不能超过云盘本身容量。

    20Gi

    创建完成后,在存储声明页面可以看到新创建的PVC,该PVC已绑定PV(即云盘存储卷)。

步骤三:创建应用并挂载云盘

  1. 在集群管理页左侧导航栏,选择工作负载 > 有状态

  2. 有状态页面,单击使用镜像创建

  3. 完成StatefulSet的参数配置,单击创建

    需要注意的参数如下,其他参数按需设置。更多信息,请参见创建有状态工作负载StatefulSet

    配置页

    参数

    描述

    示例

    应用基本信息

    应用名称

    StatefulSet名称,自定义输入。格式要求请参考界面提示。

    disk-test

    副本数量

    配置StatefulSet的副本数量。

    1

    容器配置

    镜像名称

    输入用于部署应用的镜像地址。

    anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6

    所需资源

    设置所需的vCPU、内存和临时存储资源。

    • CPU:0.25 Core

    • 内存:512 MiB

    • Ephemeral-Storage:不设置

    数据卷

    单击增加云存储声明,然后完成参数配置。

    • 挂载源:选择步骤二创建的PVC。

    • 容器路径:输入云盘要挂载到的容器路径。

    • 挂载源:disk-pvc

    • 容器路径:/data

  4. 查看应用部署情况。

    1. 有状态页面,单击应用名称。

    2. 容器组页签下,确认Pod已正常运行(状态为Running)。

验证云盘的持久化存储(kubectl)

按照上文示例创建的StatefulSet中含有1Pod,该Pod挂载了一个云盘。当该Pod被删除时,自动创建的新Pod将重新挂载之前的云盘,云盘中的数据仍然保留。您可以通过以下方式验证云盘的持久化存储。

  1. 查看挂载路径,即查看云盘中的数据。

    kubectl exec disk-test-0 -- ls /data

    预期返回:

    lost+found
  2. 在云盘中写入文件。

    kubectl exec disk-test-0 -- touch /data/test
  3. 删除Pod。

    kubectl delete pod disk-test-0
    说明

    删除StatefulSet中的Pod后,系统会自动创建一个新的Pod。

  4. 查看新创建的Pod。

    kubectl get pod -l app=nginx

    预期返回如下,由于StatefulSet的命名特性,新创建的Pod和之前的Pod名称一致。

    NAME          READY   STATUS    RESTARTS   AGE
    disk-test-0   1/1     Running   0          27s
  5. 确认新创建的Pod已重新挂载云盘,云盘中的数据仍然存在。

    kubectl exec disk-test-0 -- ls /data

    预期返回如下,可以看到云盘中存在之前写入的test文件。

    lost+found  
    test

相关文档