「Systemd-nspawn」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
39行目: 39行目:
 
# pacstrap -c ~/MyContainer base [additional pkgs/groups]
 
# pacstrap -c ~/MyContainer base [additional pkgs/groups]
   
{{Tips|{{Pkg|base}} パッケージは、{{Pkg|linux}} パッケージに依存せず、コンテナにも対応しています。}}
+
{{Tip|{{Pkg|base}} パッケージは、{{Pkg|linux}} パッケージに依存せず、コンテナにも対応しています。}}
   
 
インストールが完了したら、コンテナに chroot し、root パスワードを設定します。
 
インストールが完了したら、コンテナに chroot し、root パスワードを設定します。

2020年6月22日 (月) 15:28時点における版

関連記事

systemd-nspawnchroot コマンドに似ていますが、chroot を強化したものです。

systemd-nspawn を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム構造だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため chroot よりも強力です。

systemd-nspawn/sys, /proc/sys, /sys/fs/selinux などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノードを作成することも不可能です。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールをロードすることも制限されます。

仕組みとしては Lxc-systemdLibvirt-lxc と異なり、とてもシンプルなツールで設定を行います。

インストール

systemd-nspawnsystemd に含まれています。

サンプル

コンテナに最小限の Arch Linux ディストリビューションを作成して起動

まず arch-install-scripts パッケージをインストールしてください。

そして、お好きな場所にディレクトリを作成してください。例えば: $ mkdir ~/MyContainer

pacstrap を使って最小限の arch システムをコンテナにインストールします。最低限でも base グループはインストールする必要があります。

# pacstrap -c ~/MyContainer base [additional pkgs/groups]
ヒント: base パッケージは、linux パッケージに依存せず、コンテナにも対応しています。

インストールが完了したら、コンテナに chroot し、root パスワードを設定します。

# systemd-nspawn -D ~/MyContainer
# passwd
# logout

最後に、コンテナを起動します。

# systemd-nspawn -b -D ~/MyContainer

(-b はシェルを実行する代わりにコンテナを起動します (つまり PID=1 として systemd を実行)。-D にはコンテナのルートディレクトリにするディレクトリを指定します):

コンテナが開始したら、空のパスワードを使って "root" でログインしてください。

ノート: "Login incorrect" でログインが失敗する場合、問題は、securetty TTY デバイスのホワイトリストである可能性があります。#root ログインが失敗する をご確認ください。

コンテナの電源を切りたいときはコンテナの中から poweroff を実行することで出来ます。ホストからは、machinectl ツールでコンテナを制御できます。

ノート: コンテナの中からセッションを終了するには Ctrl を押しながら ] を素早く3回押してください。US キーボード以外の場合は ] の代わりに % を使用します。

x86_64 環境で Arch Linux i686 をブートストラップ

サブディレクトリの中に i686 の最小限の Arch Linux をインストールして chroot仮想化するかわりに systemd-nspawn コンテナとして使うことができます。i686 環境で PKGBUILD のコンパイルをテストしたい場合などに有用です。pacman.confmultilib リポジトリが有効になっていないことを確認してください。

# pacman_conf=/tmp/pacman.conf # this is pacman.conf without multilib
# mkdir /mnt/i686-archlinux
# linux32 pacstrap -C "$pacman_conf" -i /mnt/i686-archlinux base base-devel

base グループの linux の選択は解除してかまいません。作成されるブートストラップディレクトリは実機や仮想マシン上で実行するわけではないためです。

作成された i686 の Arch Linux の systemd-nspawn インスタンスを起動するには、以下のコマンドを実行:

# linux32 systemd-nspawn -D /mnt/i686-archlinux

Debian や Ubuntu 環境の作成

debootstrapdebian-archive-keyringubuntu-keyring のどちらか (インストールしたい方のディストリのキーリング) をインストールしてください。

ノート: systemd-nspawn を使用するにはコンテナ内の OS で systemd が PID 1 として動作している必要があります。Ubuntu 15.04 以前は、そのままでは動作せず、upstart から systemd への移行が必須です。また、コンテナ環境に systemd-container パッケージをインストールしてください。

