Microshiftでtopolvmを使ってPVをを作成する

前回セットアップしたMicroShiftではLVMシンプールを使ってPVを作成するように設定したので、各種動作を確認してみます。

設定内容

前回、デバイスクラスを作成しました。

$ sudo cat /etc/microshift/lvmd.yaml
socket-name:
device-classes:
  - name: thin
    default: true
    spare-gb: 0
    thin-pool:
      name: ocpthinpool
      overprovision-ratio: 10
    type: thin
    volume-group: rhel

「デバイスクラス」の明確な定義は見つかりませんでしたが、topolvmが使用するバックエンド(VG)を指しているようで、HDDやSSD、RAIDなど、ストレージのプロファイルに対応する概念のようです。
cf. lvmd.md

topolvmを使用するストレージクラスはデフォルトで1つ存在します。

$ oc get storageclasses.storage.k8s.io topolvm-provisioner -o yaml
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
  creationTimestamp: "2024-04-06T10:06:36Z"
  name: topolvm-provisioner
  resourceVersion: "391"
  uid: 29bf1ab6-82c2-4274-9aeb-ea099306cf51
parameters:
  csi.storage.k8s.io/fstype: xfs
provisioner: topolvm.io
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

ストレージクラスの方も「プロファイル」に対応する概念のようなのでストレージクラスとデバイスクラスは1:1に対応するように設定するのがわかりやすそうですが、 今回はストレージもローカルディスク1つしかないのでデフォルトのストレージクラスをそのまま使います。

PVを作成する

まずは上の設定を使ってPVを作って適当なコンテナへアタッチしてみます。

$ oc apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-claim-thin
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: topolvm-provisioner
---
apiVersion: v1
kind: Pod
metadata:
  name: base
spec:
  containers:
  - image: docker.io/nginx:stable-alpine
    name: test-container
    volumeMounts:
    - mountPath: /vol
      name: test-vol
  volumes:
  - name: test-vol
    persistentVolumeClaim:
      claimName: test-claim-thin
EOF
persistentvolumeclaim/test-claim-thin created
pod/base created

PVが作成されました。

$ oc get pvc
NAME              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
test-claim-thin   Bound    pvc-f8c20f2e-7d1a-4a3d-a2b0-e6d942c044dc   1Gi        RWO            topolvm-provisioner   50s
$ oc get pv pvc-f8c20f2e-7d1a-4a3d-a2b0-e6d942c044dc
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS          REASON   AGE
pvc-f8c20f2e-7d1a-4a3d-a2b0-e6d942c044dc   1Gi        RWO            Delete           Bound    default/test-claim-thin   topolvm-provisioner            82s
$ oc describe pv pvc-f8c20f2e-7d1a-4a3d-a2b0-e6d942c044dc
Name:              pvc-f8c20f2e-7d1a-4a3d-a2b0-e6d942c044dc
Labels:            <none>
Annotations:       pv.kubernetes.io/provisioned-by: topolvm.io
                   volume.kubernetes.io/provisioner-deletion-secret-name:
                   volume.kubernetes.io/provisioner-deletion-secret-namespace:
Finalizers:        [kubernetes.io/pv-protection]
StorageClass:      topolvm-provisioner
Status:            Bound
Claim:             default/test-claim-thin
Reclaim Policy:    Delete
Access Modes:      RWO
VolumeMode:        Filesystem
Capacity:          1Gi
Node Affinity:
  Required Terms:
    Term 0:        topology.topolvm.io/node in [beelink]
Message:
Source:
    Type:              CSI (a Container Storage Interface (CSI) volume source)
    Driver:            topolvm.io
    FSType:            xfs
    VolumeHandle:      1d0a104e-8655-4de8-a62c-827498301575
    ReadOnly:          false
    VolumeAttributes:      storage.kubernetes.io/csiProvisionerIdentity=1713637484909-2854-topolvm.io
Events:                <none>
$ sudo lvs
  LV                                   VG   Attr       LSize   Pool        Origin Data%  Meta%  Move Log Cpy%Sync Convert
  1d0a104e-8655-4de8-a62c-827498301575 rhel Vwi-aotz--   1.00g ocpthinpool        6.32
  ocpthinpool                          rhel twi-aotz-- 100.00g                    0.06   10.45
  root                                 rhel -wi-ao---- 100.00g
  swap                                 rhel -wi-ao----  <7.76g

