亚马逊AWS官方博客

在 Amazon EKS 上使用 k8s Snapshot 备份和恢复 EBS PV 卷

云端容器平台如 Amazon EKS 非常适合来运行无状态的应用程序以增强其弹性,但某些场景下我们仍然需要使用 PV 来运行有状态的服务并提供固化存储,如某些中间件应用或其他需要使用轻量化数据库的应用。这些应用通常不支持多副本,且对读写延迟和性能要求较高,因此选择正确的底层存储非常重要。

开源社区提供了标准的容器存储接口 (CSI),这是一种将任意块和文件存储系统暴露给 Kubernetes 等容器编排系统上的容器化工作负载的标准。目前 Amazon 已经官方提供了基于 EBS、EFS、FSx for Lustre 的 CSI 驱动程序,提供固化存储给 Amazon EKS 上运行的容器以满足不同场景的需求。

Amazon Elastic Block Stock (Amazon EBS) 是一种块存储服务,提供从 EC2 实例到专用存储卷的直联访问。在这篇文章中,我们将专注于 EBS CSI 驱动程序提供的 Kubernetes 卷快照功能。Kubernetes 卷快照允许您在特定时间点创建 EBS 卷的副本。 您可以使用此副本快速的还原成新的 EBS 卷。与使用标准的 Amazon EBS 快照不同,所有信息和操作将在 Kubernetes 层进行,无需手动在 Amazon 门户或通过 API 手动调用,这将有助于降低在数据恢复时的人工成本并提高安全性。

先决条件:

完成本示例的先决条件是拥有一个运行 Kubernetes 1.20 或更高版本的有效 Amazon EKS 集群。如果您需要有关如何启动 EKS 集群的说明,请参阅 Amazon EKS 文档

另请注意,Kubernetes 卷快照功能是在 Kubernetes 1.17 版本开始 Beta 测试,并在 Kubernetes 1.20 版本 GA,如果您的 EKS 集群介于这两个版本之间,相关的API版本请使用 v1beta1。有关该功能的GA信息请参阅此文档:

Step1: 部署 CSI Snapshotter 驱动程序

CSI  Snapshotter 是容器存储接口 (CSI) 在 Kubernetes 实现的一部分。它包含了使用快照所必须的资源,且必须在安装 Amazon EBS CSI driver 前部署完毕。

它包含如下内容:

  • Kubernetes 标准 CRD 配置定义文件

volumesnapshotclasses

volumesnapshots

volumesnapshotcontents

  • RBAC 相关配置定义文件
  • Controller Deployment 配置定义文件

有关于此的详情信息,请参阅 GitHub

部署完成后,默认将创建2个名为snapshot-controller的容器:

$ kubectl get pod -n kube-system | grep snapshot
snapshot-controller-75fd799dc8-8tj4w  	1/1     Running   
snapshot-controller-75fd799dc8-q4fm8   	1/1     Running   

请确保它们的状态为 “Running“。

Step2: 部署Amazon EBS CSI 驱动程序

在确保第一步所有资源处于正常运行的状态后,就可以开始部署官方提供的 Amazon EBS CSI 驱动程序了。目前,官方已经支持通过管理门户一键安装,您也可以按照官方文档的标准步骤进行手动部署。

该驱动程序包含两组容器:

  • ebs-csi-controller

— 默认运行副本数为 2

  • ebs-csi-node

— 该组容器需要确保运行在每个 worker 节点上

使用下面的命令确保相关的容器已经正常运行:

$ kubectl get pod -n kube-system | grep ebs
ebs-csi-controller-6d5b894ddc-wfvk4    6/6     Running   
ebs-csi-controller-6d5b894ddc-xppg9    6/6     Running   
ebs-csi-node-22xzl                 	3/3     Running   
ebs-csi-node-f69hs        		3/3     Running
ebs-csi-node-rgqlr                 	3/3     Running   
ebs-csi-node-sp9hx              	3/3     Running    
…

Step3:创建EBS快照

首先,与创建基于 EBS 的 Storage Class 类似,我们需要创建一个叫做 VolumeSnapshotClass 的 Kubernetes 自定义资源。该资源在第一步部署 CRD 时已经创建,如果创建有问题,此处会报找不到定义的错误。此外,如果您的 Amazone EKS 集群使用 Kubernetes 1.17 ~ 1.19 版本,请将 API 切换成 v1beta1。

VolumeSnapshotClass 定义文件:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: csi-aws-vsc
driver: ebs.csi.aws.com
deletionPolicy: Delete

确认相关资源已经创建完成:

$kubectl get VolumeSnapshotClass
NAME          DRIVER            DELETIONPOLICY   AGE
csi-aws-vsc   ebs.csi.aws.com   Delete           4d23h

在本次示例中,我们将使用如下的 Pod 定义通过输出 date 的方式来记录时间戳信息到 /data/out.txt :

apiVersion: v1
kind: Pod
metadata:
  name: app-restore
spec:
  containers:
  - name: app-restore
    image: centos
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-claim

创建完成后,确保 /data/out.txt 可以正常写入时间戳信息。之后就可以为对应的 PVC:ebs-claim 创建快照。相关定义文件参考如下。如果您的 EKS 集群使用 Kubernetes 1.17 ~ 1.19 版本,请将 API 切换成 v1beta1。

 

VolumeSnapshot定义文件:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: ebs-volume-snapshot
spec:
  volumeSnapshotClassName: <volumesnapshotclass_name>
  source:
persistentVolumeClaimName: <pvc_name>

等待 volumesnapshot 的可用状体变为: True

此时需在管理门户中确认可以看到与之对应的 EBS 快照:

Step4:恢复 EBS 快照

从 VolumeSnapShot 创建 PVC 的定义文件:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-snapshot-restored-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 4Gi
  dataSource:
    name: ebs-volume-snapshot
    kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io

挂载恢复后 PVC 的 Pod 定义文件:

apiVersion: v1
kind: Pod
metadata:
  name: app-restore
spec:
  containers:
  - name: app-restore
    image: centos
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $(date -u) >> /data/out-restore.txt; sleep 5; done"]
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-snapshot-restored-claim

等待 PVC 和 Pod 可用后,使用 $kubectl exec 在 Pod 内部运行命令来检查相关的数据是否被正确的保存和恢复。可以看到原有日志 out.txt 的输出中包含快照前的数据,且日志的最新时间戳记录与 EBS 快照生成的时间一致。

至此,EBS 快照的创建和恢复操作完成。

总结:

快照被视为保护有状态工作负载数据的关键功能。在此功能推出之前,管理员需要在 EBS 层对 PVC 对应的卷进行手动操作来创建和恢复快照,恢复后的卷还需要以静态卷的方式创建到 EKS 集群中,在使用 CSI 和 动态卷 的场景下,管理员还需要花费精力对比每个相关的 ID 信息避免出现错误。

通过提供在 Kubernetes API 中触发快照操作的方法,管理员现在可以直接在Kubernetes 层创建和管理快照。在管理层面这可以有效减少运维成本,在安全层面也可以进一步控制 EKS 运维人员在 Amazone管理门户 和 API 中的权限,满足安全的最佳实践。

我们希望这篇文章对您使用 Amazon EKS 和 EBS 卷有所帮助。 如果您有任何问题或建议,请随时发表评论。谢谢。

本篇作者

王志达

AWS解决方案架构师,主要负责基础架构如计算、存储的云端设计、改造和优化方案。有多年存储、容器平台和Devops运维经验。