テスト環境のオーバーエンジニアリングはやめよう:systemd-nspawn入門ガイド

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

小さな作業に大がかりなツールは必要か?

DockerやPodmanはコンテナ界の強力なツールですが、単一のスクリプトを30秒間テストしたいだけの時には、オーバースペックに感じることがあります。過去3年間で数十台のLinux VPSノードを管理してきた経験から、最も洗練されたツールは、すでにinitデーモンの中に隠れていることが多いと学びました。それがsystemd-nspawnです。

systemd-nspawnは「知能を持ったchroot」のようなものです。Linuxの名前空間(Namespaces)を利用してファイルシステム、プロセス、ネットワークを隔離しますが、重いバックグラウンドデーモンは必要ありません。systemdと直接統合されているため、非常に軽量です。最新のUbuntu、Fedora、Archなどを使用しているなら、すでにドライブの中にインストールされており、コマンド一つで起動できる状態にあるはずです。

クイックスタート:3分でコンテナを立ち上げる

まず、ルートファイルシステムが必要です。今回はDebianを例にします。最小限のベースイメージを取得するために、debootstrapユーティリティを使用します。標準的な回線速度であれば、120秒もかかりません。

# ツールをインストールする
sudo apt update
sudo apt install systemd-container debootstrap -y

# 設置場所を準備する
sudo mkdir -p /var/lib/machines/test-env

# 最小限のDebian Stable環境を取得する
sudo debootstrap stable /var/lib/machines/test-env http://deb.debian.org/debian/

ダウンロードが完了したら、次のコマンドですぐにコンテナの中に入ることができます:

sudo systemd-nspawn -D /var/lib/machines/test-env

これで隔離されたシェルに入りました。何を壊しても大丈夫です。ホストOSは一切影響を受けません。終了するには、exitと入力するか、Ctrl+]を素早く3回押します。

仕組みを詳しく見る

なぜ標準的なchrootよりも優れているのでしょうか?chrootはルートディレクトリを隠すだけですが、systemd-nspawnはプロセスツリー(PID名前空間)やネットワークスタックまで完全に隔離します。仮想マシン(VM)のように感じられますが、ホストのカーネルを共有しているため、起動時間は通常0.5秒未満です。パフォーマンスの低下もほとんどありません。

「フルブート」モード

シェルを開くだけでも編集には便利ですが、systemd-nspawnは独立したサーバーのようにコンテナを「起動(ブート)」させることもできます。これによりコンテナ自身のinitプロセスが開始され、NginxやPostgreSQLなどのサービスを実際の環境に近い形でテストできます。

# コンテナを起動してログインプロンプトを表示する
sudo systemd-nspawn -bD /var/lib/machines/test-env

-bフラグは、/lib/systemd/systemdなどのinitバイナリを探します。ターミナルウィンドウにおなじみのブートログが流れるのが見えるはずです。

隔離されたネットワーク

デフォルトでは、コンテナはホストのネットワークIPを共有します。コンテナに独自の仮想インターフェースを割り当てるには、仮想イーサネット(veth)フラグを使用します:

sudo systemd-nspawn -bD /var/lib/machines/test-env --network-veth

この設定により、ホストとコンテナの間にプライベートなトンネルが作成されます。ホストでsystemd-networkdが有効になっていれば、これらのインスタンスに自動的にDHCPアドレスを割り当てることができます。

プロのようにマシンを管理する

systemd-nspawnがエンジンなら、machinectlはハンドルです。バックグラウンドのコンテナ管理やイメージのダウンロードを簡単に行える管理ツールです。

バックグラウンドサービス

ターミナルを閉じてもコンテナを動かし続けたい場合は、他のシステムサービスと同じように管理できます:

# コンテナをバックグラウンドで開始する
sudo machinectl start test-env

# ホスト再起動時にも自動起動するように設定する
sudo machinectl enable test-env

# 実行中のバックグラウンドコンテナに入る
sudo machinectl shell test-env

一時的なスナップショットの威力

ファイルシステムを壊してしまう可能性のある実験的なスクリプトをテストすることがよくあります。ベースイメージを危険にさらす代わりに、--ephemeral(または-x)フラグを使用します。これはコンテナが停止した瞬間に消える一時的なスナップショットを作成します。究極の「元に戻す」ボタンです。

sudo systemd-nspawn -x -D /var/lib/machines/test-env

ワークフローのための実践的なヒント

この環境を数年間使い続けた結果、トラブルを防ぐための3つの習慣にたどり着きました:

  • 締め出しに注意: ブートモード(-b)ではログインが必要です。シェルモードの時にrootパスワードを設定していないと、プロンプトで立ち往生してしまいます。必ず事前にコンテナ内でpasswdを実行しておきましょう。
  • ディスク容量の増加に注意: これらのコンテナは小さいですが、積み重なると無視できません。machinectl listで稼働状況を確認し、週に一度はdu -sh /var/lib/machines/*を実行して、忘れ去られたテスト環境でギガバイト単位の容量を無駄にしていないかチェックしましょう。
  • コピペを省略する: ホストにあるコードをテストする場合、ファイルを移動させる必要はありません。--bindを使用して、プロジェクトフォルダを直接コンテナにマウントしましょう。その方が速いですし、ファイルも同期されます。
# ローカルのコードをコンテナの /opt フォルダにリンクする
sudo systemd-nspawn -D /var/lib/machines/test-env --bind=/home/user/project:/opt/project

systemd-nspawnは、大規模なKubernetesクラスターを置き換えるものではありません。しかし、個人の開発者やシステム管理者にとって、ホストシステムをクリーンに保つための最も効率的な方法です。OS標準機能であり、電光石火の速さで、Linuxの哲学を尊重しています。次にメインサーバーに雑多なライブラリをインストールしたくなったら、代わりにnspawnコンテナを立ち上げてみてください。ホストシステムは純粋なまま保たれ、あなたの精神衛生も守られるはずです。

Share: