如何在 Amazon EKS 中恢复、创建 EBS 永久存储快照或调整其大小,以进行灾难恢复,或者在超过 EBS 修改速率时执行这些操作?

上次更新日期:2022 年 11 月 9 日

我想使用 Amazon Elastic Kubernetes Service (Amazon EKS) 中的 Amazon Elastic Block Store (Amazon EBS) 永久存储快照进行灾难恢复。如何创建、恢复此类快照或调整其大小? 或者,我超过了我的 Amazon EBS 修改速率。但我仍然需要在 Amazon EKS 中恢复、创建我的 Amazon EBS 永久存储的快照或调整其大小。

简短描述

您正在修改 Amazon EKS 中的 Amazon EBS 永久存储,但收到以下错误:

errorCode:Client.VolumeModificationRateExceeded
errorMessage:您已达到每个卷的最大修改速率限制。每个 EBS 卷在两次修改之间至少等待 6 小时

修改卷后,必须等待至少六小时才能继续修改该卷。再次修改之前,确保该卷处于使用中可用状态。

您的组织可能有一个灾难恢复(DR)目标,其恢复时间目标(RTO)少于六小时。对于少于六小时的 RTO,使用 Amazon EBS Container Storage Interface(CSI)驱动程序创建快照并恢复您的卷。

解决方法

注意:如果您在运行 AWS 命令行界面(AWS CLI)命令时收到错误,请确保您运行的是最新版本的 AWS CLI

使用 Amazon EBS CSI 驱动程序和外部快照器执行以下操作:

  1. 创建 PersistentVolumeClaim 的 Amazon EBS 快照。
  2. 恢复 PersistentVolumeClaim
  3. PersistentVolumeClaim 绑定到工作负载。

先决条件:

使用外部快照器安装 Amazon EBS CSI 驱动程序

1.    检查您的集群上是否存在现有的 IAM OpenID Connect(OIDC)提供程序:

% cluster_name=ebs
% oidc_id=$(aws eks describe-cluster --name cluster_name --query "cluster.identity.oidc.issuer" --output text | cut -d '/' -f 5)
% aws iam list-open-id-connect-providers | grep $oidc_id

注意:cluster_name 替换为您的集群名称。

示例输出:

"Arn": "arn:aws:iam::XXXXXXXXXX:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/B7E2BC2980D17C9A5A3889998CB22B23"

注意:如果您没有 IAM OIDC 提供程序,请为您的集群创建一个

2.    安装外部快照器。
注意:在安装 Amazon EBS CSI 附加组件之前,必须安装外部快照器。此外,必须按以下顺序安装外部快照器组件:

用于 volumesnapshotclassesvolumesnapshotsvolumesnapshotcontentsCustomResourceDefinition(CRD)

mkdir crd
cd crd
wget https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/kustomization.yaml
wget https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml
wget https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml
wget https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml
kubectl apply -k ../crd

RBAC,例如 ClusterRoleClusterRoleBinding

kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml

控制器部署

kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml

3.    使用 eksctl 创建您的 Amazon EBS CSI 插件 IAM 角色:

eksctl create iamserviceaccount \
  --name ebs-csi-controller-sa \
  --namespace kube-system \
  --cluster cluster_name \
  --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
  --approve \
  --role-only \
  --role-name AmazonEKS_EBS_CSI_DriverRole

4.    使用 eksctl 添加 Amazon EBS CSI 附加组件:

eksctl create addon --name aws-ebs-csi-driver --cluster cluster_name --service-account-role-arn arn:aws:iam::account_id:role/AmazonEKS_EBS_CSI_DriverRole --force

注意:account_id 替换为您的 AWS 账户 ID。

5.    确认 Amazon EBS CSI 驱动程序和外部快照器容器组(pod)正在运行:

% kubectl get pods -A | egrep "csi|snapshot"

使用 Amazon EBS 持久存储创建 StatefulSet

1.    从 GitHub 网站下载清单

2.    创建 StorageClassVolumeSnapshotClass

% kubectl apply -f manifests/classes/

示例输出:

volumesnapshotclass.snapshot.storage.k8s.io/csi-aws-vsc created
storageclass.storage.k8s.io/ebs-sc created

3.    将 StatefulSet 与 PersistentVolumeClaim 一起部署到您的集群上:

