皆さんいかがお過ごしでしょうか。
記録的な雨が降った地域もあるようですね。
私の地方も数年前は水害がひどく、知り合いに家が流された方とかが居たので、あまり他人ごとではありません。
今年も無事に過ごせると良いのですが・・・。
さて、昨日の記事でsystemdのinitシステムtimerについて書きました。

2015-06-17 16:38まとめて面倒見てくれる勢いのsystemd(initシステムとtimer)ほとんどの主要ディストリビューションで採用されているinitシステムsystemdですが、結構ゴチャゴチャしてきたのでちょっとまとめたいと思います。コンテナ型の隔離技術や、ネットワこの記事を読む

今回は予告通りsystemd-nspawnsystemd-networkdについて取り上げたいと思います。

コンテナ・隔離技術としてのsystemd(systemd-nspawn)

このブログで何度も取り上げたのですが、Dockerのようなコンテナ型仮想化・隔離技術と呼ばれるものです。
特定のディレクトリ配下にもう一つ別のLinuxツリーを作成し、あたかも別のマシンを触っているかのように振る舞います。
隔離はcgroups管理の延長線上とも言えなくのないのでぶっ飛んだ話ですがsystemdの分野とも言えるのです。
現在はまだ管理ツールに乏しいのが悩みの種ですが、

  • データが標準で永続化されるのでチューニングしやすい
  • 稼働中のコンテナにログインしてsystemctlでサービスを自由に立ち上げられる
  • 仮想ブリッジを使うも使わないも自由
  • フォワーディングなしでホストのポートを使用できる(これも任意)

という点で私はこちらを使用しています。

当ブログのVPS上にも、

  • phpfpm (hhvmから戻した)
  • mariadb
  • nginx (ホスト80番_ルーティング専用)
  • nginx (www.geeks-dev.com)
  • nginx (demo.geeks-dev.com)
  • nginx (coqoo.net)

といったコンテナが稼働し、互いに連携しています。

最近微妙にsystemd-nspawnの使い方が変わってしまいました。
バージョンによるものなのかどうなのかはわかりませんが従来のように、

systemctl enable systemd-nspawn@MyContainer

machinectl enable MyContainer

では自動起動してくれないようになりました。
もしかすると次項で紹介するsystemd-networkdsystemd-resolvedの影響があったのは把握しているのですが、それ以外にも以前と変わっている部分が在るようです。

もう一度きちんと、確実に動く手順をまとめたいと思います。

1. コンテナを作る

まずはコンテナにするディレクトリを作成します。

mkdir ~/MyContainer

次にディレクトリにシステムをインストールします。
ここはディストリビューションごとに異なります。
いずれもrootで行います。

Fedora

dnf -y --releasever=21 --nogpg --installroot=~/MyContainer --disablerepo='*' --enablerepo=fedora install systemd passwd dnf fedora-release vim-minimal

Debian

debootstrap --arch=amd64 unstable ~/MyContainer/

ArchLinux

pacstrap -c -d ~/MyContainer/ base

2. コンテナ管理ディレクトリにリンクを貼る

このディレクトリの場所もいつの間にか変わっています。
/var/lib/container/から/var/lib/machines/になっています。

ln -s ~/MyContainer /var/lib/machines/MyContainer

3. systemd-machinedを自動起動する

従来と大きく違うのはコイツです。
多分前から居たんですけど以前まではコイツ無しで動いていました。
ちなみにこのsystemd-machinedというのは単純にsystemctl enableを使用しても動きませんでした。
なのでこんな事します。

ln -s /usr/lib/systemd/system/machines.target /etc/systemd/system/multi-user.target.wants/machines.target

4. 作ったコンテナの自動起動を設定しようとする

systemctl enable systemd-nspawn@MyContainer

設定『しようとする』と言っているのはこのままでは自動起動しないからです。
ここで自動起動にならない原因は恐らくsystemd-resolvedです。
systemd-resolvedについては次項で紹介しますが、端的にはresolv.confsystemd-networkdの設定に基づいて生成してくれます。
生成される箇所は/run/systemd/resolve/resolv.confですので、/etc/resolv.confへシンボリックリンクを貼って使用します。
んでsystemd-nspawnは起動時にホストの/etc/resolv.confをコピーしようとするのですがその時に失敗するようです。
systemd-networkdsystemd-resolvedを使用していないのであれば、ここまででちゃんと自動起動すると思います。
もし起動しなければ次の手順を行って下さい。

5. ユニットを書き換える

systemctl edit systemd-nspawn@MyContainer

中身は以下

[Unit]
After=network.target

[Service]
ExecStart=
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --directory=/var/lib/machines/%I --bind-ro=/run/systemd/resolve:/run/systemd/resolve

Afterパラメータはnetwork-online.targetの方が良いんですけど、とりあえず上記で問題無さそうです。

もしnetwork-online.targetにしたい方は以下の手順を行って下さい。

systemctl enable systemd-networkd-wait-online
systemctl edit systemd-nspawn@MyContainer

中身を変更

[Unit]
After=network-online.target

[Service]
ExecStart=
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --directory=/var/lib/machines/%I --bind-ro=/run/systemd/resolve:/run/systemd/resolve

[Install]
WantedBy=network-online.target

6. 今度こそ自動起動する

ユニットを書き換えたのでdaemon-reloadしましょう。

systemctl daemon-reload

これで完了です。
マシンを再起動してみて確認して下さい。

その他の使い方については手前味噌ですが、以下の記事をご覧下さい。

