コンテナ型仮想化といえばDockerが現在最もポピュラーなツールとして君臨しています。
昨年末はCoreOSによりRocketのリリースもアナウンスされ、「え、Dockerってマズイの?」みたいな人と「かまへん、かまへん」の人と居たはずです。
Dockerには色々思うところもあり、私の好みとしては開発途中とはいえRocketかな〜と思っています。
そこで、Rocketの中枢となっているsystemd-nspawnに目を付けてみたところ、これが意外に実用的なので現VPS上の仕様を変更してみました。
OSはArchLinuxを選択しました。

※画像は別のコンテナです

systemd-nspawn とは?

まぁね。ArchWikiに書いてあるしね・・・別にいらん世話かとは思いますけど、DockerやRocketみたいなコンテナ型の仮想化機構です。

ArchWikisystemd-nspawn
systemd-nspawn は chroot コマンドに似ていますが、chroot を強化したものです。
systemd-nspawn を使えば軽量な名前空間コンテナでコマンドや OS を実行することができます。ファイルシステム構造だけでなく、プロセスツリーや様々な IPC サブシステム、ホスト…

systemdに付属しているのでArchユーザーならすぐ試せます。
シンプルなツールですので、docker pullのような機能はありません。
man7.orgを見るとdocker pullみたいな機能やコンテナのクローン機能などもあるようなのですが、現在Arch上では使用できてません。
systemdのバージョンは同じみたいなのですが・・・なんでだろ?
これって実装予定が載ってるだけなのかな?

http://man7.org//linux/man-pages/man1/machinectl.1.html#SEE_ALSO

しかし、Dockerからエクスポートしたイメージを動かすこともできます。
企業利用ではDockerコンテナをエクスポートしてsystemd-nspawnで実行してるってとこもあるみたいです。

Arch ユーザーなら systemd-nspawn で仮想化がオススメ

systemd-nspawn自体は他のディストリビューションでも使用できます。
Archなら次のコマンドで実マシン等にインストールした時と同じように簡単にコンテナ作成を始める事が可能です。

mkdir ~/MyContainer  
pacstrap -i -c -d ~/MyContainer base

めっちゃコマンド短いねん。
この時カーネルのインストールは不要なのでSkipします。
ネットワークの仮想化(ほとんどの場合不要)を行わないならdhcpcdもいらないです。
公式Wikiではbaseだけでなくbase-develグループのインストールも推奨されております。

pacstrapコマンドが使用できない場合は、ホスト側に公式リポジトリからarch-install-scriptsをインストールすると良いでしょう。

いざ、 コンテナ 内へ侵入!

試しにこのコンテナに入ってみましょう。
以下のコマンドでマシンにログインできます。

systemd-nspawn -bD ~/MyContainer

最初のログインはrootユーザでパスワードは空。
pacman・yaourtで好きにコンテナを構築していくといいでしょう。
ある程度構築が完了した段階で、コンテナの自動起動を行っておくとさらに捗ります。
ちなみに以下の様にbindオプションを付与してあげればホスト・コンテナ間でディレクトリの共有が可能になります。

systemd-nspawn -bD ~/MyContainer --bind=/usr/share/nginx/html/MyContainer:/usr/share/nginx/html

これはホストの/usr/share/nginx/html/MyContainerをコンテナの/usr/share/nginx/htmlへとバインドしています。
もちろんディレクトリは先に作っておいてください。
コンテナを破棄したいときはこのディレクトリを消せばよいです。
後述する自動起動の設定をした後に削除したいときはユニットファイルとシンボリックリンクの削除もお忘れなく。

コンテナ の自動起動 (ホストのinitに登録)

以下の操作でコンテナを自動起動させることができます。
この時作成したシンボリックリンクの名前=マシン名となりますので、この例だとMyContainerがマシン名ということになります。

サービス名はsystemd-nspawn@MyContainer.serviceです。
ちと長いですね。
最後の.serviceは省略可能です。

ln -s ~/MyContainer /var/lib/machines/MyContainer
systemctl enable systemd-nspawn@MyContainer.service

起動しているコンテナを操作したい場合はmachinectlコマンドを使用します。

machinectl login MyContainer(マシン名)

machinectlのコンソールから抜けたい場合はCtrl押しっぱなしで]を3回入力。

コンテナ の操作一覧

シンボリックリンクが貼られたコンテナは以下のように通常のサービスと同じ扱い方が可能になります。

systemctl enable systemd-nspawn@MyContainer.service  
systemctl disable systemd-nspawn@MyContainer.service  
systemctl start systemd-nspawn@MyContainer.service  
systemctl stop systemd-nspawn@MyContainer.service  
systemctl restart systemd-nspawn@MyContainer.service

