「Systemd-nspawn」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
17行目: 17行目:
 
''systemd-nspawn'' を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム階層だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため [[chroot]] よりも強力です。
 
''systemd-nspawn'' を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム階層だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト・ドメイン名も完全に仮想化するため [[chroot]] よりも強力です。
   
''systemd-nspawn'' は {{ic|/sys}}, {{ic|/proc/sys}}, {{ic|/sys/fs/selinux}} などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノードが作成されない場合があり。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールロードすること制限され
+
''systemd-nspawn'' は {{ic|/sys}}, {{ic|/proc/sys}}, {{ic|/sys/fs/selinux}} などのコンテナの様々なカーネルインターフェイスへのアクセスを読み取り専用に制限します。コンテナの中からネットワークインターフェイスやシステムクロックを変更することは出来ません。デバイスノードが作成はできせん。コンテナの中からホスト環境を再起動することはできず、カーネルモジュールロードもできせん
   
 
仕組みとしては [[Lxc-systemd]] や [[Libvirt]]-lxc と異なり、とてもシンプルなツールで設定を行います。
 
仕組みとしては [[Lxc-systemd]] や [[Libvirt]]-lxc と異なり、とてもシンプルなツールで設定を行います。

2020年11月27日 (金) 10:48時点における版

関連記事

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 パッケージをインストールしてください。

そして、お好きな場所にディレクトリを作成してください。この例では、~/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 キーボード以外の場合は ] の代わりに % を使用します。

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 --include=systemd-container --components=main,universe codename container-name 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' オプションを付けずにログインしてからパスワードを設定してください:

# cd /var/lib/machines
# systemd-nspawn -D myContainer
# passwd
# logout

パッケージのビルドおよびテスト

使用例については、他のディストリビューションのパッケージの作成 を参照してください。

管理

/var/lib/machines/ にあるコンテナは、machinectl コマンドによって制御することができます。内部的には systemd-nspawn@.service ユニットのインスタンスを制御しています。/var/lib/machines/ のサブディレクトリはコンテナ名に対応しています。

ノート: なんらかの理由でコンテナを /var/lib/machines/ に移動できない場合、シンボリックリンクが使えます。machinectl(1) § FILES AND DIRECTORIES を参照してください。

systemd-nspawn オプションのデフォルト値

machinectlsystemd-nspawn@.service 経由で起動されたコンテナは systemd-nspawn コマンドで起動されたコンテナとはオプションの既定値が異なることを理解することが重要です。サービスが使用する追加オプションは以下の通りです。

  • -b/--boot – マネージドコンテナは自動的に init プログラムを検索し、PID 1 として起動します。
  • --network-veth つまり --private-network – マネージドコンテナは仮想ネットワークインターフェースを取得し、ホストネットワークから切り離されます。詳細は、#ネットワーキング を参照してください。
  • -U – カーネルがサポートしている場合、マネージドコンテナはデフォルトで user_namespaces(7) 機能を使用します。詳細は、#非特権コンテナ を参照してください。
  • --link-journal=try-guest

この動作は、コンテナごとの設定ファイルでオーバーライドすることができます。 詳細は、#設定 を参照してください。

machinectl

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

コンテナはコマンドで管理できます。例えば、コンテナを起動するには、次のようにします。

$ machinectl start container-name

同様に、poweroff、reboot、status,show などのサブコマンドがあります。詳細な説明については、machinectl(1) を参照してください。

その他の一般的なコマンドは以下の通りです:

  • machinectl login MyContainer - 実行中のコンテナに新しいシェルを起動
  • machinectl status MyContainer - コンテナの詳細情報を表示
  • machinectl reboot MyContainer - コンテナを再起動
  • machinectl reboot MyContainer - コンテナを電源オフ
  • machinectl enable MyContainer または machinectl enable MyContainer - コンテナを有効または無効にして、起動時に開始します。詳細については、#Enable container to start at boot を参照してください。

machinectl にはコンテナ(または仮想マシン)イメージとイメージ転送を管理するためのサブコマンドもあります。詳細については、machinectl(1) § Image Commands および、machinectl(1) § Image Transfer Commands を参照してください。

systemd ツールチェイン

