使用云盘存储快照

容器服务Kubernetes版ACK(Container Service for Kubernetes)的云盘存储快照特性可以帮助您实现应用数据的备份和恢复。本文介绍ACK的存储快照的基本概念、使用流程,并说明如何动态、静态创建快照。

前提条件

背景信息

在阿里云ACK集群中部署有状态服务通常使用云盘数据卷存储数据,虽然云盘本身提供了数据的备份(快照)恢复机制,但是如何将这种机制和Kubernetes服务集成并灵活地提供给应用使用?为了解决这个问题,Kubernetes使用以下两个特性来实现备份恢复能力:

  • 通过VolumeSnapshot资源实现云盘的备份(快照功能)。

  • 通过PVC的DataSource功能实现数据的恢复。

计费说明

云盘快照基于阿里云ECS快照实现,关于ECS云盘快照的计费信息,请参见快照计费

自2023年10月12日11:00起,阿里云ECS快照升级新版不再收取快照极速可用存储费和快照极速可用次数费,更多信息,请参见快照极速可用能力

使用说明

为了实现快照相关功能,ACK通过CRD定义了以下3个相关的资源类型。

资源类型名称

描述

VolumeSnapshotContent

存储后端的快照实例,由系统管理员创建维护,无NameSpace。类似PV概念。

VolumeSnapshot

声明一个快照实例,由用户创建维护,属于特定Namespace。类似PVC概念。

VolumeSnapshotClass

定义一个快照类,描述创建快照使用的参数、Controller。类似StorageClass概念。

存储快照资源的绑定规则如下:

  • 在使用Snapshot资源类型时,和PV、PVC一样,首先您需绑定VolumeSnapshot与VolumeSnapshotContent。

  • 集群会自动为正确配置了VolumeSnapshotClassName字段的VolumeSnapshot资源,创建VolumeSnapshotContent资源。 如果您没有配置或者配置错误,则无法自动创建VolumeSnapshotContent,您需要手动创建VolumeSnapshotContent,并绑定VolumeSnapshot。

  • VolumeSnapshotContent与VolumeSnapshot绑定是一对一的关系。

重要

删除VolumeSnapshotContent时,后端的快照也会被删除。

动态创建快照

ACK使用云盘动态创建快照使用流程如下图所示。snapshot

使用PL0、PL1、PL2、PL3级别的ESSD云盘或ESSD AutoPL云盘时,动态创建的快照默认开启快照极速可用功能。

使用流程说明如下。

流程步骤

描述

创建原始应用,创建云盘卷保存数据。

创建VolumeSnapshot,此时集群会自动创建VolumeSnapshotContent和存储端的快照实例。

创建新的应用,并配置PVC引用步骤②中创建的快照对象。

上述的三个步骤实现:

  • 备份:图中的Volume1的数据被备份到Snapshot1

  • 恢复:Snapshot1的数据(也就是Volume1的数据)被恢复成Volume2

