容器服务 TKE 存储插件与云硬盘 CBS 最佳实践应用

引言

随着自研上云的深入,越来越多的有状态服务对于在 TKE 集群中使用云上存储能力的需求也越来越强烈。

目前 腾讯云容器服务 TKE(Tencent Kubernetes Engine)已支持在 TKE 集群中的应用使用多种存储服务,包括 云硬盘 CBS文件存储 CFS 以及 对象存储 COS。TKE 通过两种存储插件(In-Tree 和 CSI)来支持上述能力,用户可以通过云控制台很方便地选择存储类型并创建对应的 PV/PVC。但仍然会有一些问题困扰着大家,比如:TKE 集群中是否支持扩容 CBS 云盘;如果集群跨可用区,如何避免集群中频繁出现挂载(attach)失败;TKE 中是否支持快照功能;我的应用应该选择哪种类型存储;In-Tree 和 CSI 都支持 CBS,二者有和区别,是否能把之前使用 In-Tree 插件创建的云盘转变为 CSI 插件管理等。

对于 TKE 存储的相关问题,这里会详细介绍。接下来,我们先概览下 Kubernetes 持久化存储的流程

Kubernetes 持久化存储流程

这里对 Kubernetes 持久化存储的流程做个概览,不深入各个组件。

创建一个使用了持久化存储的 pod 的流程包含以下步骤:

  1. 用户创建一个引用PVC的 pod(动态创建PV);
  2. Scheduler根据 pod 的配置、节点状态、PV 配置等其他因素把 pod 调度到一个合适的 node 上;
  3. PV Controller watch 到 PVC,调用 Volume Plugin 去创建 PV,并绑定 PV 和 PVC。如果是 out-of-tree 存储插件(如 CSI),则创建 PV 实际是由 external provisioner 完成,之后 PV Controller 完成 PV 和 PVC 的bound;如果是 in-tree 插件,但是通过kubernetes-sigs/sig-storage-lib-external-provisioner实现了一个 external provisioner,则与 out-of-tree 插件相同;如果是 in-tree 插件,且插件直接实现了相应的创删接口,则 PV Controller 直接调用 in-tree 插件的实现完成创建 PV。
  4. AD Controller 对比 asw 和 dsw 状态,发现 Volume 需要被 attach,则调用 Volume Plugin 的实现去 attach。in-tree 插件不需多说,如果是 CSI 插件,则 AD Controller 会先调用 CSI in-tree 代码创建 VolumeAttachment 对象,CSI 插件的一个名为 external-attacher 的 sidecar 会 watch 该对象,watch 到创建则调用 CSI driver 的相应方法(ControllerPublishVolume)来 attach。
  5. VolumeManager 等到 volume 成功 attach 到节点后,开始调用 Volume Plugin 去进行 mount 操作。这个mount 操作分为两步:第一步是格式化设备并把 volume mount 到一个 global mount path(/var/lib/kubelet/plugins下),第二步是将 bind mount 刚才的 global mount path到/var/lib/kubelet/pods/${pod_UUID}/volumes下。
  6. Kubelet 调用容器运行时启动容器,并且 bind mount 第5步中的 mount path 到容器中。

(Provision -> Attach -> Mount; Unmount -> Detach -> Delete)

TKE 存储插件及原理介绍

随着 Kubernetes 社区发展,TKE 先后支持了 In-Tree 和 CSI 两种存储插件。二者在功能上的主要区别在于 In-Tree 存储插件仅支持在 TKE 集群使用 CBS,而 CSI 支持使用 CBS、CFS、COS。

类型 支持CBS 支持CFS 支持COS 参考
In-Tree × ×
CSI //github.com/TencentCloud/kubernetes-csi-tencentcloud

In-Tree 插件(QcloudCbs)

  • kubernetes 早期只支持以 In-Tree 的方式扩展存储插件,也就是插件在 Kubernetes 代码中实现。

  • In-Tree 插件名为cloud.tencent.com/qcloud-cbs,所以也可称为 QcloudCbs,在 TKE 集群中有个默认的名为cbs的 StorageClass。

NAME            PROVISIONER                    AGE
cbs (default)   cloud.tencent.com/qcloud-cbs   48m

特性