% kubectl apply -f manifests/app/

示例输出:

service/cassandra created
StatefulSet.apps/cassandra created

4.    验证容器组(pod)是否处于 Running(正在运行)状态:

% kubectl get pods

示例输出:

NAME         READY  STATUS   RESTARTS  AGE
cassandra-0  1/1    Running  0         33m
cassandra-1  1/1    Running  0         32m
cassandra-2  1/1    Running  0         30m

5.    验证 PersistenVolumeClaim 是否绑定到您的 PersisentVolume

% kubectl get pvc

示例输出:

NAME                                              STATUS  VOLUME                                    CAPACITY ACCESS MODES STORAGECLASS  AGE

persistentvolumeclaim/cassandra-data-cassandra-0  Bound   pvc-b3ab4971-37dd-48d8-9f59-8c64bb65b2c8  2Gi      RWO          ebs-sc        28m
persistentvolumeclaim/cassandra-data-cassandra-1  Bound   pvc-6d68170e-2e51-40f4-be52-430790684e51  2Gi      RWO          ebs-sc        28m
persistentvolumeclaim/cassandra-data-cassandra-2  Bound   pvc-d0403adb-1a6f-44b0-9e7f-a367ad7b7353  2Gi      RWO          ebs-sc        26m
...

注意:请注意每个 PersistentVolumeClaim 的名称,以便与快照清单中的 PersistentVolumeClaim 名称进行比较。

6.    要测试 StatefulSet,请将内容写入 PersistentVolumeClaim

for i in {0..2}; do kubectl exec "cassandra-$i" -- sh -c 'echo "$(hostname)" > /cassandra_data/data/file.txt'; done

创建快照

快照清单中的 persistentVolumeClaimName 必须与您在 StatefulSet 中为每个容器组(pod)创建的 PersistentVolumeClaim 的名称相匹配。例如:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: cassandra-data-snapshot-0
spec:
  volumeSnapshotClassName: csi-aws-vsc
  source:
    persistentVolumeClaimName: cassandra-data-cassandra-0

1.    从每个 PersistenVolumeClaim 中创建一个快照:

% kubectl apply -f manifests/snapshot/

示例输出:

volumesnapshot.snapshot.storage.k8s.io/cassandra-data-snapshot-0 created
volumesnapshot.snapshot.storage.k8s.io/cassandra-data-snapshot-1 created
volumesnapshot.snapshot.storage.k8s.io/cassandra-data-snapshot-2 created

2.    状态完成后,验证快照在 Amazon Elastic Compute Cloud(Amazon EC2)控制台上是否可用:

aws ec2 describe-snapshots --filters "Name=tag-key,Values=*ebs*" --query 'Snapshots[*].{VOL_ID:VolumeId,SnapshotID:SnapshotId,State:State,Size:VolumeSize,Name:[Tags[?Key==`Name`].Value] [0][0]}' --output table
---------------------------------------------------------------------------------------------------------------------------------------
|                                                          DescribeSnapshots                                                          |
+------------------------------------------------------------+-------+-------------------------+------------+-------------------------+
|                            Name                            | Size  |       SnapshotID        |   State    |         VOL_ID          |
+------------------------------------------------------------+-------+-------------------------+------------+-------------------------+
|  ebs-dynamic-snapshot-c6c9cb3c-2dab-4833-9124-40a0abde170d |  2    |  snap-057c5e2de3957d855 |  pending   |  vol-01edf53ee26a615f5  |
|  ebs-dynamic-snapshot-1c1ad0c5-a93a-468f-ab54-576db5d630d4 |  2    |  snap-02bf49a3b78ebf194 |  completed |  vol-0289efe54525dca4a  |
|  ebs-dynamic-snapshot-760c48e7-33ff-4b83-a6fb-6ef13b8d31b7 |  2    |  snap-0101c3d2efa40af19 |  completed |  vol-0fe68c9ac2f6375a4  |
+------------------------------------------------------------+-------+-------------------------+------------+-------------------------+

恢复快照

您可以使用与 PersistentVolumeClaim 相同的名称从现有 PersistentVolumeClaim 创建的快照中恢复 PersistentVolumeClaim。当您重新创建 StatefulSet 时,PersistentVolumeClaim 会动态配置一个 PersistentVolume 并自动绑定到 StatefulSet 容器组(pod)。StatefulSet PersistenVolumeClaim 名称格式为:`PVC_TEMPLATE_NAME-STATEFULSET_NAME-REPLICA_INDEX`。

