从 LVM 存储中移除磁盘、设备类卷组或节点

本文介绍如何移除故障磁盘、从设备类中移除设备类卷组,以及移除 LVM Storage 中的存储节点。

根据故障范围,本文涵盖以下场景:

  • 从 device-class volume group 中移除 volume group device
  • 从 device class 中移除 device-class volume group
  • 移除 TopoLVM 存储节点
风险警告
  • 本文中的操作步骤会直接删除 PVC、PV 和 logicalvolumes.topolvm.cybozu.com 等存储资源。删除这些资源后,受影响卷中的数据通常无法恢复。请提前备份数据。
  • 继续操作之前,请确认已识别出正确的磁盘、设备类卷组或节点,并为受影响的工作负载安排维护窗口。

术语

术语描述
设备类由不同节点上的一个或多个设备类卷组组成的逻辑存储类。
设备类卷组节点上的一个 LVM volume group,表示设备类在该节点上的存储资源。
卷组设备节点上的磁盘。在 LVM 中,它对应于物理卷。

选择正确的场景

使用下表确定适用于您环境的场景。

条件场景 1:移除卷组设备场景 2:移除设备类卷组场景 3:移除 TopoLVM 存储节点
节点可访问性节点仍可访问。节点仍可访问。节点已无法恢复,或者您已决定将其从 TopolvmCluster 中永久移除。
卷组状态目标 LVM volume group 仍然存在且仍可识别。目标 LVM volume group 已不存在或已无法识别,但节点仍保留。该节点及其上的所有设备类卷组将一起移除。
移除范围从卷组中移除一个或多个故障磁盘。从保留的节点中移除一个设备类卷组。从 TopolvmCluster 中移除整个节点。
保留计划保留节点和设备类卷组。保留节点,但不保留目标设备类卷组。既不保留节点,也不保留该节点上的任何设备类卷组。

场景 1:从设备类卷组中移除卷组设备

用户场景

  • 当 device-class volume group 未完全损坏,但卷组中的一个或多个 volume group devices 发生故障且必须移除时,请使用此操作步骤。

前提条件

  • 目标节点仍在集群中且可访问。
  • 目标设备类的 Provision Type 为 Thick。
  • 目标设备类卷组未完全损坏,并且卷组中至少保留一个正常的卷组设备。

检查设备类卷组是否仍可恢复

在目标节点上运行以下命令:

vgs <vg-name>

参数:

  • <vg-name>:目标 LVM 卷组的名称。

如果命令返回正常输出,或者仅报告部分 PV 缺失但卷组仍然存在,则设备类卷组未完全损坏,您可以按照此操作步骤执行。

示例输出:

WARNING: Couldn't find device with uuid VJes6j-2a8V-8Cxf-eW84-yEJK-K24A-yBc9OD.
WARNING: VG hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33 is missing PV VJes6j-2a8V-8Cxf-eW84-yEJK-K24A-yBc9OD (last written to /dev/vdb).
WARNING: Couldn't find all devices for LV hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33/b6b331f0-5242-420f-a531-df90628bef80 while checking used and assumed devices.

操作步骤

步骤 1:停止 topolvm-operator

在控制平面节点上运行以下命令,以防止 operator 在清理期间协调资源:

kubectl -n nativestor-system scale --replicas 0 deployment topolvm-operator

步骤 2:查找受影响的 LVM 逻辑卷

在目标节点上运行以下命令,查找使用故障磁盘的逻辑卷:

lvs -a -o +devices <vg-name> | egrep "<path-to-disks>|unknown device" | awk '{print $1}'

参数:

  • <vg-name>:目标 LVM 卷组的名称。
  • <path-to-disks>:故障磁盘的设备路径,例如 /dev/vdb。如果需要匹配多个磁盘,请使用 | 分隔它们。

例如:

lvs -a -o +devices hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33 2>/dev/null | egrep "/dev/vdb|unknown" | awk '{print $1}'

示例输出:

b6b331f0-5242-420f-a531-df90628bef80

步骤 3:查找受影响的 PVC 和 PV

在控制平面节点上运行以下命令,通过逻辑卷名称查找关联的 PV 和 PVC:

