2017/10/29

btrfsのデバイスをサイズの大きなものに交換する

btrfs ファイルシステムの領域がディスクフルになってしまったため、より大きなデバイスに交換したときのメモです。

忘れた頃の no space left on device

Docker のストレージとして btrfs ファイルシステムを利用していますが、以前ディスクフルで Docker デーモンが起動しなくなって一時的な対処をしました。

その後 Elastic Stack や Oracle Database のコンテナなどを試していますが、永続データを Data Volume として利用することが多くなり、それと気づかずコンテナ破棄時に削除し忘れたり等もあって容量が足りなくなっていました。
Failed to log msg \"\" for logger json-file: write /var/lib/docker/containers/(省略)-json.log: no space left on device"
# df -hT /var/lib/docker
ファイルシス          タイプ サイズ  使用  残り 使用% マウント位置
/dev/mapper/vg-docker btrfs     40G   39G  324K  100% /var/lib/docker
ストレージプールに割り当てていたデバイスは NVMe SDD なので容量をケチっていたのがいけなかったようです。とはいえこれ以上このデバイスの容量追加は難しいので、余裕のある HDD デバイスと交換したときの手順をまとめます。

btrfs のデバイスを容量の大きなものに交換する

btrfs の操作や本記事の図については "Btrfsの薄い本" を参考にしました。

最終的に以下のような交換をしたときの手順になります。

ストレージプールにデバイスを追加

device add で 500GB のデバイスをストレージプールに追加します。

# btrfs device add /dev/mapper/vg2-docker /var/lib/docker
# btrfs filesystem show /var/lib/docker
Label: none  uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089
        Total devices 2 FS bytes used 37.44GiB
        devid    1 size 40.00GiB used 40.00GiB path /dev/mapper/vg-docker
        devid    2 size 500.00GiB used 1.00GiB path /dev/mapper/vg2-docker

バランス

とりあえず追加したデバイスにデータを移動する目的で balance start を実行してみます。

# btrfs balance start /var/lib/docker
WARNING:

        Full balance without filters requested. This operation is very
        intense and takes potentially very long. It is recommended to
        use the balance filters to narrow down the balanced data.
        Use 'btrfs balance start --full-balance' option to skip this
        warning. The operation will start in 10 seconds.
        Use Ctrl-C to stop it.
10 9 8 7 6 5 4 3 2 1
  Starting balance without any filters.

Done, had to relocate 52 out of 52 chunks
btrfs balance start /var/lib/docker  0.00s user 224.82s system 23% cpu 16:05.70 total
フォアグラウンドで実行したので私の環境では 4 分ほどでコマンドが帰ってきました。状況を見てみると used を足した合計は増えている気がしますが追加したデバイスに多くのデータが移動している様子です。
# btrfs filesystem show /var/lib/docker
Label: none  uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089
        Total devices 2 FS bytes used 37.44GiB
        devid    1 size 40.00GiB used 9.00GiB path /dev/mapper/vg-docker
        devid    2 size 500.00GiB used 45.00GiB path /dev/mapper/vg2-docker

デバイスを削除

明示的にバランスをせずとも、デバイスを削除する際にデータはストレージプール上の他のデバイスに移動されるものと思っていましたが、device remove を実行するとエラーが出ました。

# btrfs device remove /dev/mapper/vg-docker /var/lib/docker
ERROR: error removing device '/dev/mapper/vg-docker': unable to go below two devices on raid1

迷走(RAID タイプの変更)

このエラーメッセージで Web を検索しても対応が分からなかったので、試しに balance で RAID タイプを RAID0 に変更してみました。

# btrfs balance start -dconvert=raid0 /var/lib/docker
Done, had to relocate 36 out of 47 chunks
btrfs balance start -dconvert=raid0 /var/lib/docker  0.00s user 224.25s system 25% cpu 14:52.62 total
# btrfs filesystem show /var/lib/docker
Label: none  uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089
        Total devices 2 FS bytes used 37.45GiB
        devid    1 size 40.00GiB used 40.00GiB path /dev/mapper/vg-docker
        devid    2 size 500.00GiB used 40.00GiB path /dev/mapper/vg2-docker
