ある日突然 Docker のストレージとして使用していた btrfs の領域がディスクフルになってデーモンが起動しなくなってしまったので対応した時のメモです。
Why docker on btrfs?
Docker を Debian GNU/Linux 8 環境で使用していますが、ストレージドライバとして LVM Thin を使用できないことが分かりました。
デフォルトのループバックデバイスを使用した devicemapper では性能が悪そうですし、overlay や zfs は Debian 8 では使用できないので、まともに運用したことはありませんが消去法で btrfs を試していました。# lvcreate -L 30G -n docker vg # mkfs.btrfs -f /dev/mapper/vg-docker
突然の no space left on device
そんなある日 OS を起動してみると docker デーモンが動いていません。
systemd[1]: Starting Docker Application Container Engine... dockerd[23670]: chmod /var/lib/docker: no space left on device systemd[1]: docker.service: main process exited, code=exited, status=1/FAILURE systemd[1]: Failed to start Docker Application Container Engine. systemd[1]: Unit docker.service entered failed state./var/lib/docker の空きが足りない? dfコマンドの出力を見ると不足しているようには見えませんが。。。
# df -hT /var/lib/docker ファイルシス タイプ サイズ 使用 残り 使用% マウント位置 /dev/mapper/vg-docker btrfs 30G 17G 13G 57% /var/lib/dockerエラーメッセージ「chmod /var/lib/docker: no space left on device」で検索すると以下の記事が見つかりました。 どうやら btrfs の領域は df コマンドでは正確には表示できず、btrfs filesystem サブコマンドを使用しなければいけないことが分かりました。
btrfs filesystem df
の出力をみると total や used の値からは df の出力とそれほど変わらないように見えますが、
# btrfs filesystem df /var/lib/docker Data, single: total=27.22GiB, used=14.55GiB System, DUP: total=8.00MiB, used=16.00KiB System, single: total=4.00MiB, used=0.00B Metadata, DUP: total=1.38GiB, used=1.03GiB Metadata, single: total=8.00MiB, used=0.00B GlobalReserve, single: total=352.00MiB, used=0.00B
btrfs filesystem show
の出力を見ると size と used が同じ値でした。ということで何かの理由で空き領域が無いようです。
# btrfs filesystem show Label: none uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089 Total devices 1 FS bytes used 15.58GiB devid 1 size 30.00GiB used 30.00GiB path /dev/mapper/vg-docker
Balanceによる領域の開放
先の記事では btrfs のディスクフル問題の解決として以下の記事を参照していました。
これによると実データの使用量によってディスクフルなっていなければ、データまたはメタデータの平準化(balance)を行えば解決できそうです。 しかし今回は balance を行うために必要な領域も残っていない状態でした。# btrfs balance start -dusage=55 /var/lib/docker ERROR: error during balancing '/var/lib/docker' - No space left on device
# btrfs balance start -v -dusage=0 /var/lib/docker Dumping filters: flags 0x1, state 0x0, force is off DATA (flags 0x2): balancing, usage=0 ERROR: error during balancing '/var/lib/docker' - No space left on device There may be more info in syslog - try dmesg | tail最後の手段として btrfs に一時作業用のデバイスを追加する方法が紹介されていました。
One trick to get around this is to add a device (even a USB key will do) to your btrfs filesystem. This should allow balance to start, and then you can remove the device with btrfs device delete when the balance is finished.例では dd で作成したファイルをループバックマウントしたものを btrfs に追加していましたが、面倒なので今回は論理ボリュームを追加しました。
# lvcreate -L5g -n btrfs_tmp vg Logical volume "btrfs_tmp" created # btrfs device add /dev/vg/btrfs_tmp /var/lib/docker Performing full device TRIM (5.00GiB) ... # btrfs fi show Label: none uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089 Total devices 2 FS bytes used 15.58GiB devid 1 size 30.00GiB used 30.00GiB path /dev/mapper/vg-docker devid 2 size 5.00GiB used 0.00B path /dev/mapper/vg-btrfs_tmpそして balance を実行すると今度は正常に終了しました。
# btrfs balance start -v -dusage=0 /var/lib/docker Dumping filters: flags 0x1, state 0x0, force is off DATA (flags 0x2): balancing, usage=0 Done, had to relocate 7 out of 36 chunkssyslog には次のような出力がありました。
kernel: BTRFS info (device dm-10): relocating block group 30496784384 flags 1 kernel: BTRFS info (device dm-10): relocating block group 29423042560 flags 1 kernel: BTRFS info (device dm-10): relocating block group 28349300736 flags 1 kernel: BTRFS info (device dm-10): relocating block group 27275558912 flags 1 kernel: BTRFS info (device dm-10): relocating block group 26201817088 flags 1 kernel: BTRFS info (device dm-10): relocating block group 25128075264 flags 1 kernel: BTRFS info (device dm-10): relocating block group 24054333440 flags 1 kernel: BTRFS info (device dm-10): relocating block group 22980591616 flags 1 kernel: BTRFS info (device dm-10): relocating block group 30727471104 flags 36balance 後のファイルシステムの状態をみると used の値を足しても 23GB なので 7GB ほど解放されたようです。
# btrfs fi show Label: none uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089 Total devices 2 FS bytes used 15.58GiB devid 1 size 30.00GiB used 22.79GiB path /dev/mapper/vg-docker devid 2 size 5.00GiB used 256.00MiB path /dev/mapper/vg-btrfs_tmp元々あったデバイスに空き領域が確保できたので作業用として btrfs に追加した論理ボリュームは削除します。
# btrfs device delete /dev/vg/btrfs_tmp /var/lib/docker # lvremove -f vg/btrfs_tmp Logical volume "btrfs_tmp" successfully removed作業後の btrfs の状態。
# btrfs fi show Label: none uuid: d5d3aaa0-b798-4dc5-9969-5dfd9807a089 Total devices 1 FS bytes used 15.58GiB devid 1 size 30.00GiB used 23.04GiB path /dev/mapper/vg-docker # btrfs fi df /var/lib/docker Data, single: total=20.01GiB, used=14.55GiB System, DUP: total=8.00MiB, used=16.00KiB System, single: total=4.00MiB, used=0.00B Metadata, DUP: total=1.50GiB, used=1.03GiB Metadata, single: total=8.00MiB, used=0.00B GlobalReserve, single: total=352.00MiB, used=0.00B作業前と比較すると Data の total が -7.21GiB、Metadata DUP の total が -0.12GiB となりました。
# btrfs filesystem df /var/lib/docker Data, single: total=27.22GiB, used=14.55GiB System, DUP: total=8.00MiB, used=16.00KiB System, single: total=4.00MiB, used=0.00B Metadata, DUP: total=1.38GiB, used=1.03GiB Metadata, single: total=8.00MiB, used=0.00B GlobalReserve, single: total=352.00MiB, used=0.00B空き領域が確保できたので無事に docker デーモンも起動できました。
# docker info Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 70 Server Version: 17.03.1-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: 4ab9917febca54791c5f071a9d1f404867857fcc runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe init version: 949e6fa Kernel Version: 3.16.0-4-amd64 Operating System: Debian GNU/Linux 8 (jessie) OSType: linux Architecture: x86_64 CPUs: 2 Total Memory: 15.71 GiB 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 Registry: https://index.docker.io/v1/ WARNING: No kernel memory limit support WARNING: No cpu cfs quota support WARNING: No cpu cfs period support Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false
おわりに
あらためて Docker のドキュメントをみてみると btrfs を使う場合のプラクティスとして balance を cron で定期的に実行するように書いてある事に気づきました。
- Docker and Btrfs in practice - Docker Documentation
Enable a cronjob to rebalance your BTRFS devices. e.g. Spread the subvolume’s blocks evenly across your raid devices, and reclaim unused blocks. Without doing this, snapshots and subvolumes that docker removes will leave allocated blocks fillingup the BTRFS root volume
# btrfs subvolume list /var/lib/docker | wc -l 739
ZFS のような使い勝手を目指したファイルシステム、という程度の認識で btrfs を使っていますが、Copy on Write という特性による領域の割り当てなど、運用で気をつけなければいけない点があることを身をもって知りました。
あと btrfs の操作はほぼ全て btrfs コマンドのサブコマンドのようですが、最初に打ち込む btrfs
が QWERTY 配列のキーボードだと全て左手でタイプしなければいけない文字で構成されているので、ZFS における zfs コマンドや zpool コマンドと比べると長くて打ちづらいな、と今回の作業を通じて強く感じました。
0 件のコメント:
コメントを投稿