kubectl get pv -o json | jq -r --arg HANDLE <lv-name> '
  .items[]
  | select(.spec.csi.volumeHandle == $HANDLE)
  | [.metadata.name, .spec.claimRef.namespace, .spec.claimRef.name]
  | @tsv
'

参数:

  • <lv-name>:受影响的 LVM 逻辑卷的名称。

示例输出:

pvc-e11f6c18-0e15-4c70-9a24-e7136fabfb2f	demo-space	pvc-topolvm

在输出中:

  • 第 1 列是 PersistentVolume 的名称。
  • 第 2 列是 PersistentVolumeClaim 的命名空间。
  • 第 3 列是 PersistentVolumeClaim 的名称。

步骤 4:停止使用受影响 PVC 的工作负载

确定受影响的 PVC 后,停止使用这些 PVC 的工作负载,并确认所有相关 Pod 均已停止,然后再继续。

步骤 5:删除受影响的 Kubernetes 存储资源

在控制平面节点上运行以下命令:

kubectl delete pvc -n <pvc-namespace> <pvc-name>
kubectl delete pv <pv-name>
kubectl delete logicalvolumes.topolvm.cybozu.com <logicalvolume-name>

参数:

  • <pvc-namespace>:受影响 PVC 的命名空间。
  • <pvc-name>:受影响 PVC 的名称。
  • <pv-name>:受影响 PV 的名称。
  • <logicalvolume-name>:TopoLVM logicalvolumes.topolvm.cybozu.com 资源的名称。它与 <pv-name> 相同。

如果查询结果包含多个资源,请按照映射关系逐一删除。

如果某个资源无法正常删除,请根据需要添加 --force。

步骤 6:清理残留的 LVM 逻辑卷

在目标节点上运行以下命令,检查是否仍有逻辑卷存在:

lvs -a -o +devices <vg-name> 2>/dev/null | egrep "<path-to-disks>|unknown device" | awk '{print $1}'

参数:

  • <vg-name>:目标 LVM 卷组的名称。
  • <path-to-disks>:故障磁盘的设备路径,例如 /dev/vdb。如果需要匹配多个磁盘,请使用 | 分隔它们。

如果命令仍返回输出,请逐一删除剩余的逻辑卷:

lvremove <vg-name>/<lv-name>

参数:

  • <vg-name>:目标 LVM 卷组的名称。
  • <lv-name>:要移除的逻辑卷的名称。

如有需要,添加 --force。

步骤 7:从 LVM 卷组中移除缺失的物理卷

在目标节点上运行以下命令:

vgreduce --removemissing <vg-name>

参数:

  • <vg-name>:目标 LVM 卷组的名称。

如有需要,添加 --force。

步骤 8:更新 TopolvmCluster 资源

在控制平面节点上运行以下命令:

kubectl -n nativestor-system edit topolvmclusters.topolvm.cybozu.com topolvm

在编辑器中,从目标节点的 devices 列表中移除故障卷组设备。例如,从 nodeName: 192.168.133.50 的配置中移除 /dev/vdb。

修改前:

spec:
  storage:
    deviceClasses:
      - classes:
          - className: hdd
            default: true
            devices:
              - name: /dev/vdb
                type: disk
              - name: /dev/vdc
                type: disk
            volumeGroup: hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33
        nodeName: 192.168.133.50

修改后:

spec:
  storage:
    deviceClasses:
      - classes:
          - className: hdd
            default: true
            devices:
              - name: /dev/vdc
                type: disk
            volumeGroup: hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33
        nodeName: 192.168.133.50

步骤 9:更新 lvmdconfig ConfigMap

在控制平面节点上运行以下命令:

kubectl -n nativestor-system edit configmaps lvmdconfig-<node-name>

参数:

  • <node-name>:目标节点的名称。

在编辑器中,从 status.json 中移除故障卷组设备的状态。例如,移除 /dev/vdb 的 deviceStates 条目。

修改前:

status.json: '{"node":"192.168.133.50","phase":"","failClasses":[],"successClasses":[{"className":"hdd","vgName":"hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33","state":"Ready","message":"create successful","deviceStates":[{"name":"/dev/vdb","state":"Online"},{"name":"/dev/vdc","state":"Online"}]}],"loops":[],"raids":[]}'