bindオプションの追加

あぁ〜どんどん話が逸れてってるけど一応これも書いとくか。
自動起動もさせたい、ディレクトリ共有もさせたいって場合は以下の場所にユニットファイルを置きます。

/etc/systemd/system/systemd-nspawn@MyContainer.service.d/custom.conf  
# /etc/systemd/system/systemd-nspawn@マシン名.service.d/自由な名前.conf

※Systemd version 218よりユニットファイルのオーバーライドがコマンドで行えるようになり楽になりました。
上記の操作はsystemctl edit systemd-nspawn@MyContainerで代用可能です。
このコマンドで作成した場合は最後のファイル名が自動的にoverride.confとなるようです。

中身はこんな感じのたった3行。
ここはきちんとルールに沿って記述してください。

[Service]  
ExecStart=  
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --directory=/var/lib/container/%i --bind=/usr/share/nginx/html/MyContainer:/usr/share/nginx/html

2行目のExecStart=ってのは必ず要ります。
後ろーーーの方にbindオプションを追記してあげればいいです。
終わったら以下を実行。

sudo systemctl daemon-reload  
sudo systemctl restart systemd-nspawn@MyContainer.service

Docker の愚痴

Dockerはコンテナ内でのsystemdに問題があり、systemctlでサービスの起動ができません。
というより本来そんな操作で動かすものじゃない・・・。
なんとか動かす手順もあるんですが、まぁ〜〜〜これが面倒くSay YO ☆
そもそもDockerは1コンテナ=1プロセスにすべきみたいな思想を掲げているんですが、この辺が私に合わない。
進歩の激しいOSS界で1コンテナ=1プロセスなんて無謀というか意味あんのっていうか。
規模の大きいサービスを1つだけ動かすみたいな場合はそれの方がいいでしょうけど、個人、もしくは少人数でそんな細切れコンテナ管理したくはないかな。
Dockerが合わない、わからないって人は大抵この話題ですよね。

どうせチューニングは必要になるんだし、それならコンテナに一時的に入ってイジったほうが手っ取り早くない?
んで色々イジってたら面倒臭くなるんだって。
まぁメールとかDBとかスタンダードなものは分けたい気持ちはわからんでもないですよ。

どちらにしろ1コンテナ=1アプリケーションってぐらいのゆるい感覚の方が楽に運用できるんじゃないでしょうか。

systemd-nspawn はsystemctlコマンドが使用できる

いやもうフッツーに使用できます。
稼働中のコンテナに普通にログインして普通のマシンと同じように使えます。
んで色々イジれます。

systemd-nspawnはこういったコンテナをイジる時のストレスから開放してくれる。
特に説明必要ないでしょうけどこれはデカイ。

Systemd使ってないディストリ使えよって言う人もいるけど、
Archに一度慣れてしまうと他のディストリビューションはちょっと使う気にならない。
ローリングリリースの安定性も抜群だし、Wikiの充実っぷり半端ない!
丁寧な運用ができるならばこんなに使い易いOSなくないですか?
というかAURは卑怯。他のディストリが頑張ってもサクッと旨いとこ取っていくし。
末永く運営していってもらいたいですね。

systemd-nspawn コンテナ のデプロイ

リモートの本番環境などにデプロイする場合は一旦tarballにしてしまうといいでしょう。

tar zcvf MyContainer.tar.gz MyContainer

んでscpやsftp、rsyncなど好きなツールで普通にアップロードします。
そして解凍します。
そして上記の自動起動設定を本番環境でも行います。

ワオ!原始的!・・・ってやってられるかメンドクセェ!

この辺がDockerと比べるとなぁ・・・その内Rocketがいい感じに整えてくれることを願います。
もしくはman7.orgに書いてある通りの動作ができるならもっとマシな方法があるんでしょうけども。
なお、転送先でもこんな感じに特権レベルで解凍を行えばパーミッションを保持してくれます。

sudo tar zxvf MyContainer.tar.gz 

ローカルとリモートでUID・GIDを統一しておくとちょっとだけ楽ですね。

あれ何か最初書こうと思った事と違う!

いや最初はsystemd-nspawnでVPS構成しなおしたって話を書こうとしたんですよ。
なぜだ・・・なぜ使い方になってしまったんだ・・・
まぁいいや、ちょっと長くなったので一旦区切ります。

コンテナを利用して面白い試みもしていますので早めに紹介したいと思います。

2015/02/08追記
↓記事追加しました

2015-02-08 22:44systemd-nspawnを活用してVPSの構成を根底から見直した前回の記事にも書きましたがsystemd-nspawnを使ってサーバー内を思いっきりやり変えちゃいました。「時間も増えたし、いい機会かな」とコンテナをコツコツ準備してOSインストー