2015-02-07 22:56Dockerより柔軟なコンテナ型仮想化 systemd-nspawn を使ってみたコンテナ型仮想化といえばDockerが現在最もポピュラーなツールとして君臨しています。昨年末はCoreOSによりRocketのリリースもアナウンスされ、「え、Dockerってマズイこの記事を読む

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

2015-02-11 00:01systemd-nspawn コンテナ間の socket を共有させてみた話毎度Qiitaに書けよと言われんばかりの記事を書いてる筆者です。いやだって・・・Qiitaって報酬ないでしょ・・?見やすいけどさ。で本題。折角仮想化してんのにTCP通信なんて勿体無この記事を読む

2015-02-11 21:46コンテナ内の MariaDB or MySQL をホスト側からダンプする「どうせやるならとことんやる」が座右の銘です。さて此度もsystemd-nspawnの仮想化ネタ。と言っても○○をコンテナに〜とかではなく、今回はホスト側からコンテナ内のMariaこの記事を読む

2015-04-24 17:01systemd-nspawnで使うmachinectlが素晴らしい事になってた皆さんお久しぶりです。ここ最近開業の手続きやら印鑑の準備やら口座の準備やら振込先の変更やら会計ソフトの準備やらで非常にゴタゴタしておりました。やっと落ち着いてきたので、ちょっと旬をこの記事を読む

ネットワーク設定ツールとしてのsystem(systemd-networkd)

systemdで出来る事を把握しない内はなんでもかんでも手を伸ばそうとしているように見えるかも知れません。
あくまでsystemdはLinuxカーネルとアプリケーション間の接着剤であろうとしています。
ですからネットワークの設定などもsystemdの分野と言えます。
一度OSS脳から離れて冷静に考えてみると、これらに複数の選択肢など存在する必要はなく、きちんと動作する物が一つあれば良いわけです。
かといってsystemdはその他のツールを排除しようとしてるわけでもありません。
使うか使わないか自由に選択できるのです。

ただ、systemdのソフトウェア一式はそれぞれのコンポーネント上で設定ファイルの書式がiniファイル形式になっているので、無用なーザーの混乱を防いでくれます。
systemd-networkdもユニットのようにiniファイル形式で記述していけます。

systemd-networkdではデバイスにネットワーク設定を適用したり仮想ネットワークデバイスを作成する事ができます。

では使い方を見て行きましょう。
準備としては以下の2つのサービス起動が必要になります。

systemctl enable {systemd-networkd.service,systemd-resolved.service}
systemctl start {systemd-networkd.service,systemd-resolved.service}

ついで以下もやっておくと後々便利でしょう。

systemctl enable systemd-networkd-wait-online

NetworkManager等を利用している場合は切って下さい。
次にresolv.confをsystemd-resolvedが吐き出す物にリンクさせます。

mv /etc/resolv.conf /etc/resolv.conf.bak #念のため退避
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf

設定ファイルは/etc/systemd/networkに設置していきます。
これも種類があるのですが、実際のネットワークに接続するだけなら.networkファイルを使えば問題ありません。
管理しやすいようにデバイス名.networkというファイルを作っていけばいいでしょう。
enp3s0というデバイスでDHCP接続を行いたい場合は以下のようにします。

/etc/systemd/networkd/enp3s0.networkを作成。

[Match]
Name=enp3s0

[Network]
DHCP=ipv4

固定IPを使いたい場合は以下のようになります。

[Match]
Name=enp3s0

[Network]
DNS=192.168.1.1

[Address]
Address=192.168.1.2/24

[Route]
Gateway=192.168.1.1

ここでDNSの設定が出てきましたがDNSは/etc/systemd/resolved.confでも設定できます。
その場合は、以下のように記述します。

[Resolve]
DNS=192.168.1.1

恐らくこちらがグローバルな設定なのかと思いますが探してみても2つの方法による違いが見当たりませんでした。

systemd-networkdで仮想ネットワークデバイスを作る

systemd-networkdはVLANやブリッジなどの仮想ネットワークデバイスも作成できます。
私は全く使いませんがやり方次第ではDockerライクなネットワーク環境を構築することが可能です。

以下は単純なブリッジの例です。
まずホスト、コンテナの両方で以下を行っておいて下さい。

ln -sf /dev/null /etc/systemd/network/80-container-host0.network

/etc/systemd/network/br0.netdevなんかを作成して中身を書きます。

[NetDev]
Name=br0
Kind=bridge
[Match]
Name=enp3s0

[Network]
Bridge=br0

次にブリッジのプロファイルを作ります。

/etc/systemd/network/br0.networkを作成して、中身を以下のように。

[Match]
Name=br0

[Network]
DNS=192.168.1.1
Address=192.168.1.100/24
Gateway=192.168.1.1

コンテナからブリッジに接続するには、まずsystemd-nspawnコンテナのユニットに--network-bridge=br0を書き加えます。
前項の例だとこうなりますね。

[Unit]
After=network.target

[Service]
ExecStart=
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-bridge=br0 --directory=/var/lib/machines/%I --bind-ro=/run/systemd/resolve:/run/systemd/resolve

それからコンテナ内に/etc/systemd/network/host0.networkを作成して、

[Match]
Name=host0

[Network]
DNS=192.168.1.1
Address=192.168.1.101/24
Gateway=192.168.1.1

とします。

完了したらコンテナ側でも

systemctl start systemd-networkd
systemctl enable systemd-networkd

を行っておいて下さい。

まとめ

ぶっちゃけsystemd-nspawnは使いすぎて何か面白味が無いです。
systemd-networkdなんかは一回設定するとほとんど触る事無いし。
ユニット関連の方が何か面白い気がするのは私だけ?