繁体   English   中英

更改 Kube.netes Persistent Volume 的 Storage Class 并保留数据

[英]Change Kubernetes Persistent Volume's Storage Class and keep the data

我有 Elasticsearch 当前在 AKS 上运行并连接到使用高级 SSD 托管磁盘存储 Class 的持久卷的数据 pod,我想将其降级为标准 SSD 托管磁盘而不丢失我在当前使用的持久性上拥有的数据体积。 我创建了一个用标准 SSD 托管磁盘定义的新存储 Class,但如果我从中创建一个新 PV,它显然不会保留旧数据,我需要以某种方式复制它,所以我想知道会是什么切换 PV 存储的最佳实践 Class。

不幸的是,一旦创建了 PVC 并为其配置了 PV,在不创建新 PVC 的情况下唯一可以更改的是卷的大小

在不利用 CSI 快照/克隆的情况下,我能想到的唯一直接的方法是创建一个新的 PVC 并将两个卷挂载到其 Pod 的 Deployment 上具有 root 访问权限和rsync命令。

在这样的 Pod 上运行rsync -a /old/volume/mount/path /new/volume/mount/path应该可以得到你想要的。

但是,您应该确保在删除 PVC 或任何其他使用您的 PV 的资源之前这样做。 默认情况下,大多数默认存储类都会创建具有回收策略的卷,一旦使用它的所有资源都消失,就会立即删除 PV,因此数据丢失的风险很小

由于上述原因,在 Kube.netes 中不可能更改 PVC 的存储 class。 不幸的是,您必须创建一个具有所需存储空间 class 的新 PVC。

go 的一种方法是创建快照,然后从该快照创建新卷: https://kube.netes.io/docs/concepts/storage/volume-snapshots/

另一个是利用 CSI 克隆: https://kube.netes.io/docs/concepts/storage/volume-pvc-datasource/

两者都有效地促进了使用现有数据副本创建新 PV

作为对@LeoD 回答的扩展,我正在分享一个完整的分步指南,说明我最终所做的事情。

  1. 将有状态集缩放为 0。

  2. 在 Azure 找到旧 PV 的 Disk 资源:

  • kubectl describe pv检查哪些 PV 与我要替换的 PVC 相关联。
  • 按照字段DiskURI中指定的资源 ID 获取 Azure 中的磁盘。
  1. 从每个 PVC 磁盘创建一个 Azure 快照资源。

  2. 创建一个新磁盘,其分配的 GiB 至少与当前 PVC 从快照中分配的 GiB 相同。 SKU 在这一点上仍然无关紧要,但我更喜欢使用我想要实施的新 SKU。

  3. 从每个新磁盘创建一个 K8S 持久卷:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-from-azure-disk-0
  namespace: my-namespace
  annotations:
    pv.kubernetes.io/provisioned-by: disk.csi.azure.com
spec:
  capacity:
    storage: 1064
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: managed
  claimRef:
    name: pvc-from-azure-0
    namespace: my-namespace
  csi:
    driver: disk.csi.azure.com
    volumeHandle: /subscriptions/<Your subscription ID>/resourcegroups/<Name of RG where the new Disk is stored at>/providers/microsoft.compute/disks/new-disk-from-pvc-0
    fsType: ext4

确保编辑以下字段:

  • metadata.namespace :到您拥有旧资源的命名空间。
  • spec.capacity.storage :分配给您为新磁盘选择的 GiB。
  • spec.storageClassName :适合您为磁盘选择的 SKU 的存储名称 Class。
  • spec.claimRef.name :这里我们为尚未创建的 PVC 指定一个名称,稍后将使用它,只需确保您在此处选择的名称是您将在接下来创建 PVC 时使用的名称步。
  • spec.claimRef.namespace :到您拥有旧资源的名称空间。
  • csi.volumeHandle :插入新磁盘的资源 ID。
  1. 从您刚刚创建的每个新持久卷创建一个 K8S 持久卷声明:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-from-azure-0
  namespace: my-namespace
spec:
  storageClassName: managed
  volumeName: pv-from-azure-disk-0
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1064

确保编辑以下字段:

  • metadata.name :使用您在 PV 的spec.claimRef.name字段中使用的完全相同的名称。
  • metadata.namespace :到您拥有旧资源的名称空间。
  • spec.storageClassName :到您在spec.storageClassName字段中为 PV 指定的存储名称 Class。
  • spec.volumeName :您在上一步中创建的 PV 的名称。
  • spec.resources.requests.storage :分配给您在 PV 的spec.capacity.storage字段中指定的 GiB。
  1. 对每个要替换的现有 PVC 执行步骤 2-6; 例如,如果您的 Stateful Set 有 3 个 Pod,您应该为每个 Pod 的 PVC 执行 3 次。

  2. 为每个新的 PVC 创建一个 Ubuntu Pod,并将 PVC 挂载到 Pod。 (例如,如果您有 3 个 PVC,则您应该有 3 个 Ubuntu pod,每个 pod 一个)。

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-0
  namespace: my-namespace
