systemd_nspawn
chroot
本題に入る前に、理解しておきたい点がある。
Linuxに於いて、プロセスはルートディレクトリを属性の1つとして持つ。
それは普通、プロセス内で/
から始まる絶対パスの解釈に使われ、通常はシステムのルートディレクトリ(/
)が設定されている。
chroot()
システムコールはルートディレクトリを指定したパスに変更する。
これにより、アクセス可能なファイル等を制限出来る。
systemd-nspawn
systemd-nspawn
はchroot
の強化版と解釈出来る。
chroot
と異なる点として、systemd-nspawn
は
ファイルシステムの階層やプロセスツリー、各種IPC、ホスト名やドメイン等も完全に仮想化、隔離する。
名前空間を隔離し、軽量なコンテナとして扱える。
また、systemd-nspawn
を用いるモチベーションの1つとして、systemd
を用いるLinuxディストリビューションなら何も考えず使えるという点がある。
Dockerとの違い
再現されたディストリビューションのディレクトリツリー内で出来ることは何でもできる。
Dockerはアプリケーション単位でコンテナを構築するのに対し、systemd-nspawn
はコンテナに1つのLinuxシステムを構成する。
コンテナ内で複数のアプリケーションを普通のLinux環境同様に起動できるVM型の仮想化に近い環境を構築できる。
はじめる
筆者が普段使っているUbuntuをホストとし、そこにsystemd-nspawn
を用いてコンテナ環境を作る。
環境
Linux karkador 5.0.0-37-generic #40~18.04.1-Ubuntu SMP Thu Nov 14 12:06:39 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
準備
コンテナ上で必要なファイルを用意するためにdebootstrap
を用いる。
debootstrap
とは、Ubuntuのベースとなっているディストリビューションであるdebian
の最小限のディレクトリツリーを構成する為のツール。今回はこれでUbuntu用のものを用意する。
今回は/var/lib/machines/ubuntu
という名前でコンテナ用のディレクトリを用意し、そこへファイルをインストールする。
# debootstrap --arch=$(dpkg --print-architecture) $(lsb_release -cs) /var/lib/machines/ubuntu http://archive.ubuntu.com/ubuntu
これでコンテナに必要なファイルは作られた
コンテナに入る
# systemd-nspawn -D /path/to/container
これで用意した環境のルートシェルに入れる。とりあえずpasswd
でパスワードの設定だけして抜ける。
コンテナから出るにはCtrl ]]]
で良い。
# systemd-nspawn -b -D /var/lib/machines/ubuntu
コンテナをブートする。即ち、コンテナ内でinit
を起動する。
見慣れたUbuntuのブート画面の後、ログインシェルが立ち上がる。
ここまで来ればもう普段通りの事は大体できる。
抜け方は同じ。
# systemctl start systemd-nspawn@ubuntu
でコンテナが起動される。
自動起動等の操作は他と同様、enable|disable
で行う。
コンテナの操作
systemd-nspawn
コマンドには多数のオプションがある。
例えば最初の-D
は指定したディレクトリをコンテナのファイルシステムのルートとするオプション。
また、systemd-nspawn
以外にコンテナの操作に便利なコマンドがある。
--syscall-filter
コンテナ内で発行されるシステムコールのルールを変えられる。
例えばread
を許可しない時は
--syscall-filter="~read"
で出来る(尚、read
を許可しないと実行も出来ない)
指定するシステムコールに関する詳細はsystemd-analyze syscall-filter
で確認出来る。(グループ単位での指定等)
machinectl
systemctl start systemd-nspawn@
hostname
で起動されているコンテナは、machinectl
コマンドで操作できる。
machinectl list
で起動中のコンテナのリストを表示、
machinectl list-images
で/var/lib/machines
にあるコンテナのイメージのリストを表示する。
また、自動起動の操作もmachinectl enable|disable
で行える。
machinectl
は、コンテナ周りのsystemctl
の操作とsystemd-nspawn
をまとめたようなコマンドで大抵の操作はこれで行える。
コンテナのネットワーク
デフォルトではホストとネットワークを共有している。
またsystemd-networkd
をコンテナ、ホストに設定すると仮想イーサネットリンクやブリッジ、ポートフォワーディングなど、幅広いネットワーク設定が可能になる。
まとめ
Dockerとは異なる点も多く、使い方も全く別のコンテナ技術として面白いものだと思う。
もう少し運用してみてネットワーク等、情報を追加していきたい。