Persistent Volume の Space Reclamation について草々

※この記事は Red Hat Advent Calendar 2023 の 16日目の記事です。

qiita.com

こんにちは。レッドハットでクラウドインフラを生業にしている宇都宮(うつぼ)です。
早速ですがストレージに関する問題です。

問題

アリスはオンプレミスで展開された OpenShift(または Kubernetes)クラスタの管理者です。
クラスタには1つ 10TiB ものデカすぎる PV があります。この PV のバックエンドはブロックストレージで、Thin-provisioned な論理ボリュームを使っています。 ストレージの管理者であるボブからは「もうストレージの容量がなくなりそうだから、この PV から容量を返してくれ」と言われています。
クラスタ管理者のアリスは、このデカすぎる PV を使うキャロルにこの話をして、PV 内に溜め込んだ不要なファイルを消してもらうことになりました。
キャロルからは、「仰せの通りファイルを消した、3分の1 くらいになった」と報告を受けました。
アリスはこれで一件落着と枕を高くして寝ました。しかし翌日ボブからは「もう本当にまずい!早く容量を返してくれ!」と言われ、困惑しています。
さて、なぜでしょうか。なお、ボブもキャロルも嘘はついていないものとします。

解答

簡単ですね。正解は、ファイルを消してもファイルシステムは勝手に縮まないし、ファイルシステムが縮まなければボリュームサイズも減らないから です。

これは別に Kubernetes とかに限った話ではありません。一般的な Linux サーバでも同じ現象は起こります。
そもそも上の問題で一番ダメなのは 10TiB の PVC を許しているところで、OpenShift かストレージ側で Quota をかけて制限すべきです。
ですが、ブロックストレージだとファイルシステムでファイルを消したら自動で空いた容量がストレージに帰っていくなんてことは無いので、アリスもぐっすり寝てる場合ではありません。

Space Reclamation と PV

一度使ったけど空いた容量をストレージ側に返すことを、Space Reclamation と言います。
シックプロビジョニングではまず出てきませんが、シンプロビジョニングではおなじみの概念です。 シンプロビジョニングは「自分が必要な容量だけ使うべき」なポリシーですので、「必要なくなって取りすぎた容量は返すべき」だからです。

通常の Linux で Space Reclamation するには、fstrim コマンドを実行してファイルシステムの使っていない領域を開放します。その後はストレージ側でそれを回収します。
それでは Kubernetes PV の場合は?わざわざ Pod や Worker ノードに入って fstrim を実行する?そんな運用ありえないですよね。

PV の場合は、CSI (Container Storage Interface) Add-on を使って Reclaim することができます。
ReclaimSpaceJob というカスタムリソースを使います。Reclaim はそんなに常時やるものではないので、単発で Job 的に使います。

github.com

ODF で PV の Space Reclamation を試してみる

Red Hat OpenShift Data Foundation(ODF)はこれに対応しているので、実際やってみましょう。
ODF がインストールされたクラスタで適当なアプリを作って 50GiB PVC をアタッチします。

Pod からは /dev/rbd0 として見えます。この時点ではほとんど空っぽ。

sh-4.4$ lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop1         7:1    0  512G  0 loop 
rbd0        252:0    0   50G  0 disk /mnt
nvme0n1     259:0    0  100G  0 disk 
|-nvme0n1p1 259:1    0    1M  0 part 
|-nvme0n1p2 259:2    0  127M  0 part 
|-nvme0n1p3 259:3    0  384M  0 part 
`-nvme0n1p4 259:4    0 99.5G  0 part /dev/termination-log
sh-4.4$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/rbd0        49G   24K   49G   1% /mnt

ODF のダッシュボードで見ても、ほとんど使われていない初期状態です。

ここで 10GiB のダミーファイルを書き込みます。10GiB 増えています。(当たり前)

sh-4.4$ dd if=/dev/random of=/mnt/10G.dat bs=1M count=10240
10240+0 records in
10240+0 records out
10737418240 bytes (11 GB, 10 GiB) copied, 81.0443 s, 132 MB/s
sh-4.4$ 
sh-4.4$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/rbd0        49G   11G   39G  21% /mnt

ODF では三重でレプリケーションされるので、ダッシュボードで見ると 3倍の 30GiB ほどが増えていることがわかります。

それでは Pod でファイルを削除します。10GiB 減ります。

sh-4.4$ rm -f /mnt/10G.dat 
sh-4.4$ 
sh-4.4$ df -h /mnt
Filesystem      Size  Used Avail Use% Mounted on
/dev/rbd0        49G   24K   49G   1% /mnt

ODF では、全然減ってません。

さてここで ReclaimSpaceJob を作って Reclaim してみましょう。

apiVersion: csiaddons.openshift.io/v1alpha1
kind: ReclaimSpaceJob
metadata:
  name: reclaim-odf-pvc
  namespace: test
spec:
  target:
    persistentVolumeClaim: odf-pvc

これを実行すると、次のようになります。

減っている!

ODF の中で動く Ceph のブロックデバイス(RBD)は、シンプロビジョニングで作られます。
この ReclaimSpaceJob によって、アプリ Pod と同じノードで動く CSI driver が fstrim を実行します。Ceph RBD は sparse なイメージファイルなので、ゼロ領域は自動的に Ceph のプールに返されます。

CSIドライバのログより

Space Reclamation はスケジュールするともっと楽

ad hoc に Reclaim するなら ReclaimSpaceJob を作りますが、定期的に実行するようスケジュールしておくとよいです。
ReclaimSpaceCronJob というカスタムリソースでスケジュールを設定できるのですが、対象の PVC に annotation を追加することで代用できます。

# oc annotate pvc odf-pvc "reclaimspace.csiaddons.openshift.io/schedule=@weekly" -n test
persistentvolumeclaim/odf-pvc annotated

上の @weekly の部分は Cron と同じ書き方でもOKです。毎週金曜日の深夜0時に実行するなら、0 0 * * 5 みたいな感じですね。
これでアリスもボブも枕を高くしてぐっすり眠れることでしょう。

まとめ

クラウド環境で Space Reclamation しないとマズい、ということはほとんど無いと思いますが、冒頭の問題のようにオンプレミス環境だったら意外とあるかもしれません。
ストレージはあって当然使えて当然、とお思いの方もいるかもしれませんが、いやいや結構中の人は色々と工夫と苦労をしているんですね。
今回は ODF で確認しましたが、他のストレージの CSI はどうなのでしょう。すみません私もわかりません。色々と試してみるとよいのではないかなと思います。

というわけで、今回はここまで。

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。