spec:
  containers:
   - name: ubuntu-0
     image: ubuntu
     command:
      - "sleep"
      - "604800"
     volumeMounts:
       - mountPath: /mnt/snapshot-data-0
         name: snapshot-data-0
  volumes:
   - name: snapshot-data-0
     persistentVolumeClaim:
       claimName: pvc-from-azure-0

确保编辑以下字段:

  • metadata.namespace :到您拥有旧资源的命名空间。
  • spec.volumes.persistentVolumeClaim.claimName :您创建的新 PVC 的名称。
  1. 执行每个 Ubuntu Pod 并验证您的所有数据都在其中。

  2. 如果所有数据都在那里,您可以删除 Ubuntu Pod。

  3. 现在是非常关键的部分,您需要删除旧的原始 PVC 和 Stateful Set,但在此之前,请确保您拥有 Stateful Set 的原始 yaml 文件或用于创建 Stateful Set 的任何其他文件,确保您知道如何重新创建 Stateful Set ,然后才继续删除旧的原始 PVC 和 Stateful Set。

  4. 删除有状态集和旧 PVC 完成后,在您的有状态集 yaml 或配置中,将volumeClaimTemplates块中的storageClassName值替换为您要使用的新存储 Class。

...

volumeClaimTemplate:
  accessModes: [ "ReadWriteOnce" ]
  storageClassName: "managed" # <--- Edit this field
  resources:
    requests:
      storage: "1064"
    limits:
      storage: "1064"
      
...      
  1. 现在使用新配置重新创建有状态集。 这将重新创建有状态集并创建新的空 PVC,这些 PVC 将使用存储 Class 中新指定的 SKU。

  2. PVC 创建完成后,将新的 Stateful Set 缩放为 0。

  3. 现在重新创建 Ubuntu Pod,但这次同时挂载您在第一步中创建的 Azure 磁盘中的 PVC 和新状态集的新空 PVC:

apiVersion: v1
kind: Pod
metadata:
  name: ubuntu-0
  namespace: my-namespace
spec:
  containers:
   - name: ubuntu-0
     image: ubuntu
     command:
      - "sleep"
      - "604800"
     volumeMounts:
       - mountPath: /mnt/snapshot-data-0
         name: snapshot-data-0
       - mountPath: /mnt/new-data-0
         name: new-data-0           
  volumes:
   - name: snapshot-data-0
     persistentVolumeClaim:
       claimName: pvc-from-azure-0
   - name: new-data-0
     persistentVolumeClaim:
       claimName: my-stateful-set-data-0

确保编辑以下字段:

  • metadata.namespace :到您拥有资源的名称空间。
  • spec.volumes.persistentVolumeClaim :这个有两个字段,一个是snapshot-data-0 ,一个是new-data-0 顾名思义,snapshot-data-0 应该包含我们在第一步中创建的 Azure 磁盘中的旧数据,而 new-data-0 应该是空的,因为它应该是从重新创建的新 PVC有状态集的。 因此,snapshot-data-0 的spec.volumes.persistentVolumeClaim的值应该是您从 Azure 磁盘创建的新 PVC 的名称。 new-data-0 的spec.volumes.persistentVolumeClaim的值应该是在重新创建 Stateful Set 之后创建的新 PVC 的名称。
  1. 执行到 Ubuntu Pod 并执行以下命令:
apt update && apt install rsync -y
nohup rsync -avz /mnt/snapshot-data-0/ /mnt/new-data-0 --log-file=$HOME/.rsyncd.log &

第一个命令是安装rsync ,第二个命令是将所有旧数据复制到新的空 PVC 中,并将命令日志保存在/root/.rsyncd.log以供您检查进度参考。 请注意,根据您存储的数据量,此命令可能需要一些时间。 就我个人而言,大约需要 1 小时才能完成。

  1. 对每个备份的和旧的 PVC 对执行步骤 15-16。

  2. 完成所有 PVC 对后,删除 Ubuntu Pod。

  3. 扩展新的有状态集备份。

  4. 利润。 您现在拥有具有相同数据但具有不同存储类的相同状态集。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM