文章目录


容器一直被认为非常适合无状态应用程序。但大多数实际用例都需要某种数据持久性。为了支持这样的用例,Kubernetes 引入了有状态工作负载的概念。

我们最近开发的一些云原生应用程序用于集群数据库(例如使用其操作符部署的 MongoDB),以利用使 Kubernetes 成为云部署平台的弹性、自动扩展和其他生命周期特性。

在运行集群内数据库时,定期备份同样重要。虽然对于原生 Kubernetes 资源来说,使用 etcd 备份就足够了,并且 Velero 等工具在备份/恢复 Kubernetes 资源方面做得非常出色,但卷备份带来了挑战,尽管 Velero 确实支持使用 restic 进行卷备份,但这是一种非常基本的方式进行备份。此外,静态备份总是进行完整备份,这可能会导致 RTO 的扩展以及其他复杂性,因为数据量的增长。


在这篇博文中,我们将展示另一种进行卷备份的方法,即在 AWS 云中使用卷快照。请注意,在编写卷备份时,很大程度上依赖于云提供商,Kubernetes 本身不支持卷快照的 DR,即它不支持在新区域的新集群中恢复数据。

值得庆幸的是,大多数云提供商都支持卷快照、将快照移动到恢复区域并使用这些快照进行恢复。

以下是支持卷快照的云提供商​​列表​​。


本博客中使用的一些 Kubernetes 组件是

​Persistent Volume (PV)​

表示物理存储的抽象。

​StorageClass​

创建 PV 的存储类型。例如,PersistenceVolumeClass 可以来自 AWS gp2 或 io1。它也可以来自具有特定 RAID 选项的本地磁盘或 NFS 分区。

​PersistentVolumeClaim (PVC)​

对 PV 上特定资源的声明。PVC 消耗 PV 的特定大小和访问模式以及其他特性。为了让 pod 挂载 PV 存储类型,它必须首先在该 PV 上创建声明。虽然在 k8s pod 上挂载存储的过程中,它就像 PVC 是卷一样运行,而实际上 PVC 本身并不代表任何物理存储,而是使用物理存储的权利。

​VolumeSnapshotContent​

这与 PV 类似,因为它表示某些物理存储上数据的实际快照。这通常由 PVC 创建,但也可以预先配置。

​VolumeSnapshot​

VolumeSnapshot 与 VolumeSnapshotContent 的关系类似于 PVC 与 PV 的关系。VolumeSnapshotContent 是物理存储,而 VolumeSnapshot 是它的接口。VolumeSnapshot 表示来自 PVC 的快照请求,它维护从 PVC 持有的数据到 VolumeSnapshotContent 创建快照的状态。它还可以用作从其绑定的 VolumeSnapshotContent 的内容创建 PVC 的源。

​VolumeSnapshotClass​

这类似于 SnapshotClass,因为它描述了 VolumeSnapshotContent 的属性。在这种情况下,最重要的属性是 ebs.csi.aws.com 驱动程序。

下图表示我们将用于此博客的用例

用于灾难恢复的 Kubernetes 卷备份_数据

让我们了解所涉及的所有步骤。

  1. 部署使用 pvc 实现持久性的示例应用程序并将一些示例数据添加到此卷
  2. 使用卷快照备份卷
  3. 将快照复制到部署第二个集群的另一个区域 (eu-west-2)
  4. 使用 AWS 复制的快照在第二个 OCP 集群中创建 VolumeSnapshotContent 和 VolumeSnapshot
  5. 使用新创建的 VolumeSnapshot 在第二个集群中创建应用程序 PVC 并验证还原

先决条件

  1. 我们在 AWS 中部署了两个 OpenShift 集群,它们应该位于两个不同的区域(us-east-1 和 eu-west-2)。
  2. 应用程序已安装并运行在其中一个集群上,我们将在其中启动应用程序卷备份并将其恢复到另一个集群上。
  3. 应在两个集群上安装与 CSI 驱动程序兼容的存储类。
  4. 确保在这两个集群上安装了卷快照 CRD 和卷快照控制器,如果没有,请执行以下步骤。
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
  1. VolumeSnapshotClass 也应该在两个集群中创建
  • 确保​​deletionPolicy​​ 使用 Retain,否则一旦通过删除应用程序命名空间或从 kubernetes 集群删除了 volumesnapshot,快照就会从 AWS 中删除。

解决方案

我们现在依次执行以下所有步骤,以演示使用 AWS 快照备份和还原应用程序及其卷 (PVC)。

这里包含此博客中使用的代码​​git 存储库​

步骤 1. 部署使用 pvc 进行持久性的示例应用程序并将一些示例数据添加到此卷