後は簡単に Debian や Ubuntu 環境をセットアップできます:

# cd /var/lib/machines
# debootstrap <codename> myContainer <repository-url>

Debian の場合、コードネームとして指定するのは "stable" や "testing" などのローリングの名前か "stretch" や "sid" などのリリース名になります。Ubuntu の場合、"xenial" や "zesty" などのコードネームを使ってください。コードネームの完全なリストは /usr/share/debootstrap/scripts にあります。Debian イメージの場合は "repository-url" には http://deb.debian.org/debian/ などを指定します。Ubuntu のイメージの場合は "repository-url" は http://archive.ubuntu.com/ubuntu/ などとなります。

Arch と違って、Debian や Ubuntu は最初のログイン時にパスワードが要ることになっています。root のパスワードを設定するために、'-b' オプションを付けずにログインしてからパスワードを設定してください:

# systemd-nspawn -D myContainer
# passwd
# logout

上記のコマンドで上手く行かない場合、コンテナを起動してから以下のコマンドを使ってみてください:

# systemd-nspawn -b -D myContainer  #Starts the container
# machinectl shell root@myContainer /bin/bash  #Get a root bash shell
# passwd
# logout

プライベートユーザーの作成 (非特権コンテナ)

systemd-nspawn は非特権コンテナをサポートしていますが、コンテナは root で起動する必要があります。

ノート: 非特権コンテナは user_namespaces(7) を必要とします。詳しくは Linux Containers#非特権コンテナのサポートを有効化 (任意) を参照してください。

非特権コンテナを使うときは systemd-nspawn に全てを決めさせるのが一番簡単です:

# systemd-nspawn -UD myContainer
# passwd
# logout
# systemd-nspawn -bUD myContainer

上記のコマンドで systemd-nspawn はディレクトリの所有者が使われているかどうか確認して、使われていない場合は所有者をベースとしてそれを上回る 65536 の ID が使われます。一方で UID/GID が使用中の場合はランダムに 524288 - 1878982656 の範囲から 65536 の ID を選択します。

ノート:
  • ランダムに選ばれるベース ID は必ず 65536 の倍数です。
  • カーネルがユーザー名前空間をサポートしている場合、-U--private-users=pick は同じです。--private-users=pick には --private-users-chown が暗黙的に含まれます。詳しくは systemd-nspawn(1) を参照してください。

コンテナの UID/GID を手動で指定することも可能です:

# systemd-nspawn -D myContainer --private-users=1354956800:65536 --private-users-chown
# passwd
# logout
# systemd-nspawn -bUD myContainer

コンテナの起動時に --private-users=1354956800:65536--private-users-chown を使うこともできますが、無駄に複雑なので、ID を割り当てた後に -U を使うようにしてください。

マシンのブート時にコンテナを起動する

コンテナを頻繁に使用する場合、ブート時に 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
ノート: systemd-nspawn@.service は nspawn コンテナが /var/lib/machines にあることを想定したテンプレートユニットです。
ヒント:
  • systemd v229 現在 /var/lib/machines にコンテナのシンボリックリンクを作成しても動作しません。[1] を参照。
  • コンテナの起動をカスタマイズする場合、/etc/systemd/nspawn/myContainer.nspawn ユニットを編集してください。利用可能なオプションは systemd.nspawn(5) を参照。

control group の中身を表示したい場合は、$ systemd-cgls を実行してください。

管理

使用例は他のディストリビューションのパッケージの作成を参照。

machinectl

ノート: machinectl ツールを使うには systemddbus がコンテナにインストールされている必要があります。詳しくは [2] を参照。

コンテナの管理は原則 $ machinectl コマンドで行います。このサービスを使って仮想マシンやコンテナの状態を確認したり操作します。オプションの詳細なリストは machinectl(1) を参照してください。