修改后:

status.json: '{"node":"192.168.133.50","phase":"","failClasses":[],"successClasses":[{"className":"hdd","vgName":"hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33","state":"Ready","message":"create successful","deviceStates":[{"name":"/dev/vdc","state":"Online"}]}],"loops":[],"raids":[]}'

步骤 10:启动 topolvm-operator

在控制平面节点上运行以下命令:

kubectl -n nativestor-system scale --replicas 1 deployment topolvm-operator

步骤 11:验证卷组设备已移除

在控制平面节点上运行以下命令:

kubectl -n nativestor-system get topolvmclusters.topolvm.cybozu.com topolvm -o jsonpath="{.status.nodeStorageState}" | jq

确认已移除的卷组设备不再显示在目标节点的 deviceStates 中。

场景 2:从设备类中移除设备类卷组

用户场景

  • 当节点上的设备类卷组完全损坏,无法仅通过移除单个卷组设备进行恢复时,使用此操作步骤。

前提条件

  • 目标节点仍在集群中且可访问。
  • 目标设备类卷组已完全损坏。
  • 移除目标设备类卷组后,节点上至少保留一个其他设备类卷组。

检查设备类卷组是否已完全损坏

在目标节点上运行以下命令:

vgs

如果输出中不再显示目标 LVM volume group,则表示设备类卷组已完全损坏,您可以按照此操作步骤执行。

注意

此场景会从节点中移除整个设备类卷组,而不仅仅是移除该卷组中的单个卷组设备。

操作步骤

步骤 1:停止 topolvm-operator

在控制平面节点上运行以下命令:

kubectl -n nativestor-system scale --replicas 0 deployment topolvm-operator

步骤 2:查找受影响的 PVC 和 PV

在控制平面节点上运行以下命令,以查找目标节点上与指定存储类关联的 PV、PVC 和 logicalvolumes.topolvm.cybozu.com 资源:

kubectl get pv -o json | jq -r --arg NODE <node-name> --arg SC <storageclass-name> '
  .items[]
  | select(.spec.nodeAffinity.required.nodeSelectorTerms[]?.matchExpressions[]? | select(.key=="topology.topolvm.cybozu.com/node") | .values[]? == $NODE)
  | select(.spec.storageClassName == $SC)
  | [.metadata.name, .spec.claimRef.namespace, .spec.claimRef.name]
  | @tsv
'

参数:

  • <node-name>:目标节点的名称。
  • <storageclass-name>:与目标设备类卷组关联的存储类名称。如果涉及多个存储类,请针对每个存储类分别运行查询。

示例输出:

pvc-e11f6c18-0e15-4c70-9a24-e7136fabfb2f	demo-space	pvc-topolvm

在输出中:

  • 第 1 列是 PersistentVolume 和 logicalvolumes.topolvm.cybozu.com 资源的名称。
  • 第 2 列和第 3 列是 PersistentVolumeClaim 的命名空间和名称。

如果目标设备类卷组关联了多个存储类,请针对每个存储类重复此查询以及后续清理步骤。

步骤 3:停止使用受影响 PVC 的工作负载

确定受影响的 PVC 后,停止使用这些 PVC 的工作负载,并确认所有相关 Pod 均已停止,然后再继续。

步骤 4:删除受影响的 Kubernetes 存储资源

在控制平面节点上运行以下命令:

kubectl delete pvc -n <pvc-namespace> <pvc-name>
kubectl delete pv <pv-name>
kubectl delete logicalvolumes.topolvm.cybozu.com <logicalvolume-name>

参数:

  • <pvc-namespace>:受影响 PVC 的命名空间。
  • <pvc-name>:受影响 PVC 的名称。
  • <pv-name>:受影响 PV 的名称。
  • <logicalvolume-name>:TopoLVM logicalvolumes.topolvm.cybozu.com 资源的名称。它与 <pv-name> 相同。

如果查询结果包含多个资源,请根据映射关系逐个删除。

如果某个资源无法正常删除,请根据需要添加 --force。