我们部署了一个简单的应用程序,其中包含一个 pod (test-pod) 和一个附加到该 pod 的 PVC (pvc-002) 以实现数据持久性。此应用程序安装在 AWS us-east-1 区域上运行的第一个集群上。

Pod 定义:

apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: csi-app
labels:
app: test-pod
spec:
containers:
- image: quay.io/libpod/ubuntu
name: test-pod
command: ["sleep","1000"]
volumeMounts:
- mountPath: /myvolumepath
name: mydata
volumes:
- name: mydata
persistentVolumeClaim:
claimName: pvc-002

PVC 定义:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: csi-app
name: pvc-002
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: gp2-csi

然后我们使用示例文件 sample.txt 将一些示例数据添加到应用程序的挂载点 (/myvolumepath)

用于灾难恢复的 Kubernetes 卷备份_数据_02

步骤 2. 使用卷快照备份卷

现在,我们创建一个卷快照,它将备份应用程序 PVC,这将在 AWS 中创建一个快照。我们运行以下命令来创建 PVC 的快照。

用于灾难恢复的 Kubernetes 卷备份_应用程序_03

VolumeSnapshot 定义

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
name: pvc002-snapshot
spec:
volumeSnapshotClassName: csi-aws-vsc
source:
persistentVolumeClaimName: pvc-002

一旦我们为 PVC 创建了卷快照,在 AWS 环境的同一个区域 us-east-1 中也会创建一个快照。

用于灾难恢复的 Kubernetes 卷备份_kubernetes_04

步骤 3. 将快照复制到部署第二个集群的另一个 AWS 区域 (eu-west-2)

我们可以按照下图使用 AWS 控制台复制此快照。我们需要在页面上指定目标区域和描述,然后将在第二个区域创建快照,该区域是第一个区域的副本。

用于灾难恢复的 Kubernetes 卷备份_kubernetes_05

复制的快照是在 AWS 的 eu-west-2 区域中创建的。

用于灾难恢复的 Kubernetes 卷备份_数据_06

步骤 4. 使用 AWS 复制的快照在第二个 OCP 集群(我们的恢复集群)中创建 VolumeSnapshotContent 和 VolumeSnapshot

现在,我们使用新复制的快照在 AWS 的 eu-west-2 区域中部署的第二个 OCP 集群中创建一个 VolumeSnapshotContent。

我们使用以下命令来创建它。注意,我们在 VolumeSnapshotContent 定义中提到了 snapshotHandle 参数的 Snapshot ID 。我们可以在 AWS 控制台上获取这个值(快照 ID 以 snap-开头)。

用于灾难恢复的 Kubernetes 卷备份_应用程序_07

VolumeSnapshotContent 定义

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotContent
metadata:
name: test-snapshot-content
spec:
deletionPolicy: Delete
driver: ebs.csi.aws.com
source:
snapshotHandle: snap-026780e8ff3bd6e74
volumeSnapshotClassName: csi-aws-vsc
volumeSnapshotRef:
name: restore-snapshot
namespace: csi-app

接下来,我们使用新创建的 VolumeSnapshotContent 在第二个 OCP 集群上创建 VolumeSnapshot。

用于灾难恢复的 Kubernetes 卷备份_持久性_08

VolumeSnapshot 定义

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
name: restore-snapshot
spec:
source:
volumeSnapshotContentName: test-snapshot-content

步骤 5. 使用新创建的 VolumeSnapshot 在第二个集群中创建应用程序 PVC 并验证还原

我们需要在 spec 部分指定 VolumeSnapshot 名称和存储类名称。

用于灾难恢复的 Kubernetes 卷备份_应用程序_09

PVC 定义:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: csi-app
name: pvc-002
spec:
storageClassName: gp2-csi
dataSource:
name: restore-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

最后,在第二个 OCP 集群中创建 POD,该集群使用新创建的 PVC 指向使用相同 POD 定义恢复的数据。

登录 POD 并使用卷快照检查数据是否在挂载点正确恢复。

我们可以看到 sample.txt 文件存在于挂载路径中,该文件与我们在第一个集群上运行的应用程序中写入的数据相同。

用于灾难恢复的 Kubernetes 卷备份_kubernetes_10

结论

在上面的博客文章中,我们演示了如何拍摄卷快照,将其移动到不同的区域,并使用相同的快照重新创建卷。也可以使用 Velero 拍摄快照,但是在新集群/区域中移动到不同的区域恢复并不能使用 Velero 开箱即用。这是满足我们解决卷的 DR 要求的方法之一。

翻译

​Kubernetes volume backup for disaster recovery​

关注

微信公众号【我的小碗汤】,扫左侧码关注,了解更多咨询,更有免费资源供您学习