設定した通り、シンプールを通してLVが作成されていることがわかります。

スナップショット

スナップショットとは、

Storage Red Hat build of MicroShift 4.15 | Red Hat Customer Portal ボリュームのスナップショット | Kubernetes

ボリュームスナップショットは、完全に新しいボリュームを作成することなく、特定の時点でボリュームの内容をコピーするための標準化された方法をKubernetesユーザーに提供します。この機能により、たとえばデータベース管理者は、編集または削除の変更を実行する前にデータベースをバックアップできます。

スナップショットを作成するため、スナップショットクラスを作成します。

$ oc apply -f - <<EOF
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: topolvm-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true" 
driver: topolvm.io 
deletionPolicy: Delete 
EOF

このPVのスナップショットを作成します。 ですが、試しにPodを止めずにスナップショットを作成した際はPVへの書き込みはほとんどないにも関わらず出来上がったLVMスナップショットをマウントできませんでした。

$ sudo mount /dev/rhel/e1bd464a-c351-4173-8bd8-b5234d9b2279 /mnt/snapshot
mount: /mnt/snapshot: cannot mount /dev/mapper/rhel-e1bd464a--c351--4173--8bd8--b5234d9b2279 read-only.

PVへの書き込みを停止するためにあらかじめPodを削除します。

$ oc delete pod base
pod "base" deleted
$ oc get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                     STORAGECLASS          REASON   AGE
pvc-f8c20f2e-7d1a-4a3d-a2b0-e6d942c044dc   1Gi        RWO            Delete           Bound    default/test-claim-thin   topolvm-provisioner            35s
$ oc apply -f - <<EOF
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: test-snapshot
spec:
  volumeSnapshotClassName: topolvm-snapclass
  source:
    persistentVolumeClaimName: test-claim-thin
EOF
volumesnapshot.snapshot.storage.k8s.io/test-snapshot created

作成されたようです。取得したスナップショットの情報を確認してみます。

$ oc get volumesnapshot
NAME            READYTOUSE   SOURCEPVC         SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS       SNAPSHOTCONTENT                                    CREATIONTIME   AGE
test-snapshot   true         test-claim-thin                           1Gi           topolvm-snapclass   snapcontent-a8443d82-ac86-448d-b068-ddb09eecbb9c   32s            33s
$ sudo lvs
  LV                                   VG   Attr       LSize   Pool        Origin                               Data%  Meta%  Move Log Cpy%Sync Convert
  4adb15e6-2d9e-46dc-a3a1-a9e4ef405627 rhel Vri-a-tz--   1.00g ocpthinpool 1d0a104e-8655-4de8-a62c-827498301575 6.32
  1d0a104e-8655-4de8-a62c-827498301575 rhel Vwi-aotz--   1.00g ocpthinpool                                      6.32
  ocpthinpool                          rhel twi-aotz-- 100.00g                                                  0.06   10.45
  root                                 rhel -wi-ao---- 100.00g
  swap                                 rhel -wi-ao----  <7.76g

LVMのレイヤでは対象のLVから(LVMの)スナップショットを取得していることがわかります。
ただしこのままではこのホストが壊れたらスナップショットも失われてしまうためバックアップとしては弱いです。 きちんと障害に備えるにはこのスナップショットを別のハードウェア等に退避しておいたほうがよいです。

$ sudo mkdir /mnt/snapshot
$ sudo mount /dev/rhel/4adb15e6-2d9e-46dc-a3a1-a9e4ef405627 /mnt/snapshot/
mount: /mnt/snapshot: WARNING: source write-protected, mounted read-only.sudo mount /dev/ /mnt/snapshot
$ sudo cp -a /mnt/snapshot DESTINATION

スナップショットからリストア

スナップショットからPVCを作ってPodへアタッチします。

$ oc apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: snapshot-restore
spec:
  accessModes:
  - ReadWriteOnce
  dataSource:
    apiGroup: snapshot.storage.k8s.io
    kind: VolumeSnapshot
    name: test-snapshot
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: base
spec:
  containers:
  - image: docker.io/nginx:stable-alpine
    name: test-container
    volumeMounts:
    - mountPath: /vol
      name: test-vol
  volumes:
  - name: test-vol
    persistentVolumeClaim:
      claimName: snapshot-restore
