ディスクパーティションの自動化:systemd-repartを本番環境で6ヶ月運用したレビュー

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

静的ディスクイメージのボトルネック

6ヶ月前、私たちのチームは壁に突き当たりました。120台のエッジデバイスと様々なクラウドインスタンスを、単一の2.1GB Linuxイメージでデプロイしていました。イメージ自体は軽量でしたが、ハードウェア構成はバラバラでした。32GBのSDカードで動作するものもあれば、1TBのNVMeドライブを搭載したものもありました。デプロイのたびに、ルートパーティションを手動でリサイズするか、初回起動時に growpart や resize2fs を実行するための壊れやすいシェルスクリプトをメンテナンスしなければなりませんでした。

5台以上のサーバーを管理したことがある人なら、このもどかしさがわかるはずです。汎用的なUbuntuのクラウドイメージをダウンロードして起動したものの、OSが認識しているのは、せっかく料金を払った100GBのボリュームのうち、わずか8GBだけだったという経験です。Cloud-initで対処することも可能ですが、最小限の環境には大げさすぎることがよくあります。カスタムの組み込みシステムを構築している場合は、フル機能のCloud-initスイートよりもフットプリントを小さくしたいと考えるでしょう。

標準的なリサイズ手法が大規模環境で失敗する理由

摩擦の原因は、従来のGPTやMBRのパーティションテーブルが「静的」であるという事実にあります。ディスクイメージを作成すると、パーティションテーブルはファイルの最初の数セクターに書き込まれます。このテーブルは、最終的な物理ディスクのサイズを知る術がありません。2GB의 イメージを64GBのディスクに書き込んだとしても、テーブルは2GBのまま固定されます。残りの62GBは、何らかの処理が行われない限り「未割り当て領域」のままです。

手動での修正には通常、以下のような作業が伴います。

  • fdisk を使用してパーティションを削除し、再作成する(本番環境では心臓に悪い作業です)。
  • resize2fs や xfs_growfs を実行して、実際のファイルシステムを拡張する。
  • リサイズ中に停電が発生した場合、データ破損のリスクがある。

過去数年間にわたって数十台のLinuxノードを管理してきた経験から、手動の手順はヒューマンエラーの温床でしかないことを学びました。私は、ディスクレイアウトを処理するための堅牢で宣言的な方法を何週間も探し続けました。その結果、たどり着いたのが systemd-repart です。

競合ツールの比較:growpart vs. systemd-repart

移行を決める前に、標準的なツールを評価しました。多くの管理者は growpart を使用していますが、これは本質的には sfdisk のシェルスクリプトラッパーです。これは「命令型」のツールです。特定のタイミングで「何をすべきか」を正確に指示する必要があります。もしスクリプトがエッジケースに遭遇して途中で失敗すれば、パーティションテーブルが壊れたまま放置されることも少なくありません。

systemd-repart は異なるアプローチを取ります。これは「宣言的」です。シンプルな設定ファイルを使用して「ディスクがどうあるべきか」を定義します。起動の初期段階で、systemd-repart は物理ディスクを調査し、設定と比較します。そして、その状態に到達するために必要な変更を加えます。冪等性(べきとうせい)があるため、何度実行しても何かを壊す心配はありません。

機能 growpart / 手動 systemd-repart
設定 スクリプトベース(命令型) 設定ファイル(宣言型)
安全性 中(スクリプトのロジックに依存) 高(アトミックなGPT更新)
暗号化 手動でのLUKSリサイズが必要 ネイティブなLUKSサポート
複雑さ 複数のバイナリが必要 systemdに組み込み済み

systemd-repartの実装:宣言的アプローチ

複雑なコマンドを実行する代わりに、/usr/lib/repart.d/ または /etc/repart.d/ に .conf ファイルを配置します。このツールは特にGPTパーティションテーブルを対象としていることに注意してください。レガシーなMBR(DOS)形式はサポートしていません。

1. ルートパーティションの拡張

最も一般的なタスクは、ルートパーティションをディスク全体に広げることです。ルートパーティションがディスクの2番目のエントリである場合、50-root.conf という名前のファイルを作成します。

# /etc/repart.d/50-root.conf
[Partition]
Type=root
# 必要な最小サイズ
SizeMinBytes=512M
# 空のままにすると、利用可能なすべてのスペースを使用する
GrowFileSystem=yes

サービスが実行されると、GPT Type GUIDによってパーティションを識別します。そして、カーネルがサポートしていれば、パーティションと基盤となるファイルシステムを同時に拡張します。

2. 専用データパーティションの追加

私が頼りにしている機能の1つに、ウェイト(重み)ベースのシステムがあります。ドライブのサイズに応じてスケールする専用の /var/log パーティションが必要だとしましょう。自分で計算をする必要はありません。

# /etc/repart.d/60-data.conf
[Partition]
Type=linux-generic
Label=Data
# 残りの空き容量の50%を占有する
Weight=500
Format=ext4
MountPoint=/data

Weight=500 を持つパーティションが2つある場合、systemd-repart は残りのスペースを50/50で分割します。これは、同じイメージを32GBのSDカードと1TBのNVMeドライブの両方にデプロイする場合に非常に役立ちます。

3. テストの設定

テストせずに本番環境のディスクに変更をコミットしてはいけません。私は常に最初に --dry-run フラグを使用します。これにより、1バイトも書き込むことなく、提案された変更の詳細なマップが表示されます。

systemd-repart --dry-run --pretty

出力により、現在のレイアウトと提案されたレイアウトが視覚的に表示されます。確認できたら、--apply=yes で手動で適用できます。ほとんどの本番環境の設定では、initramfsステージ中に systemd-repart.service がこれを自動的に処理します。

本番環境での6ヶ月運用から得られた教訓

半年運用してみて、manページには載っていないいくつかの微妙な点に気づきました。

GPTバックアップヘッダー: AWSやProxmoxで仮想ディスクをリサイズすると、GPTバックアップヘッダーが物理的なディスクの末尾ではなくなります。systemd-repart はこれを自動的に修正します。ただし、ブロックデバイスへの書き込み権限が必要であり、一部の堅牢化されたコンテナ環境では制限される可能性があります。

ファイルシステムのサポート: GrowFileSystem=yes の切り替えは、Ext4、XFS、Btrfsで完璧に動作します。より特殊なファイルシステムを使用している場合、systemd-repart はパーティションを拡張しますが、内部のリサイズを処理するために systemd-growfs が必要になる場合があります。

英数字順の並び: repart.d/ 内のファイルはアルファベット順に処理されます。10-root.conf と 20-data.conf の両方が拡張を要求している場合、その順序によって物理的な配置が決まります。レイアウトの予期せぬ事態を避けるために、厳格な番号付け規則を守ってください。

あなたに適していますか?

1台のノートPCを管理しているだけなら、これはおそらく過剰(オーバースペック)です。しかし、ディスクイメージを構築したり、クラウドフリートを管理したり、IoTデバイスを出荷したりする人にとっては、大きなアップグレードとなります。私たちの200行のシェルスクリプトは、3つのシンプルな設定ファイルに置き換わりました。

systemdエコシステム(特にLUKSや systemd-growfs)との深い統合により、インフラストラクチャの予測可能性が高まります。私の経験では、午前3時にサーバーが故障したとき、予測可能性こそが最大の味方です。もし、まだ起動スクリプトで fdisk のハックを使っているなら、systemd-repart を試してみてください。ただし、最初に --dry-run を実行することを忘れないでください。

Share: