systemd-nspawn
systemd-nspawn は chroot コマンドに似ていますが、chroot を強化したものです。
systemd-nspawn を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム構造だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため chroot よりも強力です。
systemd-nspawn は /sys
, /proc/sys
, /sys/fs/selinux
などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノードを作成することも不可能です。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールをロードすることも制限されます。
仕組みとしては Lxc-systemd や Libvirt-lxc と異なり、とてもシンプルなツールで設定を行います。
インストール
systemd-nspawn は systemd に含まれています。
サンプル
コンテナに最小限の Arch Linux ディストリビューションを作成して起動
まず公式リポジトリからパッケージ arch-install-scripts をインストールしてください。
そして、お好きな場所にディレクトリを作成してください。例えば: $ mkdir ~/MyContainer
。
pacstrap を使って最小限の arch システムをコンテナにインストールします。最低限でも base グループはインストールする必要があります。
# pacstrap -i -c -d ~/MyContainer base [additional pkgs/groups]
インストールが完了したら、コンテナを起動してください (-b
はシェルを実行する代わりにコンテナを起動します (つまり PID=1 として systemd
を実行)。-D
にはコンテナのルートディレクトリにするディレクトリを指定します。-n
はホストとコンテナ間のプライベートネットワークを設定します):
# systemd-nspawn -b -D ~/MyContainer -n
これで終わりです。空のパスワードを使って "root" でログインしてください。
コンテナの電源を切りたいときはコンテナの中から poweroff
を実行することで出来ます。ホストからは、machinectl ツールでコンテナを制御できます。
x86_64 環境で Arch Linux i686 をブートストラップ
サブディレクトリの中に i686 の最小限の Arch Linux をインストールして chroot や仮想化するかわりに systemd-nspawn コンテナとして使うことができます。i686 環境で PKGBUILD
のコンパイルをテストしたい場合などに有用です。pacman.conf
で multilib
リポジトリが有効になっていないことを確認してください。
# pacman_conf=/tmp/pacman.conf # this is pacman.conf without multilib # mkdir /mnt/i686-archlinux # linux32 pacstrap -C "$pacman_conf" -di /mnt/i686-archlinux base base-devel
base
グループの linux
の選択は解除してかまいません。作成されるブートストラップディレクトリは実機や仮想マシン上で実行するわけではないためです。
作成された i686 の Arch Linux の systemd-nspawn インスタンスを起動するには、以下のコマンドを実行:
# linux32 systemd-nspawn -D /mnt/i686-archlinux
Debian や Ubuntu 環境の作成
debootstrap, gnupg1AUR と debian-archive-keyringAUR か ubuntu-keyringAUR のどちらか (インストールしたい方のディストリのキーリング) をインストールしてください。
後は簡単に Debian や Ubuntu 環境をセットアップできます:
# cd /var/lib/machines # debootstrap <codename> myContainer <repository>
Debian の場合、コードネームとして指定するのは "stable" や "testing" などのローリングの名前か "stretch" や "sid" などのリリース名になります。Ubuntu の場合、"wily" や "hardy" などのコードネームを使ってください。完全なリストは /usr/share/debootstrap/scripts
にあります。
Arch と違って、Debian や Ubuntu は最初のログイン時にパスワードが要ることになっています。root のパスワードを設定するために、'-b' オプションを付けずにログインしてからパスワードを設定してください:
# systemd-nspawn -D myContainer # passwd # logout
マシンのブート時にコンテナを起動する
コンテナを頻繁に使用する場合、ブート時に systemd でコンテナを起動できます。まず systemd
ターゲットの machines.target
を有効化してください:
# systemctl enable machines.target
それから以下を実行してください:
# mv ~/MyContainer /var/lib/machines/MyContainer # systemctl enable systemd-nspawn@MyContainer.service # systemctl start systemd-nspawn@MyContainer.service
control group の中身を表示したい場合は、$ systemd-cgls
を実行してください。
管理
使用例は他のディストリビューションのパッケージの作成を参照。
machinectl
コンテナの管理は原則 $ machinectl
コマンドで行います。このサービスを使って仮想マシンやコンテナの状態を確認したり操作します。オプションの詳細なリストは machinectl(1)
を参照してください。
例:
- 実行中のコンテナに新しいシェルを起動:
$ machinectl login MyContainer
- コンテナの詳細情報を表示:
$ machinectl status MyContainer
- コンテナを再起動:
$ machinectl reboot MyContainer
- コンテナを電源オフ:
$ machinectl poweroff MyContainer
- イメージをダウンロード:
# machinectl pull-tar URL name
systemd ツールチェイン
systemd のコアツールチェインは多くがコンテナでも使えるようにアップデートされています。コンテナの名前を引数とする -M, --machine=
オプションをツールに付けるだけです。
例:
- 特定のマシンの journal ログを表示:
$ journalctl -M MyContainer
- control group の中身を表示:
$ systemd-cgls -M MyContainer
- コンテナの起動時間を表示:
$ systemd-analyze -M MyContainer
- リソース利用状況を表示:
$ systemd-cgtop
Tips and tricks
X 環境
新しいコンテナで X アプリケーションを動かす必要がある場合は Xhost を見て下さい。
外部の X サーバーにコンテナのセッションを接続するには DISPLAY
環境変数を設定する必要があります。
X は必要なファイルを /tmp
ディレクトリに保存します。コンテナから全てを表示させるには、/tmp
ディレクトリのファイルにアクセスできるようにしなくてはなりません。コンテナを起動するときに --bind=/tmp/.X11-unix:/tmp/.X11-unix
オプションを追加してください。
nspawn コンテナの中で Firefox を実行
Firefox 設定#nspawn コンテナの中で Firefox を実行を見て下さい。
ホストのファイルシステムにアクセス
例えばホストとコンテナの両方が Arch Linux で、pacman のキャッシュを共有するには:
# systemd-nspawn --bind=/var/cache/pacman/pkg
詳しくは man systemd-nspawn
の --bind
と --bind-ro
を参照してください。
ネットワーク
ネットワーク管理に systemd-networkd を使用して DNS に systemd-resolved
を使用する、インターネットに接続できる最も簡単な設定:
# systemctl enable --now systemd-networkd systemd-resolved # ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf # let systemd-resolved manage /etc/resolv.conf
上記の設定を使うには -n
スイッチを使って systemd-nspawn
を実行して、ホストに仮想イーサネットリンクを作成する必要があります。
systemd-resolved
を使わないでコンテナの /etc/resolv.conf
を手動で編集して DNS サーバーの IP アドレスを追加することも可能です。
基本的な systemd-networkd のホストとコンテナの .network
ファイルは https://github.com/systemd/systemd/tree/master/network にあります。
もっと複雑なネットワークを設定する方法は、systemd-networkd#コンテナでの使用方法を見て下さい。
nsswitch.conf
ホストからコンテナへの接続を楽にするために、コンテナの名前のローカル DNS 解決を有効にすることができます。/etc/nsswitch.conf
の hosts:
セクションに mymachines
を追加してください:
hosts: files mymachines dns myhostname
こうすると、ホスト上でホストネーム foo
の DNS ルックアップで /etc/hosts
が参照され、それからローカルコンテナの名前、上流の DNS などが参照されます。
ホストのネットワークを使用
machinectl start MyContainer
で起動したコンテナによって使用されるプライベートネットワークを無効化するには systemctl edit systemd-nspawn@.service
を実行して systemd-nspawn@.service
サービスファイルの設定を編集してください。--network-veth
パラメータを削除するように ExecStart=
オプションを設定します:
/etc/systemd/system/systemd-nspawn@.service.d/override.conf
[Service] ExecStart= ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --machine=%I
次に起動したコンテナはホストのネットワークを使用するようになります。
仮想イーサネットインターフェイス
コンテナを systemd-nspawn ... -n
で起動した場合、systemd は自動的にホストとコンテナに仮想イーサネットインターフェイスを作成して、仮想イーサネットケーブルで接続します。
コンテナの名前が foo
ならば、仮想イーサネットインターフェイスのホストにおける名前は ve-foo
になり、コンテナではどんな場合でも名前は host0
です。
ip link
でインターフェイスを確認すると、インターフェイスの名前には ve-foo@if2
や host0@if9
のように接尾辞が付きます。@ifN
は実際はインターフェイスの名前には含まれていません。仮想イーサネットケーブルが他の端末に接続されていることを示すために ip link
によって情報が加えられています。
例えば、ホストの仮想イーサネットインターフェイス ve-foo@if2
がコンテナ foo
に接続、コンテナの中の2番目のネットワークインターフェイスに接続する場合、コンテナの中から ip link
を実行するとインデックス 2 が付きます。同じように、コンテナの host0@if9
という名前のインターフェイスはホストの9番目のインターフェイスに接続します。
systemd を使っていない環境で動作させる
Init#systemd-nspawn を見て下さい。
Btrfs のサブボリュームをコンテナのルートとして使う
Btrfs サブボリュームをコンテナのルートのテンプレートとして使うには、--template
フラグを使用します。サブボリュームのスナップショットを使ってコンテナのルートディレクトリが生成されます。
例えば、/.snapshots/403/snapshot
に存在するスナップショットを使うには:
# systemd-nspawn --template=/.snapshots/403/snapshots -b -D my-container
my-container
は作成するコンテナのディレクトリの名前に置き換えてください。電源を切っても、新しく作成されたサブボリュームは消えません。
コンテナの一時的な Btrfs スナップショットを使う
--ephemeral
や -x
フラグを使ってコンテナの一時的な btrfs スナップショットを作成してコンテナのルートとして利用できます。コンテナの実行中に変更が加えられても保存されません。例:
# systemd-nspawn -D my-container -xb
my-container はシステムに存在する既存のコンテナのディレクトリに置き換えてください。例えば /
が btrfs のサブボリュームだった場合、以下のコマンドで実行中のホスト環境の一時的なコンテナを作成することができます:
# systemd-nspawn -D / -xb
コンテナの電源を切ると、作成された btrfs サブボリュームはすぐに削除されます。
トラブルシューティング
root ログインが失敗する
(machinectl login <name>
を使用して) ログインしようとしたときに以下のエラーが表示される場合:
arch-nspawn login: root Login incorrect
そして journalctl
が以下のように表示する場合:
pam_securetty(login:auth): access denied: tty 'pts/0' is not secure !
コンテナのファイルシステム上にある /etc/securetty
のターミナル名のリストに pts/0
を追加してください。詳しくは [3] を参照。また、コンテナの /etc/securetty
を削除して root で全ての tty にログインできるようにするという方法もあります。[4] を見てください。
コンテナのパッケージをアップグレードできない
ときどきコンテナの特定のパッケージがアップグレードできなくなることがあります。filesystem などが特にそうです。原因は /sys
が読み取り専用でマウントされていることにあります。mount -o remount,rw -t sysfs sysfs /sys
を実行してディレクトリを読み書き可能で再マウントしてから、アップグレードを行なって、コンテナを再起動してください。