その後に single に変更しました。
# btrfs balance start -dconvert=single /var/lib/docker
Done, had to relocate 19 out of 22 chunks
btrfs balance start -dconvert=single /var/lib/docker  0.00s user 173.74s system 19% cpu 14:29.15 total
RAID タイプを変更する前に戻ったようですが、変更によるデータ移動でフラグメントが解消されたせいか微妙に used の値が変わっています。
# btrfs filesystem show
Label: none  uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089
        Total devices 2 FS bytes used 37.45GiB
        devid    1 size 40.00GiB used 1.53GiB path /dev/mapper/vg-docker
        devid    2 size 500.00GiB used 37.53GiB path /dev/mapper/vg2-docker

デバイスを指定してバランス

エラーの理由は削除しようとするデバイスにデータが残っていることだと思い、明示的に全てのデータ(データとメタデータ)を移動したいデバイス(devid=2)に balance します。

# btrfs balance start -dconvert=single,devid=2 -mconvert=single,devid=2 /var/lib/docker
ERROR: error during balancing '/var/lib/docker': Invalid argument
There may be more info in syslog - try dmesg | tail
何やら引数が間違っているようですが、書式としてはあっていると思ったので強制(-f)してみます。
# btrfs balance start -f -dconvert=single,devid=2 -mconvert=single,devid=2 /var/lib/docker
Done, had to relocate 40 out of 40 chunks
btrfs balance start -f -dconvert=single,devid=2 -mconvert=single,devid=2   0.00s user 271.58s system 22% cpu 19:47.76 total
状況を見てみると削除したいデバイス(devid=1)にはデータが残ってなさそうです。
# btrfs filesystem show
Label: none  uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089
        Total devices 2 FS bytes used 37.45GiB
        devid    1 size 40.00GiB used 0.00B path /dev/mapper/vg-docker
        devid    2 size 500.00GiB used 39.03GiB path /dev/mapper/vg2-docker

再びデバイスを削除

ここでもう一度 device remove を実行してみると今度は上手く削除できました。

# btrfs device remove /dev/mapper/vg-docker /var/lib/docker
# btrfs filesystem show
Label: none  uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089
        Total devices 1 FS bytes used 37.45GiB
        devid    2 size 500.00GiB used 39.03GiB path /dev/mapper/vg2-docker
念のため作業中には止めていた Docker デーモンを起動しても無事に認識されました。
# docker info
Containers: 7
 Running: 2
 Paused: 0
 Stopped: 5
Images: 111
Server Version: 17.05.0-ce
Storage Driver: btrfs
 Build Version: Btrfs v3.17
 Library Version: 101
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 9048e5e50717ea4497b757314bad98ea3763c145
runc version: 9c2d8d184e5da67c95d601382adf14862e4f2228
init version: 949e6fa
Kernel Version: 4.9.0-4-amd64
Operating System: Debian GNU/Linux 9 (stretch)
OSType: linux
Architecture: x86_64
CPUs: 2
Total Memory: 15.68GiB
Name: microserver.myhome
ID: JNLR:5HTY:XMAU:CASU:OHUW:FUYU:3KYE:GGEM:O3SH:QYJK:PKT5:7LYE
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
No Proxy: localhost,127.0.0.1
Username: yoshikaw
Registry: https://index.docker.io/v1/
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

おわりに

途中で迷走したので果たしてこれが正しい手順だったのか分かりませんが、btrfs のストレージプール容量枯渇からデバイスを追加して切り替える手順がとりあえずできました。LVM で管理しているデバイスを btrfs のストレージプールとして利用するのはオーバーヘッドが多い気がしますが、自宅サーバなのであまり気にしないことにします。

btrfs は今後 Red Hat Enterprise Linux では使用できなくなるようですが、Debian GNU/Linux での動作がサポートされるのであればこのまま使用してゆこうと思います。

そういえば Oracle Linux も btrfs をサポートしていますが、UEK のリリースノートを見ると RAID タイプ 5/6 をサポートするようになったみたいですね。 まだ Docker のバックエンドストレージとしてしか btrfs を使用していませんが、Linux で手軽にできる CoW なファイルシステムとして色々と試してゆこうと思います。

0 件のコメント:

コメントを投稿