EOF
persistentvolumeclaim/snapshot-restore created
pod/base created
$ oc get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                      STORAGECLASS          REASON   AGE
pvc-462ea98a-e038-4218-8418-eaf56d6d5f8f   1Gi        RWO            Delete           Bound    default/snapshot-restore   topolvm-provisioner            23h
pvc-9aa6b184-f7b5-4cbd-9948-26cccfd9a107   1Gi        RWO            Delete           Bound    default/test-claim-thin    topolvm-provisioner            24h
$ oc describe pv pvc-462ea98a-e038-4218-8418-eaf56d6d5f8f
Name:              pvc-462ea98a-e038-4218-8418-eaf56d6d5f8f
Labels:            <none>
Annotations:       pv.kubernetes.io/provisioned-by: topolvm.io
                   volume.kubernetes.io/provisioner-deletion-secret-name:
                   volume.kubernetes.io/provisioner-deletion-secret-namespace:
Finalizers:        [kubernetes.io/pv-protection]
StorageClass:      topolvm-provisioner
Status:            Bound
Claim:             default/snapshot-restore
Reclaim Policy:    Delete
Access Modes:      RWO
VolumeMode:        Filesystem
Capacity:          1Gi
Node Affinity:
  Required Terms:
    Term 0:        topology.topolvm.io/node in [beelink]
Message:
Source:
    Type:              CSI (a Container Storage Interface (CSI) volume source)
    Driver:            topolvm.io
    FSType:            xfs
    VolumeHandle:      1a36fc28-9e75-45a2-a8d2-7444c3ada58e
    ReadOnly:          false
    VolumeAttributes:      storage.kubernetes.io/csiProvisionerIdentity=1714679255467-5370-topolvm.io
Events:                <none>
$ sudo lvs
  LV                                   VG   Attr       LSize   Pool        Origin                               Data%  Meta%  Move Log Cpy%Sync Convert
  1a36fc28-9e75-45a2-a8d2-7444c3ada58e rhel Vwi-aotz--   1.00g ocpthinpool 4adb15e6-2d9e-46dc-a3a1-a9e4ef405627 6.32
  4adb15e6-2d9e-46dc-a3a1-a9e4ef405627 rhel Vri-a-tz--   1.00g ocpthinpool 1d0a104e-8655-4de8-a62c-827498301575 6.32
  1d0a104e-8655-4de8-a62c-827498301575 rhel Vwi-a-tz--   1.00g ocpthinpool                                      6.32
  ocpthinpool                          rhel twi-aotz-- 100.00g                                                  0.07   10.46
  root                                 rhel -wi-ao---- 100.00g
  swap                                 rhel -wi-ao----  <7.76g

LVMレイヤでは、LVMスナップショットから新たなLVが作成されています。

スナップショットの削除

スナップショットの削除時に実体となるLVを削除するかどうかをVolumeSnapshotClassで設定できます。
VolumeSnapshotClass(再掲)

$ oc apply -f - <<EOF
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: topolvm-snapclass
  annotations:
    snapshot.storage.kubernetes.io/is-default-class: "true" 
driver: topolvm.io 
deletionPolicy: Delete 
EOF

deletionPolicyをDeleteに設定した場合、VolumeSnapshotの削除と同時に実体のLV(MicroShift上ではVolumeSnapshotContentリソースとして管理されています)も削除されます。 Retainに設定した場合はVolumeSnapshotContentが削除されずに残ります。

$ oc delete volumesnapshot test-snapshot
volumesnapshot.snapshot.storage.k8s.io "test-snapshot" deleted
$ sudo lvs
  LV                                   VG   Attr       LSize   Pool        Origin Data%  Meta%  Move Log Cpy%Sync Convert
  1a36fc28-9e75-45a2-a8d2-7444c3ada58e rhel Vwi-aotz--   1.00g ocpthinpool        6.32
  1d0a104e-8655-4de8-a62c-827498301575 rhel Vwi-a-tz--   1.00g ocpthinpool        6.32
  ocpthinpool                          rhel twi-aotz-- 100.00g                    0.07   10.46
  root                                 rhel -wi-ao---- 100.00g
  swap                                 rhel -wi-ao----  <7.76g

Retainに設定した場合:

$ oc patch volumesnapshotclass topolvm-snapclass --type='json' -p='[{"op": "replace", "path": "/deletionPolicy", "value":"Retain"}]'
volumesnapshotclass.snapshot.storage.k8s.io/topolvm-snapclass patched
$ oc apply -f - <<EOF
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: test-snapshot-retain
spec:
  volumeSnapshotClassName: topolvm-snapclass
  source:
    persistentVolumeClaimName: test-claim-thin
