+++ date = "2022-12-05" tags = ["arch","docker"] title = "archlinuxでsystemd-nspawnを使いcontinerを立ててみた" slug = "archlinux-systemd-nspaw-continer" +++ botに複数の仮想環境を構築する必要があったので、今回はsystemd-nspawnを採用してみることにしました。 結論から言うと、systemd-nspawnはとっつきにくいですが、一度使えるようになっておくと、本格的に便利だと感じました。 ただ、とっつきにくさがすごい。コマンドも複数あって混乱を招くと思われます。 archwikiの最初の説明が以下です。 ```sh $ mkdir -p ~/arch $ sudo pacstrap -c ~/arch base # -D : chroot $ sudo systemd-nspawn -D ~/arch $ passwd $ logout # -b : コンテナ起動 $ sudo systemd-nspawn -b -D ~/arch # -n : ネットワーク $ sudo systemd-nspawn -b -D ~/arch -n ``` これは色んな意味で正しいのですが、私の環境では動作しません。 設定したpasswordでloginできない。なお、設定していないと空なのでenterでloginできるはず(たぶん)。ttyのsecurityが働いているからです。 ```sh Arch Linux 6.0.11-arch1-1 (pts/1) arch login: arch-nspawn login: root Login incorrect ``` ここでホストから`~/arch/etc/securetty`を編集し、ここでは`pts/1`でloginしようとしているため、これを追記します。`pts/0`なら`pts/0`ですし、その他ならそのttyを記述してください。 ```sh $ sudo vim ~/arch/etc/securetty ``` さて、loginできたとしましょう。 一旦、`poweroff`して仮想環境(continer)を落とします。 ```sh $ poweroff $ machinectl list ``` 次に、本来のsystemd-nspawnの一般的な使い方を説明します。 ```sh $ machinectl --help $ sudo mv ~/arch /var/lib/machines/ $ sudo machinectl list-images $ sudo machinectl start arch $ sudo machinectl login arch # vmの削除 $ sudo machinectl remove arch # vmにshell # loginはおすすめしません。Ctrl+Dで抜けられません。shellの場合はexitできます。continerはupしたままになります。 $ sudo machinectl shell arch # vmをdown $ sudo machinectl poweroff arch $ sudo machinectl terminate arch ``` `/var/lib/machines`においたcontiner image(dir)をmachinectlで呼び出します。 これは、`systemctl`の`systemd-nspawn@arch`でも同じようなことができます。 ```sh # archというcontinerをstart $ sudo systemctl start systemd-nspawn@arch $ sudo machinectl start arch # archというccontinerをPC起動時に立ち上げる $ sudo systemctl enable systemd-nspawn@arch $ sudo machinectl enable arch $ sudo systemctl daemon-reload ``` machinectl, systemd-nspawn, systemctlのどれを使ってもいいですが、個人的にはmachinectlをおすすめします。しかし、それぞれが使い方に微妙な違いを含んでいます。 machinectlは主にvm操作で、pacstrapはarchの構築、systemctlはホスト環境の構築、systemd-nspawnはdir(chroot)操作です。 正直、わかりづらい。 dockerのほうが遥かにわかりやすいですね。 ですが、archer(archlinuxを普段使いしる人)にとっては、慣れると扱いやすいし、便利そうだと感じています。 ```sh # イメージのダウンロード $ sudo machinectl pull-tar --verify=no http://localhost:8000/arch.tar.gz arch # アーカイブ $ sudo machinectl export-tar --format=[gz, bzip2, xz] [コンテナ名] [ファイル名] # xz でマルチスレッド圧縮をする例 (一番お勧め!) $ maxz() { machinectl export-tar $1 $1.tar && nice -n 20 xz -z -f -T $(nproc) -vv $1.tar; } $ maxz gbase # インポート $ sudo machinectl import-tar [ファイル名] [コンテナ名] # docker imgをインポート $ sudo docker export $(docker create debian:latest) | machinectl import-tar - debian # hostのnetworkを使う, VirtualEthernetもconfiguredにすると有効 $ networkctl IDX LINK TYPE OPERATIONAL SETUP 1 lo loopback carrier unmanaged 2 eth0 ether routable configured 3 ve-arch ether no-carrier configuring $ sudo vim /etc/systemd/nspawn/arch.nspawn ``` ```sh:/etc/systemd/nspawn/arch.nspawn [Network] VirtualEthernet=no ``` ```sh # ssh接続 $ ssh-keygen -f ~/.ssh/test $ sudo cat ~/.ssh/test.pub >> /var/lib/machines/arch/root/.ssh/authorized_keys $ sudo machinectl shell arch $ pacman -S openssh $ vim /etc/ssh/sshd_config $ systemctl enable sshd $ systemctl start ssh $ exit $ ssh root@localhost -p xxx -i ~/.ssh/test ``` ### bot運用をどうするか ![](https://raw.githubusercontent.com/syui/img/master/other/mastodon_bot_20221203_0005.png) 例えば、botに一つの仮想環境をあてがい、その中で使える機能を限定して、1日に1回、もしくは呼び出すごとにresetされるように運用するのがいいかも。 その場合、cronとcloneを駆使してやるとよさそう。 ```sh $ sudo machinectl clone arch backup $ sudo machinectl poweroff arch $ sudo machinectl remove arch $ sudo machinectl clone backup arch ``` ### ref https://wiki.archlinux.org/title/systemd-nspawn https://blog.usaturn.net/contents/2016/manage_spawn_container/ https://blog.n-z.jp/blog/2022-09-27-systemd-nspawn.html