systemd-nspawnことはじめ
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とは異なる点も多く、使い方も全く別のコンテナ技術として面白いものだと思う。
 
	
	
Comments