containerd はコンテナランタイムの中核として、イメージレイヤの差分管理に「スナップショッタ」と呼ばれるプラグイン機構を使っています。デフォルトの overlayfs スナップショッタは Linux カーネルの OverlayFS を利用しており、ほぼすべての環境で動作する汎用的な選択肢です。
一方、ノードのルートファイルシステムが btrfs の場合は、containerd に組み込まれた btrfs スナップショッタが利用できます。btrfs ネイティブのサブボリューム機構とコピーオンライト(CoW)を直接活用するため、OverlayFS の多段マウントによるオーバーヘッドを回避できます。K8s 本番クラスタでは全ノードを同時に切り替えるのではなく、1台ずつドレインして設定変更するローリング方式が安全です。本記事ではその一連の流れを取り上げます。
containerdスナップショッタの役割と overlayfs・btrfs の違い
スナップショッタは、コンテナイメージの各レイヤをホスト上でどのように表現するかを決める抽象レイヤです。containerd はプラグイン方式でスナップショッタを差し替えられる設計になっており、overlayfs・btrfs・zfs・native(単純なディレクトリコピー)などが標準で同梱されています。
overlayfs は上位レイヤと下位レイヤを重ね合わせてコンテナのルートファイルシステムを構成します。これに対して btrfs スナップショッタはサブボリュームのスナップショット機能を使い、差分をファイルシステムレベルで管理します。イメージキャッシュの物理配置が btrfs のサブボリューム体系と一致するため、ストレージ効率と削除操作の速度が向上するケースがあります。ただし、btrfs スナップショッタが使えるのはルートボリュームまたは containerd のデータルート(既定は /var/lib/containerd)が btrfs でマウントされているノードに限られます。
移行前の事前確認
作業対象ノードで次の点を確認してから移行手順に進んでください。
- ファイルシステムの確認:
findmnt -T /var/lib/containerdを実行し、TYPE列がbtrfsであることを確認します。btrfs でない場合、btrfsスナップショッタは起動に失敗します。 - カーネルモジュールの確認:
lsmod | grep btrfsでモジュールがロード済みであることを確認します。未ロードの場合はmodprobe btrfsでロードし、永続化設定も行います。 - containerdのバージョン確認:
containerd --versionを実行します。後述の 2.x 系と 1.x 系では設定ファイルの書式が異なります。 - クラスタの冗長性確認:移行対象ノードをドレインしても残りのノードでワークロードが維持できるか、PodDisruptionBudget(PDB)の設定値とノード数を確認します。
ローリング移行手順(ノード単位)
以下の手順を対象ノードごとに繰り返します。一度に複数ノードを同時に作業すると、クラスタの許容ノード数を下回るリスクがあるため、基本的には1台ずつ進めてください。
ステップ1:ノードのドレインと隔離
まず対象ノードをスケジュール不可にし、既存のPodを退避させます。
# NODE_NAME には実際のノード名を指定する
kubectl drain NODE_NAME \
--ignore-daemonsets \
--delete-emptydir-data \
--timeout=300s
--delete-emptydir-data を指定するとemptyDirボリュームのデータは失われます。ステートフルワークロードがある場合は事前にデータ退避の要否を確認してください。
ステップ2:containerd 設定の変更
対象ノードにSSHでログインし、/etc/containerd/config.toml を編集します。containerd 1.x 系(config version 2)の場合は以下のように [plugins."io.containerd.grpc.v1.cri".containerd] セクションの snapshotter を変更します。
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "btrfs"
設定ファイルが存在しない場合は containerd config default コマンドで既定値を生成してから編集します。
containerd config default | sudo tee /etc/containerd/config.toml
# その後 snapshotter = "btrfs" に書き換える
ステップ3:サービス再起動とノードの復帰
設定を保存したら containerd を再起動します。
sudo systemctl restart containerd
sudo systemctl is-active containerd # active であることを確認
containerd が正常に起動したことを確認してから、ノードをスケジュール可能に戻します。
kubectl uncordon NODE_NAME
しばらく待ってから kubectl get pods -A -o wide | grep NODE_NAME でPodが正常に配置されていることを確認し、次のノードの作業に移ります。
動作検証
移行後のノードで、実際に btrfs スナップショッタが使われているかを確認します。
# crictl でランタイム情報を確認
crictl info | grep -i snapshotter
# 期待する出力例(想定例)
# "snapshotter": "btrfs"
また、containerd の名前空間 k8s.io 配下でスナップショット一覧を確認することもできます。
sudo ctr -n k8s.io snapshots --snapshotter btrfs ls
このコマンドが正常に実行されてスナップショット一覧が表示されれば、btrfs スナップショッタが機能しています。エラーが出る場合は journalctl -u containerd --since "10 minutes ago" でログを確認してください。
加えて、新しくPodをデプロイして起動・終了が正常に行われるかを実際のワークロードで確認することを推奨します。テスト用のDeploymentを一時的に作成し、スケールアップ・ダウン・削除の一連の操作を行うと、スナップショッタの基本動作を確認できます。
切り戻し手順と注意点
問題が発生した場合は、設定を overlayfs に戻して containerd を再起動することで切り戻せます。ただし、スナップショッタを切り替えると既存のイメージキャッシュは別のスナップショッタからは読み取れません。overlayfs に戻した場合、btrfs スナップショッタで取得済みのスナップショットは利用できなくなるため、イメージの再プルが発生します。
切り戻しの手順は移行と同様で、ドレイン → 設定変更 → containerd 再起動 → アンコードンの順に進めます。キャッシュをクリーンな状態にしてから再起動するには以下の操作が有効です。
# btrfsスナップショッタのスナップショットをすべて削除(切り戻し時のみ)
sudo ctr -n k8s.io snapshots --snapshotter btrfs rm $(sudo ctr -n k8s.io snapshots --snapshotter btrfs ls -q)
# または未使用イメージをまとめて削除
sudo crictl rmi --prune
よくあるつまずきとして、切り戻し後に ImagePullBackOff が多発するケースがあります。これはキャッシュが消えてイメージの再プルが集中するためです。クラスタ規模が大きい場合はイメージレジストリへの負荷を考慮し、ノードをある程度間隔を空けてアンコードンすることで軽減できます。
2026年現行環境での差分(containerd 2.x / K8s 1.32以降)
2025年後半にリリースされた containerd 2.x 系では、設定ファイルのフォーマットが config version 3 に更新されています。1.x 系の config v2 と書式が変わっており、既存の設定ファイルをそのまま流用するとwarningが出るか、一部の設定が無視されます。
containerd 2.x での設定ファイルの先頭は以下のようになります。
version = 3
[plugins."io.containerd.cri.v1.runtime".containerd]
snapshotter = "btrfs"
プラグインパスが io.containerd.grpc.v1.cri(v2)から io.containerd.cri.v1.runtime(v3)に変わっている点に注意が必要です。containerd config default コマンドで出力された既定設定を元に書き換えることで、バージョンに応じた正しい書式を得られます。
また、K8s 1.32 以降では CRI(Container Runtime Interface)側でスナップショッタの設定を RuntimeClass ごとに切り替えられる機構が整備されています。全ノード共通ではなく、特定のワークロードにだけ btrfs スナップショッタを適用したい場合は RuntimeClass の overhead および scheduling フィールドと組み合わせてノードアフィニティで制御する方法も選択肢に入ります。
なお、containerd 2.x では非推奨だった --snapshotter フラグが一部のサブコマンドで削除されています。スクリプト類で ctr コマンドを使っている場合は、移行前にコマンドの互換性を確認してください。nerdctl を利用している環境では、nerdctl info の出力にスナップショッタ名が表示されるため、移行後の確認にも活用できます。
K8s 本番クラスタでのスナップショッタ切り替えは、設定変更そのものよりも「既存スナップショットとの非互換性」と「イメージ再取得によるレジストリ負荷」への対処がポイントです。ローリング方式で1ノードずつ進め、各ノードで動作確認を取りながら作業することで、サービス影響を最小限に抑えられます。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
PR・広告
コマンド操作から基本運用までを手を動かして学べる定番書。記事で触れた技術の土台固めに。
※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。