步骤 5:更新 TopolvmCluster 资源

在控制平面节点上运行以下命令:

kubectl -n nativestor-system edit topolvmclusters.topolvm.cybozu.com topolvm

在编辑器中,从目标节点移除设备类卷组。例如,在 nodeName: 192.168.140.13 的配置中,移除 className: hdd 条目及其关联的 volumeGroup 和 devices 配置。

之前:

spec:
  storage:
    deviceClasses:
      - classes:
          - className: ssd
            default: true
            devices:
              - name: /dev/vdc
                type: disk
            volumeGroup: ssd-4a8737fc-48d3-4c61-882d-0a5bcc6f77a1
          - className: hdd
            devices:
              - name: /dev/vdb
                type: disk
            volumeGroup: hdd-97dc00f3-1df6-4f64-8ddc-7b0b6c5d6de5
        nodeName: 192.168.140.13

之后:

spec:
  storage:
    deviceClasses:
      - classes:
          - className: ssd
            default: true
            devices:
              - name: /dev/vdc
                type: disk
            volumeGroup: ssd-4a8737fc-48d3-4c61-882d-0a5bcc6f77a1
        nodeName: 192.168.140.13

如果移除的 className 条目包含 default: true,请将另一个保留的类指定为默认类。

步骤 6:更新 lvmdconfig ConfigMap

在控制平面节点上运行以下命令:

kubectl -n nativestor-system edit configmaps lvmdconfig-<node-name>

参数:

  • <node-name>:目标节点的名称。

在编辑器中,从 lvmd.yaml 和 status.json 中移除与目标设备类卷组对应的配置。例如,移除 className: hdd 的配置。

之前:

lvmd.yaml: |
  socket-name: /run/topolvm/lvmd.sock
  device-classes:
  - name: ssd
    volume-group: ssd-4a8737fc-48d3-4c61-882d-0a5bcc6f77a1
    default: true
    type: thick
  - name: hdd
    volume-group: hdd-97dc00f3-1df6-4f64-8ddc-7b0b6c5d6de5
    default: false
    type: thick
status.json: '{"node":"192.168.140.13","phase":"","failClasses":[],"successClasses":[{"className":"hdd","vgName":"hdd-97dc00f3-1df6-4f64-8ddc-7b0b6c5d6de5","state":"Ready","message":"create successful","deviceStates":[{"name":"/dev/vdb","state":"Online"}]},{"className":"ssd","vgName":"ssd-4a8737fc-48d3-4c61-882d-0a5bcc6f77a1","state":"Ready","message":"create successful","deviceStates":[{"name":"/dev/vdc","state":"Online"}]}],"loops":[],"raids":[]}'

之后:

lvmd.yaml: |
  socket-name: /run/topolvm/lvmd.sock
  device-classes:
  - name: ssd
    volume-group: ssd-4a8737fc-48d3-4c61-882d-0a5bcc6f77a1
    default: true
    type: thick
status.json: '{"node":"192.168.140.13","phase":"","failClasses":[],"successClasses":[{"className":"ssd","vgName":"ssd-4a8737fc-48d3-4c61-882d-0a5bcc6f77a1","state":"Ready","message":"create successful","deviceStates":[{"name":"/dev/vdc","state":"Online"}]}],"loops":[],"raids":[]}'

如果移除的 className 条目包含 default: true,请将另一个保留的类指定为默认类。

步骤 7:启动 topolvm-operator

在控制平面节点上运行以下命令:

kubectl -n nativestor-system scale --replicas 1 deployment topolvm-operator

步骤 8:验证设备类卷组已移除

在控制平面节点上运行以下命令:

kubectl -n nativestor-system get topolvmclusters.topolvm.cybozu.com topolvm -o jsonpath="{.status.nodeStorageState}" | jq

确认目标节点上不再显示已移除的设备类卷组,并确认剩余的设备类卷组运行状况正常。

场景 3:移除 TopoLVM 存储节点

用户场景

  • 目标节点已无法恢复,或者您已决定将其从 TopolvmCluster 中永久移除。