本文示例将通过创建MySQL应用并恢复应用的数据,说明如何使用存储快照功能。操作步骤如下。

  1. 创建VolumeSnapshotClass快照类。

    1. 使用以下YAML内容创建volumesnapshotclass.yaml文件。

      apiVersion: snapshot.storage.k8s.io/v1
      kind: VolumeSnapshotClass
      metadata:
       name: default-snapclass
      driver: diskplugin.csi.alibabacloud.com
      parameters:
        retentionDays: "5"
      deletionPolicy: Delete

      参数

      说明

      deletionPolicy

      • 当值为Delete时,说明删除VolumeSnapshot时,VolumeSnapshotContent以及关联的快照也会一起被删除。

      • 当值为Retain时,说明删除VolumeSnapshot时,VolumeSnapshotContent以及关联的快照不会被删除。

      parameters.retentionDays

      指定快照自动回收时间。

      parameters.forceDelete

      当指定forceDelete"true"时,表示使用强制删除快照功能。自csi-provisioner组件v1.26.5-92f859a-aliyun版本起,默认使用强制删除且不可修改,此前默认为普通删除。

      • 强制删除:强制删除用户创建的所有已使用和未使用的快照。

      • 普通删除:只能删除未使用的快照。已经使用过的快照,不能使用普通删除。

    2. 执行以下命令创建VolumeSnapshotClass快照类。

      kubectl apply -f volumesnapshotclass.yaml
  2. 创建原始应用并写入数据。

    1. 使用以下YAML内容创建mysql.yaml文件。

      apiVersion: apps/v1
      kind: StatefulSet
      metadata:
        name: mysql
      spec:
        selector:
          matchLabels:
            app: mysql
        serviceName: "mysql"
        replicas: 1
        template:
          metadata:
            labels:
              app: mysql
          spec:
            containers:
            - name: mysql
              image: mysql:5.7
              env:
              - name: MYSQL_ROOT_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: mysql-pass
                    key: password
              imagePullPolicy: IfNotPresent
              volumeMounts:
              - name: disk
                mountPath: /data
        volumeClaimTemplates:
        - metadata:
            name: disk
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "alicloud-disk-topology-alltype"
            resources:
              requests:
                storage: 20Gi
      ---
      apiVersion: v1
      kind: Secret
      metadata:
        name: mysql-pass
      type: Opaque
      data:
        username: dGVz****            
        password: dGVzdDEt****    
    2. 执行以下命令创建应用MySQL。

      kubectl apply -f mysql.yaml
    3. 执行以下命令往Pod(mysql-0)中写入数据。

      kubectl exec -it mysql-0 -- touch /data/test
      kubectl exec -it mysql-0 -- ls /data

      输出:

      lost+found test
  3. 创建VolumeSnapshot。

    说明
    • 若您集群使用的CSI版本不低于v1.22.12-b797ad9-aliyun,创建快照时, 不依赖该PVC是否有Running Pod存在,可对任意挂载过的云盘创建快照。关于CSI版本更多信息,请参见csi-provisioner

    • 若您集群使用的CSI版本低于v1.22.12-b797ad9-aliyun,创建快照时,则需要保证有Pod正在使用当前PVC,即保证云盘处于挂载状态。

    1. 使用以下YAML内容创建snapshot.yaml文件。

      apiVersion: snapshot.storage.k8s.io/v1
      kind: VolumeSnapshot
      metadata:
        name: new-snapshot-demo
        namespace: default
      spec:
        volumeSnapshotClassName: default-snapclass
        source:
          persistentVolumeClaimName: disk-mysql-0
    2. 执行以下命令创建VolumeSnapshot。

      kubectl apply -f snapshot.yaml
    3. 执行以下命令查看是否创建VolumeSnapshot和VolumeSnapshotContent。您也可以登录ECS控制台查看快照实例。

      查看VolumeSnapshot命令:

      kubectl get volumesnapshots.snapshot.storage.k8s.io

      输出:

      NAME                      AGE
      new-snapshot-demo                    36m

      查看VolumeSnapshotContent命令:

      kubectl get VolumeSnapshotContent

      输出:

      NAME                      AGE
      snapshotcontent-222222                  36m
  4. 恢复数据。

    1. 使用以下YAML内容创建mysql-restore文件。

      apiVersion: apps/v1
      kind: StatefulSet
      metadata:
        name: mysql-restore
      spec:
        selector:
          matchLabels:
            app: mysql
        serviceName: "mysql"
        replicas: 1
        template:
          metadata:
            labels:
              app: mysql
          spec:
            containers:
            - name: mysql
              image: mysql:5.7
              env:
              - name: MYSQL_ROOT_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: mysql-pass
                    key: password
              imagePullPolicy: IfNotPresent
              volumeMounts:
              - name: disk
                mountPath: /data
        volumeClaimTemplates:
        - metadata:
            name: disk
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "alicloud-disk-topology-alltype"
            resources:
              requests:
                storage: 20Gi
            dataSource:
              name: new-snapshot-demo
              kind: VolumeSnapshot
              apiGroup: snapshot.storage.k8s.io
      说明

      volumeClaimTemplates中,需设置dataSource的类型为VolumeSnapshot,且VolumeSnapshot的名字为步骤3中创建的new-snapshot-demo。

    2. 执行以下命令恢复数据。

      kubectl apply -f mysql-restore.yaml
  5. 执行以下命令查看Pod(mysql-restore-0)数据。

    kubectl exec -it mysql-restore-0 -- ls /data

    输出:

    lost+found test

    可见在不同的Pod中返回相同的数据,实现了数据的恢复。

静态创建快照(使用ECS上已有快照)

将已有ECS快照导入至ACK集群中的操作步骤如下。

  1. 使用以下YAML内容创建VolumeSnapshotContent。

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshotContent
    metadata:
      name: new-snapshot-content-test
    spec:
      deletionPolicy: Retain
      driver: diskplugin.csi.alibabacloud.com
      source:
        snapshotHandle: <your-snapshotid>
      volumeSnapshotRef:
        name: new-snapshot-demo
        namespace: default

    参数

    描述

    snapshotHandle

    填写在ECS页面上的已生成的快照ID。

    volumeSnapshotRef

    填写要创建的VolumeSnapshot的信息:

    • name:将要创建的VolumeSnapshot的名称。

    • namespace:将要创建的VolumeSnapshot所在的命名空间。

  2. 使用以下YAML内容创建VolumeSnapshot。

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: new-snapshot-demo
      namespace: default
    spec:
      source:
        volumeSnapshotContentName: new-snapshot-content-test

    参数

    描述

    metadata.name

    VolumeSnapshot的名称,需要和上述VolumeSnapshotContent中指定的相同。

    spec.source.volumeSnapshotContentName

    当前VolumeSnapshot绑定的VolumeSnapshotContent的名称,需与上述创建的VolumeSnapshotContent的名称一致。

  3. 恢复数据。

    1. 使用以下YAML内容创建mysql-restore文件。

      apiVersion: apps/v1
      kind: StatefulSet
      metadata:
        name: mysql-restore
      spec:
        selector:
          matchLabels:
            app: mysql
        serviceName: "mysql"
        replicas: 1
        template:
          metadata:
            labels:
              app: mysql
          spec:
            containers:
            - name: mysql
              image: mysql:5.7
              env:
              - name: MYSQL_ROOT_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: mysql-pass
                    key: password
              imagePullPolicy: IfNotPresent
              volumeMounts:
              - name: disk
                mountPath: /data
        volumeClaimTemplates:
        - metadata:
            name: disk
          spec:
            accessModes: [ "ReadWriteOnce" ]
            storageClassName: "alicloud-disk-topology-alltype"
            resources:
              requests:
                storage: 20Gi
            dataSource:
              name: new-snapshot-demo
              kind: VolumeSnapshot
              apiGroup: snapshot.storage.k8s.io
      说明

      volumeClaimTemplates中,需设置dataSource的类型为VolumeSnapshot,且VolumeSnapshot的名字为步骤2中创建的new-snapshot-demo。

    2. 执行以下命令恢复数据。

      kubectl apply -f mysql-restore.yaml
  4. 执行以下命令查看Pod(mysql-restore-0)数据。

    kubectl exec -it mysql-restore-0 -- ls /data

    输出:

    lost+found test

    可见在不同的Pod中返回相同的数据,实现了数据的恢复。