In-Tree 插件只实现了使用 CBS 的能力,其主要特性有:

  • 静态数据卷:即用户手动创建 volme、PV 对象、PVC 对象
  • 动态数据卷:根据 StorageClass 配置来由插件控制创建和删除 volume 和 PV
  • 拓扑感知:CBS 不支持跨可用区挂载,在多可用区集群中,会先调度 pod,然后去调度后的 node 的 zone 创建 volume。
  • 调度器感知节点 maxAttachLimit:腾讯云单个 CVM 上默认最多挂载 20块 CBS 盘,调度器感知该限制,调度时过滤到要超过 maxAttachLimit 的节点。可以全局修改 maxAttachLimit,但需要 IaaS 层先支持。
腾讯云存储 静态数据卷 动态数据卷 拓扑感知 调度器感知节点 maxAttachLimit
腾讯云硬盘(CBS) 支持两种使用方式:

  • 直接通过 volume 使用
  • 通过PV/PVC使用(推荐)
  • 支持 支持。pod 调度后,在同一个可用区创建 volume。避免 CBS 跨可用区无法使用。 支持。云服务器(cvm)可以挂载的云硬盘(cbs)是有上限的。调度器调度 pod 时过滤掉超过最大可挂载 CBS 数量的节点。

    原理简介

    下面简单了解下 In-Tree 插件 QcloudCbs 的架构图,了解各相关组件分别完成何种工作。

    上图是包含 TKE In-Tree 存储插件的 Kubernetes 存储架构图。图中绿色部分,皆属于 In-Tree 插件 QcloudCbs 的实现范畴。
    由上述的 Kubernetes持久化存储流程 可知要动态使用一个 cbs pv,主要有三个过程:provision、attach、mount,而这三个过程是由不同组件负责的:

    • cbs-provisioner 负责 volume 的 provision/delete。为了与 Kubernetes 代码解耦,cbs-provisioner 是基于kubernetes-sigs/sig-storage-lib-external-provisioner实现的一个 external provisioner,来 provision 和 delete volume。PV Controller 在这种模式下虽然不去 provision/delete volume,但是还是会参与处理(比如 PV 和 PVC 的绑定)。
    • AD Controller 负责 volume 的 attach/detach。Tencent Cloud Provider 中封装云 API,In-Tree 插件调用 Cloud Provider 实现了 attach/detach 的具体逻辑,并提供给 AD Controller 调用。
    • kubelet 的 Volume Manager 负责 volume 的 mount/unmount。In-Tree 插件中实现 MountDevice、SetUp 等接口,Volume Manager 调用其完成准备 volume 的最后一步。
    • 另外,Scheduler 中也有 volume 相关的逻辑,我们添加了一个 predicate 策略:MaxQcloudCbsVolumeCount,该策略主要实现调度器感知节点 maxAttachLimit特性。而 Scheduler 原生的一个 predicate 策略:NoVolumeZoneConflictPred,是用来把 pod 调度到已有 PV 所在 zone 的节点,这可以避免云盘跨可用区挂载的问题;对于新建 PV 的话,避免云盘跨可用区挂载问题则由拓扑感知特性完成。

    CSI 插件

    CSI 是 Kubernetes 社区扩展卷的标准和推荐方式。TKE 的 CSI 插件包含 CBS、CFS、COS 三个 driver,本节重点介绍 CBS CSI driver,并与 QcloudCbs 进行对比。3个 driver 的静态 pv 和动态 pv 的支持情况如下表所示:

    腾讯云存储 静态数据卷 动态数据卷
    云硬盘(CBS) 支持 支持
    文件存储(CFS) 支持 支持
    对象存储(COS) 支持 不支持

    CBS CSI 特性及与 QcloudCbs 对比

    • CBS CSI 比 QcloudCbs 多几个特性:volume 在线扩容,volume 快照和恢复。
    存储插件 静态数据卷 动态数据卷 拓扑感知 调度器感知节点maxAttachLimit 卷在线扩容 卷快照&恢复
    CBS CSI
    QcloudCbs(In-Tree) × ×

    原理简介

    CSI 原理简介

    CSI 原理参考上图。要实现一个 CSI driver,一般需要实现以下 3 个 gRPC services(CSI Controller Service 可选):

    • CSI Identity Services:提供 driver 信息(drivername,版本等)

    • CSI Controller Services

      (可选):controller 负责创删卷、attach/detach、扩容、快照等。涉及的方法如下:

      • CreateVolume/DeleteVolume
      • Controller[Publish|Unpublish]Volume (对应attach/detach)
      • CreateSnapshot/DeleteSnapshot/ListSnapshots
      • ControllerExpandVolume
    • CSI Node Services

      :负责向节点注册 driver,mount/unmount。涉及的方法如下:

      • NodeStageVolume/NodeUnstageVolume((un)mount device)
      • NodePublishVolume/NodeUpPublishVolume((un)mount volume)

    在我们实现之外,kuberntes Team 还提供了多个外部组件,用于沟通 k8s 原生组件(apiserver、controller manager、kubelet)与自己实现的 CSI driver。

    • external-provisioner:watch PersistentVolumeClaim(PVC)对象,调用 driver 的CreateVolume/DeleteVolume
    • external-attacher:watch VolumeAttachment对象,调用 driver 的Controller[Publish|Unpublish]Volume
    • external-resizer: watch PersistentVolumeClaim对象,调用 driver 的ControllerExpandVolume
    • external-snapshottersnapshot-controller:snapshot-controller watch VolumeSnapshotVolumeSnapshotContent CRD 对象,external-snapshotter watch VolumeSnapshotContent对象。调用 driver 的CreateSnapshot/DeleteSnapshot/ListSnapshots
    • *node-driver-registrar*:使用NodeGetInfo获取 driver 信息,然后使用 kubelet 插件注册机制注册 driver。
    CBS CSI 部署图

    CBS CSI 使用社区推荐部署方式,包含两个 workload:

    • 一个 DaemonSet,也就是每个 Node 会有一个,我们可以简单称为NodePlugin,由 CBS CSI Driver 和 node-driver-registrar 两个容器组成。负责向节点注册 driver,并提供 mount 的能力。
    • 一个 StatefulSet/Deployment,我们可以简称为Controller。由 driver 和多个 sidecar(external-provisioner、external-attacher、external-resizer、external-snapshotter、snapshot-controller)一起构成,提供创删卷、attach/detach、扩容、快照等能力

    CBS CSI 插件的 mount 是 driver 容器执行的,它是如何 mount 到 Node 上的?
    • 答案是:挂载传播(Mount propagation)。挂载传播允许容器内的 mount 在容器外可见。参见//stupefied-goodall-e282f7.netlify.app/contributors/design-proposals/node/propagation/
    • CBS CSI 的 global mount 阶段(NodeStageVolume)要把设备 mount 到/var/lib/kubelet/plugins的子目录下;之后 bind mount 阶段(NodePublishVolume)的 target path 是/var/lib/kubelet/pods。所以我们为这两个目录都设置了挂载传播(模式为Bidirectional

    使用推荐

    • TKE 集群版本为 1.14+(包含 1.14),推荐使用 CSI 插件
    • 需要在TKE集群中使用 CFS 和 COS 能力,使用 CSI 插件
    • 需要在TKE集群中对 CBS 盘在线扩容和使用快照功能,使用 CSI 插件
    • 已经使用了 QcloudCbs(In-Tree 插件)的,可以继续使用。(后续会通过 Volume Migration 统一到 CBS CSI)

    最佳实践

    provisioner:

    • cbs csi —— “com.tencent.cloud.csi.cbs”
    • cbs intree —— “cloud.tencent.com/qcloud-cbs”

    cbs csi 的安装请参见 cbs csi 文档,我们也已经在腾讯云控制台支持扩展组件安装。

    本节最佳实践均以 cbs csi 插件为例,相应版本要求也是针对 cbs csi 插件。

    1、如果集群节点跨 zone,如何避免 cbs 云盘跨可用区挂载?

    cbs 云盘不支持跨可用区挂载到节点,所以在跨可用区的集群中推荐通过拓扑感知特性来避免跨可用区挂载的问题。

    1.1 使用前注意

    • TKE集群版本 >= 1.14
    • 确保 csi 插件为最新版本

    1.2 如何使用

    使用方式很简单,在 storageclass 中设置 volumeBindingModeWaitForFirstConsumer,然后使用该 storageClass 即可。intree 和 csi 插件均支持。

    kind: StorageClass
    metadata:
      name: cbs-topo
    parameters:
      type: cbs
    provisioner: com.tencent.cloud.csi.cbs
    reclaimPolicy: Delete
    volumeBindingMode: WaitForFirstConsumer
    

    1.3 原理

    拓扑感知调度需要多个 k8s 组件配合完成,包括 scheduler、pv controller、external-provisioner。流程为:

    1. pv controller watch 到 PVC 对象,发现 storageclass 的 volumeBindingMode 为WaitForFirstConsumer,即不会马上处理该pvc的创建事件,等待 scheduler 处理;
    2. scheduler 调度完 pod 后,会将 nodeName 以 annotation 的方式打到 PVC 对象上: volume.kubernetes.io/selected-node: 10.0.0.72
    3. pv controller 获取到 PVC 对象的更新事件后,处理这个 annotation(volume.kubernetes.io/selected-node),根据 nodeName 获取 Node 对象,传入到 provisioner 中。
    4. provisioner 根据传过来的 Node 对象的 label 获取可用区(failure-domain.beta.kubernetes.io/zone),之后在对应 zone 创建 pv,从而达到和 pod 相同可用区的效果,避免云盘和 node 在不同可用区而无法挂载。

    2、如何在线扩容云盘?

    TKE 支持在线扩容 PV,对应的云盘及文件系统,即不需要重启 pod 即可完成扩容。但,为了确保文件系统的稳定性,还是推荐先让云盘文件系统处于未 mount 情况下。为此,我们将提供两种扩容方式:

    1. 不重启 pod 的情况下在线扩容
      • 这种情况下被扩容的云盘的文件系统被 mount 在节点上,如果 I/O 的话,有可能会出现文件系统扩容错误
    2. 重启 pod 的情况下在线扩容
      • 这种情况下被扩容的云盘的文件系统被 unmount了。可以避免上面的问题,推荐这种方式

    2.1 使用前注意

    • TKE集群版本 >= 1.16,详见 cbs csi 文档
    • 仅 cbs csi 插件支持扩容,确保 csi 插件为最新版本
    • 可以在扩容前使用快照来备份数据,避免扩容失败导致数据丢失。参见下方 3.2.1 使用快照备份云硬盘

    2.2 如何使用

    2.2.1 创建允许扩容的 StorageClass

    在 storageclass 中设置allowVolumeExpansiontrue

    allowVolumeExpansion: true
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: cbs-csi-expand
    parameters:
      diskType: CLOUD_PREMIUM
    provisioner: com.tencent.cloud.csi.cbs
    reclaimPolicy: Delete
    volumeBindingMode: Immediate
    
    2.2.2 不重启 pod 的情况下在线扩容

    1、确认扩容前 pv 和文件系统状态,大小均为 20G

    $ kubectl exec ivantestweb-0 df /usr/share/nginx/html
    Filesystem     1K-blocks  Used Available Use% Mounted on
    /dev/vdd        20511312 45036  20449892   1% /usr/share/nginx/html
    $ kubectl get pv pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS   REASON   AGE
    pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c   20Gi       RWO            Delete           Bound    default/www1-ivantestweb-0   cbs-csi                 20h
    

    2、执行以下命令修改 PVC 对象中的容量,扩容至 30G

    $ kubectl patch pvc www1-ivantestweb-0 -p '{"spec":{"resources":{"requests":{"storage":"30Gi"}}}}'
    

    执行后稍等片刻,可以发现 pv 和文件系统已经扩容至 30G:

    $ kubectl exec ivantestweb-0 df /usr/share/nginx/html
    Filesystem     1K-blocks  Used Available Use% Mounted on
    /dev/vdd        30832548 44992  30771172   1% /usr/share/nginx/html
    $ kubectl get pv pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS   REASON   AGE
    pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c   30Gi       RWO            Delete           Bound    default/www1-ivantestweb-0   cbs-csi                 20h
    
    2.2.3 重启 pod 的情况下在线扩容

    1、确认扩容前 pv 和文件系统状态,大小均为 30G

    $ kubectl exec ivantestweb-0 df /usr/share/nginx/html
    Filesystem     1K-blocks  Used Available Use% Mounted on
    /dev/vdd        30832548 44992  30771172   1% /usr/share/nginx/html
    $ kubectl get pv pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c 
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS   REASON   AGE
    pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c   30Gi       RWO            Delete           Bound    default/www1-ivantestweb-0   cbs-csi                 20h
    

    2、使用下面命令给 PV 对象打标签,打一个非法 zone,旨在下一步重启 pod 后 pod 无法调度到某个节点上

    $ kubectl label pv pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c failure-domain.beta.kubernetes.io/zone=nozone
    

    3、重启 pod。重启后由于 pod 对应的 pv 的标签表明的是非法 zone,pod 会处于 Pending 状态

    $ kubectl delete pod ivantestweb-0
    
    $ kubectl get pod ivantestweb-0
    NAME            READY   STATUS    RESTARTS   AGE
    ivantestweb-0   0/1     Pending   0          25s
    
    $ kubectl describe pod ivantestweb-0
    Events:
      Type     Reason            Age                 From               Message
      ----     ------            ----                ----               -------
      Warning  FailedScheduling  40s (x3 over 2m3s)  default-scheduler  0/1 nodes are available: 1 node(s) had no available volume zone.
    

    4、修改 PVC 对象中的容量,扩容至 40G

    kubectl patch pvc www1-ivantestweb-0 -p '{"spec":{"resources":{"requests":{"storage":"40Gi"}}}}'
    

    5、去掉 PV 对象之前打的标签,这样 pod 就能调度成功了。

    $ kubectl label pv pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c failure-domain.beta.kubernetes.io/zone-persistentvolume/pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c labeled
    

    稍等片刻,pod running,对应的 pv 和文件系统也扩容成功,从 30G 扩容到 40G 了

    $ kubectl get pod ivantestweb-0
    NAME            READY   STATUS    RESTARTS   AGE
    ivantestweb-0   1/1     Running   0          17m
    
    $ kubectl get pv pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS   REASON   AGE
    pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c   40Gi       RWO            Delete           Bound    default/www1-ivantestweb-0   cbs-csi                 20h
    
    $ kubectl get pvc www1-ivantestweb-0
    NAME                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    www1-ivantestweb-0   Bound    pvc-e193201e-6f6d-48cf-b96d-ccc09225cf9c   40Gi       RWO            cbs-csi        20h
    
    $ kubectl exec ivantestweb-0 df /usr/share/nginx/html
    Filesystem     1K-blocks  Used Available Use% Mounted on
    /dev/vdd        41153760 49032  41088344   1% /usr/share/nginx/html
    

    3、如何创建快照和使用快照来恢复卷?

    3.1 使用前注意

    • TKE集群版本 >= 1.18,详见 cbs csi 文档
    • 仅 cbs csi 插件支持快照,确保 csi 插件镜像为最新版本

    3.2 如何使用

    3.2.1 使用快照备份云硬盘

    1、使用下面 yaml,创建VolumeSnapshotClass对象

    apiVersion: snapshot.storage.k8s.io/v1beta1
    kind: VolumeSnapshotClass
    metadata:
      name: cbs-snapclass
    driver: com.tencent.cloud.csi.cbs
    deletionPolicy: Delete
    

    创建后显示:

    $ kubectl get volumesnapshotclass
    NAME            DRIVER                      DELETIONPOLICY   AGE
    cbs-snapclass   com.tencent.cloud.csi.cbs   Delete           17m
    

    2、使用下面 yaml,创建

    apiVersion: snapshot.storage.k8s.io/v1beta1
    kind: VolumeSnapshot
    metadata:
      name: new-snapshot-demo
    spec:
      volumeSnapshotClassName: cbs-snapclass
      source:
        persistentVolumeClaimName: csi-pvc
    

    创建后稍等片刻,volumesnapshot 和 volumesnapshotcontent 对象都创建成功,READYTOUSE为 true:

    $ kubectl get volumesnapshot
    NAME                READYTOUSE   SOURCEPVC            SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS   SNAPSHOTCONTENT                                    CREATIONTIME   AGE
    new-snapshot-demo   true         www1-ivantestweb-0                           10Gi          cbs-snapclass   snapcontent-ea11a797-d438-4410-ae21-41d9147fe610   22m            22m
    $ kubectl get volumesnapshotcontent
    NAME                                               READYTOUSE   RESTORESIZE   DELETIONPOLICY   DRIVER                      VOLUMESNAPSHOTCLASS   VOLUMESNAPSHOT      AGE
    snapcontent-ea11a797-d438-4410-ae21-41d9147fe610   true         10737418240   Delete           com.tencent.cloud.csi.cbs   cbs-snapclass         new-snapshot-demo   22m
    

    具体快照 id 在 volumesnapshotcontent 对象中,status.snapshotHandle(snap-e406fc9m),可以根据这个快照 id 在腾讯云控制台确认快照是否存在

    $ kubectl get volumesnapshotcontent snapcontent-ea11a797-d438-4410-ae21-41d9147fe610 -oyaml
    apiVersion: snapshot.storage.k8s.io/v1beta1
    kind: VolumeSnapshotContent
    metadata:
      creationTimestamp: "2020-11-04T08:58:39Z"
      finalizers:
      - snapshot.storage.kubernetes.io/volumesnapshotcontent-bound-protection
      name: snapcontent-ea11a797-d438-4410-ae21-41d9147fe610
      resourceVersion: "471437790"
      selfLink: /apis/snapshot.storage.k8s.io/v1beta1/volumesnapshotcontents/snapcontent-ea11a797-d438-4410-ae21-41d9147fe610
      uid: 70d0390b-79b8-4276-aa79-a32e3bdef3d6
    spec:
      deletionPolicy: Delete
      driver: com.tencent.cloud.csi.cbs
      source:
        volumeHandle: disk-7z32tin5
      volumeSnapshotClassName: cbs-snapclass
      volumeSnapshotRef:
        apiVersion: snapshot.storage.k8s.io/v1beta1
        kind: VolumeSnapshot
        name: new-snapshot-demo
        namespace: default
        resourceVersion: "471418661"
        uid: ea11a797-d438-4410-ae21-41d9147fe610
    status:
      creationTime: 1604480319000000000
      readyToUse: true
      restoreSize: 10737418240
      snapshotHandle: snap-e406fc9m
    
    3.2.2 从快照恢复卷(云硬盘)

    1、我们在 3.2.1 中创建的VolumeSnapshot的对象名为new-snapshot-demo,使用下面 yaml 来从快照恢复一个卷

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: restore-test
    spec:
      storageClassName: cbs-csi
      dataSource:
        name: new-snapshot-demo
        kind: VolumeSnapshot
        apiGroup: snapshot.storage.k8s.io
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
    

    发现 restore 的 pvc 已经创建出来,diskid 也在 pv 中(disk-gahz1kw1)

    $ kubectl get pvc restore-test
    NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    restore-test   Bound    pvc-80b98084-29a3-4a38-a96c-2f284042cf4f   10Gi       RWO            cbs-csi        97s
    $ kubectl get pv pvc-80b98084-29a3-4a38-a96c-2f284042cf4f -oyaml
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      annotations:
        pv.kubernetes.io/provisioned-by: com.tencent.cloud.csi.cbs
      creationTimestamp: "2020-11-04T12:08:25Z"
      finalizers:
      - kubernetes.io/pv-protection
      name: pvc-80b98084-29a3-4a38-a96c-2f284042cf4f
      resourceVersion: "474676883"
      selfLink: /api/v1/persistentvolumes/pvc-80b98084-29a3-4a38-a96c-2f284042cf4f
      uid: 5321df93-5f21-4895-bafc-71538d50293a
    spec:
      accessModes:
      - ReadWriteOnce
      capacity:
        storage: 10Gi
      claimRef:
        apiVersion: v1
        kind: PersistentVolumeClaim
        name: restore-test
        namespace: default
        resourceVersion: "474675088"
        uid: 80b98084-29a3-4a38-a96c-2f284042cf4f
      csi:
        driver: com.tencent.cloud.csi.cbs
        fsType: ext4
        volumeAttributes:
          diskType: CLOUD_PREMIUM
          storage.kubernetes.io/csiProvisionerIdentity: 1604478835151-8081-com.tencent.cloud.csi.cbs
        volumeHandle: disk-gahz1kw1
      nodeAffinity:
        required:
          nodeSelectorTerms:
          - matchExpressions:
            - key: topology.com.tencent.cloud.csi.cbs/zone
              operator: In
              values:
              - ap-beijing-2
      persistentVolumeReclaimPolicy: Delete
      storageClassName: cbs-csi
      volumeMode: Filesystem
    status:
      phase: Bound
    

    参考

    【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!