前提条件

  • 您已决定不保留目标节点上的任何设备类卷组。
  • 使用目标节点上本地卷的工作负载已停止,或已迁移到其他节点。
  • 移除目标节点后,剩余节点仍可继续承载所需的工作负载。

操作步骤

步骤 1:停止 topolvm-operator

在控制平面节点上运行以下命令:

kubectl -n nativestor-system scale --replicas 0 deployment topolvm-operator

步骤 2:查找受影响的 PVC 和 PV

在控制平面节点上运行以下命令,查找与目标节点关联的 PV、PVC 和 logicalvolumes.topolvm.cybozu.com 资源:

kubectl get pv -o json | jq -r --arg NODE <node-name> '
  .items[]
  | select(.spec.nodeAffinity.required.nodeSelectorTerms[]?.matchExpressions[]? | select(.key=="topology.topolvm.cybozu.com/node") | .values[]? == $NODE)
  | [.metadata.name, .spec.claimRef.namespace, .spec.claimRef.name]
  | @tsv
'

参数:

  • <node-name>:目标节点的名称。

步骤 3:停止使用受影响 PVC 的工作负载

确定受影响的 PVC 后,停止使用这些 PVC 的工作负载,并确认所有相关 Pod 均已停止,然后再继续。

步骤 4:删除受影响的 Kubernetes 存储资源

在控制平面节点上运行以下命令:

kubectl delete pvc -n <pvc-namespace> <pvc-name>
kubectl delete pv <pv-name>
kubectl delete logicalvolumes.topolvm.cybozu.com <logicalvolume-name>

参数:

  • <pvc-namespace>:受影响 PVC 的命名空间。
  • <pvc-name>:受影响 PVC 的名称。
  • <pv-name>:受影响 PV 的名称。
  • <logicalvolume-name>:TopoLVM logicalvolumes.topolvm.cybozu.com 资源的名称。它与 <pv-name> 相同。

如果查询结果包含多个资源,请根据映射关系逐个删除这些资源。

如果资源无法正常删除,请根据需要添加 --force。

步骤 5:更新 TopolvmCluster 资源

在控制平面节点上运行以下命令:

kubectl -n nativestor-system edit topolvmclusters.topolvm.cybozu.com topolvm

在编辑器中,删除目标节点的整个配置块。例如,删除 nodeName: 192.168.140.13 的配置块。

删除前:

spec:
  storage:
    deviceClasses:
      - classes:
          - className: hdd
            default: true
            devices:
              - name: /dev/vdc
                type: disk
            volumeGroup: hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33
        nodeName: 192.168.133.50
      - classes:
          - className: ssd
            default: true
            devices:
              - name: /dev/vdc
                type: disk
            volumeGroup: ssd-4a8737fc-48d3-4c61-882d-0a5bcc6f77a1
          - className: hdd
            devices:
              - name: /dev/vdb
                type: disk
            volumeGroup: hdd-97dc00f3-1df6-4f64-8ddc-7b0b6c5d6de5
        nodeName: 192.168.140.13

删除后:

spec:
  storage:
    deviceClasses:
      - classes:
          - className: hdd
            default: true
            devices:
              - name: /dev/vdc
                type: disk
            volumeGroup: hdd-2ab8f0a2-7d1d-42d7-ba6b-da94c6185c33
        nodeName: 192.168.133.50

步骤 6:更新 lvmdconfig ConfigMap

在控制平面节点上运行以下命令:

kubectl -n nativestor-system edit configmaps lvmdconfig-<node-name>

参数:

  • <node-name>:目标节点的名称。

在编辑器中,删除整个 lvmd.yaml 和 status.json 部分。不要保留已移除节点的任何配置或状态。

步骤 7:启动 topolvm-operator

在控制平面节点上运行以下命令:

kubectl -n nativestor-system scale --replicas 1 deployment topolvm-operator

步骤 8:验证节点已移除

在控制平面节点上运行以下命令:

kubectl -n nativestor-system get topolvmclusters.topolvm.cybozu.com topolvm -o jsonpath="{.status.nodeStorageState}" | jq

确认目标节点不再显示在 status.nodeStorageState 中。例如,192.168.140.13 不应再出现在输出中。