例:

  • 実行中のコンテナに新しいシェルを起動:
    $ machinectl login MyContainer
  • コンテナの詳細情報を表示:
    $ machinectl status MyContainer
  • コンテナを再起動:
    $ machinectl reboot MyContainer
  • コンテナを電源オフ:
    $ machinectl poweroff MyContainer
ヒント: 電源オフや再起動は systemctlrebootpoweroff コマンドをコンテナのセッションの中から実行することでも可能です。
  • イメージをダウンロード:
    # 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

ヒントとテクニック

X 環境

新しいコンテナで X アプリケーションを動かす必要がある場合は Xhost を見て下さい。

外部の X サーバーにコンテナのセッションを接続するには DISPLAY 環境変数を設定する必要があります。

X は必要なファイルを /tmp ディレクトリに保存します。コンテナから全てを表示させるには、/tmp ディレクトリのファイルにアクセスできるようにしなくてはなりません。コンテナを起動するときに --bind=/tmp/.X11-unix:/tmp/.X11-unix オプションを追加してください。

ノート: systemd バージョン 235 には バグ が存在し、/tmp/.X11-unix がファイルシステムから消失することがあります。問題を回避するには /tmp/.X11-unix を読み取り専用でバインドしてください: --bind-ro=/tmp/.X11-unix/X0/run/user/1000 もバインドしている場合は明示的に /run/user/1000/bus を読み取り専用でバインドすることで dbus ソケットが削除されないように保護することができます。

nspawn コンテナの中で Firefox を実行

Firefox 設定#nspawn コンテナの中で Firefox を実行を見て下さい。

ホストのファイルシステムにアクセス

例えばホストとコンテナの両方が Arch Linux で、pacman のキャッシュを共有するには:

# systemd-nspawn --bind=/var/cache/pacman/pkg

詳しくは systemd-nspawn(1)--bind--bind-ro を参照してください。

ファイルを使ってコンテナごとにバインドを設定することもできます:

/etc/systemd/nspawn/my-container.nspawn
[Files]
Bind=/var/cache/pacman/pkg

#コンテナごとに設定を指定するを参照。

ネットワーク

ネットワーク管理に 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.confhosts: セクションに 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@if2host0@if9 のように接尾辞が付きます。@ifN は実際はインターフェイスの名前には含まれていません。仮想イーサネットケーブルが他の端末に接続されていることを示すために ip link によって情報が加えられています。

例えば、ホストの仮想イーサネットインターフェイス ve-foo@if2 がコンテナ foo に接続、コンテナの中の2番目のネットワークインターフェイスに接続する場合、コンテナの中から ip link を実行するとインデックス 2 が付きます。同じように、コンテナの host0@if9 という名前のインターフェイスはホストの9番目のインターフェイスに接続します。

ネットワークブリッジを使用

ローカルネットワークの物理マシンのようにコンテナに IP アドレスを割り当てるためにホスト環境にネットワークブリッジを設定している場合 (詳しくは systemd-networkd#2つの別々な IP で DHCP を使うsystemd-networkd#固定 IP ネットワークを参照)、--network-bridge=br0 オプションを使って systemd-nspawn から利用することができます。

systemd を使っていない環境で動作させる

Init#systemd-nspawn を見て下さい。

コンテナごとに設定を指定する

全体設定を上書きすることなく各コンテナの設定を指定したい場合 (例: どれかひとつのコンテナにディレクトリをバインドする場合)、.nspawn ファイルを使うことで設定できます [3]systemd.nspawn(5) を見てください [4]

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 を追加してください。詳しくは [5] を参照。また、コンテナの /etc/securetty を削除して root で全ての tty にログインできるようにするという方法もあります。[6] を見てください。

コンテナのパッケージをアップグレードできない

ときどきコンテナの特定のパッケージがアップグレードできなくなることがあります。filesystem などが特にそうです。原因は /sys が読み取り専用でマウントされていることにあります。mount -o remount,rw -t sysfs sysfs /sys を実行してディレクトリを読み書き可能で再マウントしてから、アップグレードを行なって、コンテナを再起動してください。

参照