EOF
volumesnapshot.snapshot.storage.k8s.io/test-snapshot-retain created
$ oc get volumesnapshot test-snapshot-retain
NAME                   READYTOUSE   SOURCEPVC         SOURCESNAPSHOTCONTENT   RESTORESIZE   SNAPSHOTCLASS       SNAPSHOTCONTENT                                    CREATIONTIME   AGE
test-snapshot-retain   true         test-claim-thin                           1Gi           topolvm-snapclass   snapcontent-31631ab1-a663-4436-b0b6-d19e538364e8   45s            45s
$ oc get volumesnapshotcontent
NAME                                               READYTOUSE   RESTORESIZE   DELETIONPOLICY   DRIVER       VOLUMESNAPSHOTCLASS   VOLUMESNAPSHOT         VOLUMESNAPSHOTNAMESPACE   AGE
snapcontent-31631ab1-a663-4436-b0b6-d19e538364e8   true         1073741824    Retain           topolvm.io   topolvm-snapclass     test-snapshot-retain   default                   72s
$ oc delete volumesnapshot test-snapshot-retain
volumesnapshot.snapshot.storage.k8s.io "test-snapshot-retain" deleted
$ oc get volumesnapshotcontent
NAME                                               READYTOUSE   RESTORESIZE   DELETIONPOLICY   DRIVER       VOLUMESNAPSHOTCLASS   VOLUMESNAPSHOT         VOLUMESNAPSHOTNAMESPACE   AGE
snapcontent-31631ab1-a663-4436-b0b6-d19e538364e8   true         1073741824    Retain           topolvm.io   topolvm-snapclass     test-snapshot-retain   default                   5m14s
$ oc get volumesnapshotcontent snapcontent-31631ab1-a663-4436-b0b6-d19e538364e8 -o jsonpath='{.status.snapshotHandle}'
92d06036-12de-4600-877a-113ec5e21932
$ sudo lvs
  LV                                   VG   Attr       LSize   Pool        Origin                               Data%  Meta%  Move Log Cpy%Sync Convert
  92d06036-12de-4600-877a-113ec5e21932 rhel Vri-a-tz--   1.00g ocpthinpool cd059561-dcd6-4afd-9c22-f370f6caf6aa 6.32
  cd059561-dcd6-4afd-9c22-f370f6caf6aa rhel Vwi-a-tz--   1.00g ocpthinpool                                      6.32
  ocpthinpool                          rhel twi-aotz-- 100.00g                                                  0.07   10.46
  root                                 rhel -wi-ao---- 100.00g
  swap                                 rhel -wi-ao----  <7.76g

VolumeSnapshotを削除しても実体のLV(92d06036-12de-4600-877a-113ec5e21932)が残っていることがわかります。 実体も削除する場合はVolumeSnapshotContentを削除します。

$ oc delete volumesnapshotcontent snapcontent-31631ab1-a663-4436-b0b6-d19e538364e8
volumesnapshotcontent.snapshot.storage.k8s.io "snapcontent-31631ab1-a663-4436-b0b6-d19e538364e8" deleted
$ sudo lvs
  LV                                   VG   Attr       LSize   Pool        Origin                               Data%  Meta%  Move Log Cpy%Sync Convert
  92d06036-12de-4600-877a-113ec5e21932 rhel Vri-a-tz--   1.00g ocpthinpool cd059561-dcd6-4afd-9c22-f370f6caf6aa 6.32
  cd059561-dcd6-4afd-9c22-f370f6caf6aa rhel Vwi-a-tz--   1.00g ocpthinpool                                      6.32
  ocpthinpool                          rhel twi-aotz-- 100.00g                                                  0.07   10.46
  root                                 rhel -wi-ao---- 100.00g
  swap                                 rhel -wi-ao----  <7.76g

これが正常動作なのかはわかりませんが、上の通りVolumeSnapshotContentを削除してもLVが残ってしまいました。

$ sudo lvremove rhel/92d06036-12de-4600-877a-113ec5e21932
  Logical volume "92d06036-12de-4600-877a-113ec5e21932" successfully removed.

最後の動作が想定外でしたが、概ね動作を理解できました。

関連記事

comments powered by Disqus