systemd のコアツールチェインは多くがコンテナでも使えるようにアップデートされています。コンテナの名前を引数とする -M, --machine= オプションをツールに付けるだけです。

例:

  • 特定のマシンの journal ログを表示:
    $ journalctl -M MyContainer
  • control group の中身を表示:
    $ systemd-cgls -M MyContainer
  • コンテナの起動時間を表示:
    $ systemd-analyze -M MyContainer
  • リソース利用状況を表示:
    $ systemd-cgtop

設定

コンテナ毎の設定

グローバル設定のオーバーライドではなく、コンテナ毎の設定を指定するには、.nspawn ファイルを使用できます。詳細については、 systemd.nspawn(5) を参照してください。

ノート:
  • .nspawn ファイルは、machinectl remove を実行した時に、/etc/systemd/nspawn/ から予期せずに削除される場合があります。
  • systemd-nspawn@.service ファイルで指定されている、--settings=override がある場合、.nspawn ファイルで指定されているネットワークオプションとコマンドラインオプションの相互作用で正しく動作しません。回避策としてサービスが --network-veth を指定している場合でも、VirtualEthernet=on オプションを含める必要があります。

PC起動時にコンテナを自動で開始する

コンテナを頻繁に使用する場合は、PC起動時に開始することをおすすめします。

まず、machines.target有効になっている事を確認します。 machinectl で検出可能なコンテナは、有効または無効にできます:

$ machinectl enable container-name
ノート:
  • This has the effect of enabling the systemd-nspawn@container-name.service systemd unit.
  • As mentioned in #Default systemd-nspawn options, containers started by machinectl get a virtual Ethernet interface. To disable private networking, see #Use host networking.

リソース制御

systemctl set-property でコンテナの制限やリソース管理を実装するために、コントロールグループを利用することができます。systemd.resource-control(5) を参照してください。例えば、メモリ容量やCPU使用率を制限できます。コンテナのメモリ消費を2GiBに制限するには:

# systemctl set-property systemd-nspawn@container-name.service MemoryMax=2G

または、CPU時間の使用量をだいたい2コア分に制限したい場合:

# systemctl set-property systemd-nspawn@container-name.service CPUQuota=200%

これにより以下の永続ファイルが作成されます。 /etc/systemd/system.control/systemd-nspawn@container-name.service.d/.

ドキュメントによると、MemoryHigh はメモリ消費をチェックするための推奨される方法ですが、MemoryMax のように厳密に制限されることはありません。MemoryMax を最終防衛戦として残して、両方のオプションを使用できます。また、コンテナが認識できるCPUの数を制限しないことも考慮に入れてください。ただし、CPU時間合計に対して、コンテナが最大で取得する時間を制限することで、同様の結果が得られます。

ヒント: これらの変更を一時的なものにしたい場合は、--runtime オプションを渡すことができます。その結果は、systemd-cgtop で確認できます。

ネットワーキング

systemd-nspawn コンテナは、ホストネットワーク または プライベートネットワークのいずれかを使用できます。

  • ホストネットワークモードでは、コンテナはホストネットワークへのフルアクセスが可能です。これは、コンテナがホスト上のすべてのネットワークサービスにアクセスできるようになり、コンテナからのパケットがホストのパケットとして外部ネットワークに表示される事を意味します(つまり、同じIPアドレスを共有します)。
  • プライベートネットワークモードでは、コンテナはホストのネットワークから切断されています。これにより、ループバックデバイスとコンテナに明示的に割り当てられたものを除いて、すべてのネットワークインターフェイスがコンテナを使用できなくなります。コンテナのネットワークインターフェイスを設定するには、いくつかの方法があります。
    • an existing interface can be assigned to the container (e.g. if you have multiple Ethernet devices),
    • a virtual network interface associated with an existing interface (i.e. VLAN interface) can be created and assigned to the container,
    • a virtual Ethernet link between the host and the container can be created.
In the latter case the container's network is fully isolated (from the outside network as well as other containers) and it is up to the administrator to configure networking between the host and the containers. This typically involves creating a network bridge to connect multiple (physical or virtual) interfaces or setting up a Network Address Translation between multiple interfaces.

The host networking mode is suitable for application containers which do not run any networking software that would configure the interface assigned to the container. Host networking is the default mode when you run systemd-nspawn from the shell.