要恢复快照,请执行以下步骤:

1.    删除现有的 StatefulSet 工作负载:

kubectl delete -f manifests/app/Cassandra_statefulset.yaml

注意:删除工作负载也会删除 StatefulSet 容器组(pod)。您创建的快照充当备份。

示例输出:

statefulset.apps "cassandra" deleted

2.    强制删除 PersistentVolumeClaim

for i in {0..2}
do
  kubectl delete pvc cassandra-data-cassandra-$i --force
done

注意:删除 PersistentVolumeClaim 也会删除 PersistentVolume

3.    使用与您创建的 PersistentVolumeClaim 相同的名称从快照中恢复 PersistentVolumeClaim

kubectl apply -f manifests/snapshot-restore/

示例输出:

persistentvolumeclaim/cassandra-data-cassandra-0 created
persistentvolumeclaim/cassandra-data-cassandra-1 created
persistentvolumeclaim/cassandra-data-cassandra-2 created

4.    验证每个 PersistentVolumeClaim 是否处于 Pending(待处理)状态:

kubectl get pvc

示例输出:

NAME                         STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
cassandra-data-cassandra-0   Pending                                      ebs-sc         24s
cassandra-data-cassandra-1   Pending                                      ebs-sc         23s
cassandra-data-cassandra-2   Pending                                      ebs-sc         22s

5.    使用原始清单重新创建 StatefulSet:

kubectl apply -f manifests/app-restore/

注意:要调整存储的大小,请使用新的存储大小定义 StatefulSet。

示例输出:

StatefulSet.apps/cassandra created

6.    检查 Amazon EBS 存储的内容以确认快照和恢复正常运行:

for i in {0..2}; do kubectl exec "cassandra-$i" -- sh -c 'cat /cassandra_data/data/file.txt'; done
cassandra-0
cassandra-1
cassandra-2

调整 PersistentVolumeClaim 的大小

您可以修改 PersistentVolumeClaim.spec.resources.requests.storage,以自动反映您在 StatefulSet 清单中定义的大小:

for i in {0..2}
do
  echo "Resizing cassandra-$i"
  kubectl patch pvc cassandra-data-cassandra-$i -p '{ "spec": { "resources": { "requests": { "storage": "4Gi" }}}}'
done

注意:4Gi 是存储大小的示例。定义适合您的使用案例的存储大小。

确认新的存储大小已反映在 Amazon EC2 控制台和容器组(pod)中:

% aws ec2 describe-volumes --filters "Name=tag-key,Values=*pvc*" --query 'Volumes[*].{ID:VolumeId,Size:Size,Name:[Tags[?Key==`Name`].Value] [0][0]}' --output table
-------------------------------------------------------------------------------------------
|                                     DescribeVolumes                                     |
+------------------------+--------------------------------------------------------+-------+
|           ID           |                         Name                           | Size  |
+------------------------+--------------------------------------------------------+-------+
|  vol-01266a5f1f8453e06 |  ebs-dynamic-pvc-359a87f6-b584-49fa-8dd9-e724596b2b43  |  4    |
|  vol-01b63a941450342d9 |  ebs-dynamic-pvc-bcc6f2cd-383d-429d-b75f-846e341d6ab2  |  4    |
|  vol-041486ec92d4640af |  ebs-dynamic-pvc-fa99a595-84b7-49ad-b9c2-1be296e7f1ce  |  4    |
+------------------------+--------------------------------------------------------+-------+

% for i in {0..2}
do
  echo "Inspecting cassandra-$i"
  kubectl exec -it cassandra-$i -- lsblk
  kubectl exec -it cassandra-$i -- df -h
done...

运行以下 Kubectl 命令来清理您的 StatefulSet

要删除您为 StatefulSet 创建的资源,请运行以下 kubectl 命令:

app-restore

kubectl delete -f manifests/app-restore

snapshot-restore

kubectl delete -f manifests/snapshot-restore

snapshot

kubectl delete -f manifests/snapshot

classes

kubectl delete -f manifests/classes

Cassandra

kubectl delete -f manifests/app/Cassandra_service.yaml

这篇文章对您有帮助吗?


您是否需要账单或技术支持?