On the other hand, the private networking mode is suitable for system containers that should be isolated from the host system. The creation of virtual Ethernet links is a very flexible tool allowing to create complex virtual networks. This is the default mode for containers started by machinectl or systemd-nspawn@.service.

The following subsections describe common scenarios. See systemd-nspawn(1) § Networking Options for details about the available systemd-nspawn options.

ホストネットワークを使う

プライベートネットワークを無効にし、machinectl で開始されたコンテナで使用される仮想イーサネットリンクを作成するには、次のオプションを指定して、.nspawn ファイルを追加します:

/etc/systemd/nspawn/container-name.nspawn
[Network]
VirtualEthernet=no

これにより、systemd-nspawn@.service-n/--network-veth オプションが上書きされ、新しく開始されたコンテナはホストネットワークモードを使用します。

Use a virtual Ethernet link

If a container is started with the -n/--network-veth option, systemd-nspawn will create a virtual Ethernet link between the host and the container. The host side of the link will be available as a network interface named ve-container-name. The container side of the link will be named host0. Note that this option implies --private-network.

ノート:
  • If the container name is too long, the interface name will be shortened (e.g. ve-long-conKQGh instead of ve-long-container-name) to fit into the 15-characters limit. The full name will be set as the altname property of the interface (see ip-link(8)) and can be still used to reference the interface.
  • When examining the interfaces with ip link, interface names will be shown with a suffix, such as ve-container-name@if2 and host0@if9. The @ifN is not actually part of the interface name; instead, ip link appends this information to indicate which "slot" the virtual Ethernet cable connects to on the other end.
For example, a host virtual Ethernet interface shown as ve-foo@if2 is connected to the container foo, and inside the container to the second network interface – the one shown with index 2 when running ip link inside the container. Similarly, the interface named host0@if9 in the container is connected to the 9th network interface on the host.

When you start the container, an IP address has to be assigned to both interfaces (on the host and in the container). If you use systemd-networkd on the host as well as in the container, this is done out-of-the-box:

  • the /usr/lib/systemd/network/80-container-ve.network file on the host matches the ve-container-name interface and starts a DHCP server, which assigns IP addresses to the host interface as well as the container,
  • the /usr/lib/systemd/network/80-container-host0.network file in the container matches the host0 interface and starts a DHCP client, which receives an IP address from the host.

If you do not use systemd-networkd, you can configure static IP addresses or start a DHCP server on the host interface and a DHCP client in the container. See Network configuration for details.

To give the container access to the outside network, you can configure NAT as described in Internet sharing#Enable NAT. If you use systemd-networkd, this is done (partially) automatically via the IPMasquerade=yes option in /usr/lib/systemd/network/80-container-ve.network. However, this issues just one iptables rule such as

-t nat -A POSTROUTING -s 192.168.163.192/28 -j MASQUERADE

The filter table has to be configured manually as shown in Internet sharing#Enable NAT. You can use a wildcard to match all interfaces starting with ve-:

# iptables -A FORWARD -i ve-+ -o internet0 -j ACCEPT
ノート: systemd-networkd uses the libiptc library to interact with iptables. If you use nftables, install the iptables-nft translation layer. See also systemd issue 13307.
この記事またはセクションの正確性には問題があります。
理由: Investigate if/why the following is necessary. (議論: トーク:Systemd-nspawn#)

Additionally, the rule -A FORWARD -i ve-+ -o internet0 -j ACCEPT may not work as described in Internet sharing#Enable NAT. If that is the case, try -A FORWARD -i ve-+ -j ACCEPT.

Use a network bridge

If you have configured a network bridge on the host system, you can create a virtual Ethernet link for the container and add its host side to the network bridge. This is done with the --network-bridge=bridge-name option. Note that --network-bridge implies --network-veth, i.e. the virtual Ethernet link is created automatically. However, the host side of the link will use the vb- prefix instead of ve-, so the systemd-networkd options for starting the DHCP server and IP masquerading will not be applied.

The bridge management is left to the administrator. For example, the bridge can connect virtual interfaces with a physical interface, or it can connect only virtual interfaces of several containers. See systemd-networkd#Network bridge with DHCP and systemd-networkd#Network bridge with static IP addresses for example configurations using systemd-networkd.

There is also a --network-zone=zone-name option which is similar to --network-bridge but the network bridge is managed automatically by systemd-nspawn and systemd-networkd. The bridge interface named vz-zone-name is automatically created when the first container configured with --network-zone=zone-name is started, and is automatically removed when the last container configured with --network-zone=zone-name exits. Hence, this option makes it easy to place multiple related containers on a common virtual network. Note that vz-* interfaces are managed by systemd-networkd same way as ve-* interfaces using the options from the /usr/lib/systemd/network/80-container-vz.network file.

Use a "macvlan" or "ipvlan" interface

Instead of creating a virtual Ethernet link (whose host side may or may not be added to a bridge), you can create a virtual interface on an existing physical interface (i.e. VLAN interface) and add it to the container. The virtual interface will be bridged with the underlying host interface and thus the container will be exposed to the outside network, which allows it to obtain a distinct IP address via DHCP from the same LAN as the host is connected to.

systemd-nspawn offers 2 options:

  • --network-macvlan=interface – the virtual interface will have a different MAC address than the underlying physical interface and will be named mv-interface.
  • --network-ipvlan=interface – the virtual interface will have the same MAC address as the underlying physical interface and will be named iv-interface.

Both options imply --private-network.

既存のインターフェイスを使用する

ホストシステムに複数の物理ネットワークインターフェイスがある場合は、 --network-interface=interface を使用してコンテナにインターフェイスを割り当てることができます(コンテナが起動している間はホストからは利用できないようにします)。--network-interface--private-network を意味することに注意してください。

ノート: systemd-nspawn コンテナにワイヤレスネットワークインターフェイスを渡すことは現在サポートされていません。[2]

ポートマッピング

プライベートネットワークが有効になっている場合、-p/--port オプションを使用するか、.nspawn ファイルの Port 設定を使用して、ホスト上の個々のポートをコンテナ上のポートにマップできます。これは nat テーブルに iptables ルールを発行することで行いますが、フィルタテーブルの FORWARD チェーンは #Use a virtual Ethernet link で示されているように、手動で設定する必要があります。

例えば、ホスト上のTCPポート8000をコンテナ内のTCPポート80にマッピングするには、次のように入力します:

/etc/systemd/nspawn/container-name.nspawn
[Network]
Port=tcp:8000:80
ノート:
  • systemd-nspawn は、ポートをマッピングする際に loopback インターフェイスを明示的に除外します。したがって、上記の例では、localhost:8000 はホストに接続し、コンテナには接続しません。他のインターフェイスへの接続のみがポートマッピングの対象となります。詳細は、[3] を参照してください。
  • ポートマッピングは IPv4 接続に対してのみ機能します。 [4]

ドメイン名前解決

コンテナ内の ドメイン名前解決systemd-nspawn--resolv-conf オプションか、.nspawn ファイルの ResolvConf= オプションで設定できます。systemd-nspawn(1) § 統合オプション に多くの値が記述されています。

デフォルト値は auto で以下の事を意味します:

  • --private-network が有効になっている場合、/etc/resolv.conf はコンテナ内のまま残ります。
  • あるいは、ホストで systemd-resolved が実行されている場合、そのスタブ resolv.conf ファイルがコンテナにコピーまたはバインドマウントされます。
  • それ以外の場合、/etc/resolv.conf ファイルはホストからコンテナにコピーされるか、バインドマウントされます。

最後の2つのケースでは、コンテナルートが書き込み可能な場合はファイルがコピーされ、読み取り専用の場合はバインドマウントされます。

ヒントとテクニック

非特権コンテナ

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

ノート: この機能には user_namespaces(7) が必要です。詳細については、Linux Containers#Enable support to run unprivileged containers (optional) を参照してください。

これを行う最も簡単な方法は、-U オプションを使用して systemd-nspawn が自動的に未使用の UIDs/GIDs の範囲を選択させることです:

# systemd-nspawn -bUD ~/MyContainer

カーネルがユーザー名前空間をサポートしている場合、-U オプションは --private-users=pick --private-users-chown と同等です。これはコンテナの開始時にコンテナ内のファイルとディレクトリが選択された範囲のプライベート UIDs/GIDs に変更される事を意味します。詳細は、 systemd-nspawn(1) § User Namespacing Options を参照してください。

ノート: コンテナの UID/GID の範囲を手動で指定することもできますが、これが役立つことはほとんどありません。

プライベート UID/GID の範囲を持つコンテナを起動したら、パーミッションエラーを避けるために、そのコンテナを使い続ける必要があります。あるいは、--private-users-chown (または -U) のファイルシステムへの影響を元に戻すには、0で始まるIDの範囲を指定します:

# systemd-nspawn -D ~/MyContainer --private-users=0 --private-users-chown

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 ソケットが削除されないように保護することができます。

xhost の回避

xhost は、Xサーバに対してかなり粗いアクセス権しか与えません。​$XAUTHORITY ファイルを使用すると、より詳細なアクセス制御が可能になります。​残念ながら、コンテナ内の$XAUTHORITY ファイルにアクセスできるようにしただけではうまくいきません。$XAUTHORITY ファイルはホスト固有のものですが、コンテナは別のホストです。​stackoverflowを参考にした以下のトリックを使えば、Xサーバがコンテナ内で実行されているXアプリケーションから、$XAUTHORITY ファイルを受け入れるようにすることができます:

$ XAUTH=/tmp/container_xauth
$ xauth nextract - "$DISPLAY" | sed -e 's/^..../ffff/' | xauth -f "$XAUTH" nmerge -
# systemd-nspawn -D myContainer --bind=/tmp/.X11-unix --bind="$XAUTH" -E DISPLAY="$DISPLAY" -E XAUTHORITY="$XAUTH" --as-pid2 /usr/bin/xeyes

上記の2行目では、接続ファミリーを ""FamilyWild""(値65535) に設定しているため、エントリはすべての表示に一致します。​詳細はXsecurity(7) を参照。

Firefox を起動する

PID 1 として実行するには

 # systemd-nspawn --setenv=DISPLAY=:0 \
              --setenv=XAUTHORITY=~/.Xauthority \
              --bind-ro=$HOME/.Xauthority:/root/.Xauthority \
              --bind=/tmp/.X11-unix \
              -D ~/containers/firefox \
              firefox

あるいは、コンテナを起動して、例えば、systemd-networkd に仮想ネットワークインターフェイスを設定することもできます。

# systemd-nspawn --bind-ro=$HOME/.Xauthority:/root/.Xauthority \
              --bind=/tmp/.X11-unix \
              -D ~/containers/firefox \
              --network-veth -b

コンテナが起動したら、次のようにXorgバイナリを実行します:

# systemd-run -M firefox --setenv=DISPLAY=:0 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 ファイルを使うことで設定できます [5]systemd.nspawn(5) を見てください [6]

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

execv(...) failed: Permission denied

systemd-nspawn -bD /path/to/container によってコンテナを起動 (またはコンテナ内で何かを実行) しようとすると、以下のようなエラーが発生します:

execv(/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init) failed: Permission denied

問題のファイル (例えば /lib/systemd/systemd) のパーミッションが正しくても、コンテナが保存されているファイルシステムを非rootユーザーとしてマウントした結果である可能性があります。例えば、fstabnoauto,user,... というオプションを指定して手動でディスクをマウントした場合、systemd-nspawn は rootが所有するファイルであっても実行は許可しません。

TERM の端末タイプが間違っている (色が壊れている)

machinectl login でコンテナにログインすると、コンテナ内の端末の色とキーストロークが壊れることがあります。これは、TERM 環境変数の端末タイプが正しくないことが原因である可能性があります。環境変数はホストのシェルから継承されませんが、明示的に設定されていない限り、systemd (vt220) で固定されたデフォルトに戻ります。設定するには、コンテナ内の container-getty@.service サービス用のオーバーレイを作成して、machinectl login の login getty を起動し、ログインしているホスト端末と一致する値を TERM に設定してください。

/etc/systemd/system/container-getty@.service.d/term.conf
[Service]
Environment=TERM=xterm-256color

もしくは、machinectl shell を使用してください。端末から TERM 環境変数を適切に継承します。

コンテナ内へのNFS共有のマウント

現時点(2019年6月)では利用できません。

参照