Plamoテンプレートを使ったコンテナの作成
前回 、Plamoテンプレート(lxc-plamo
)を題材に、テンプレートの中身を詳しく紹介しました。テンプレートは、lxc-create
コマンドを使ってコンテナを作成するときに使われます。以下のように実行するのでしたね。
~$ sudo lxc-create -n ct01 -t plamo
これで、ct01
という名前のPlamoコンテナ環境が作成されました。このコンテナは、root権限で利用することになります。では次に、root権限ではなく、一般ユーザ権限で利用するコンテナを作成しましょう。
コンテナの作成に先立ち、あるユーザに紐づいたUID/GIDの範囲の指定を行うため、root権限でユーザに対する/etc/{subuid,subgid}
の設定が必要です。ここでは、100000から65536個のUID/GIDをtaro
というユーザに割り当てます。
~$ sudo usermod -v 100000-165535 -w 100000-165535 taro
~$ cat /etc/subuid
taro:100000:65536
~$ cat /etc/subgid
taro:100000:65536
また、lxc-create
コマンド実行時に読み込まれるtaro
ユーザ用のデフォルトファイル(~/.config/lxc/default.conf
)を用意します。後で説明するネットワークの設定と併せて、以下のように設定します。
~$ cat ~/.config/lxc/default.conf
lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536
lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
これらの非特権コンテナに関する詳細は、この連載の後の回で説明する予定です。さて、準備ができたので、以下のように実行してみましょう。
~$ lxc-create -n ct01 -t plamo
This template can't be used for unprivileged containers.
You may want to try the "download" template instead.
lxc_container: container creation template for ct01 failed
lxc_container: Error creating container ct01
コンテナの作成に失敗してしまいました。そうです。一般ユーザ権限では、通常のテンプレートを使ったコンテナ環境の作成が難しいので、非特権コンテナの作成が制限されています。そこで、ダウンロードテンプレートを使って実行することになります。
~$ lxc-create -n ct01 -t download -- -d plamo -r 5.x -a amd64
アーキテクチャにamd64
と指定するあたりは、( Plamo Linuxでは、そのような名前で呼ばれていないので)少々気持ち悪いと感じるかも知れませんが、ここでは気にしないことにします。
LXCのダウンロード用サーバから、作成済みコンテナイメージをダウンロードして、コンテナ環境が作成されました。コンテナ環境を作成した一般ユーザ権限で(正確には、lxc.id_map
で設定したユーザ名前空間内で)コンテナを利用することができます。
一般ユーザ権限で作成したコンテナ環境
ダウンロードした作成済みコンテナイメージは、基本的にPlamoテンプレート(lxc-plamo
)などのテンプレートを実行して、作成したコンテナのルートファイルシステムをtar.xzで固めているだけのものです。それでは、root権限で通常のテンプレートを使って作成したコンテナ環境と、一般ユーザ権限でダウンロードテンプレートを使って作成したコンテナ環境とでは、どのような違いがあるのでしょうか。
まず、作成したコンテナのルートファイルシステム上のファイル/ディレクトリのUID/GIDが、通常のコンテナ環境と異なります。
lxc-create
コマンドを実行すると、内部でテンプレートが呼び出されます。このとき、一般ユーザ権限で実行した場合は、lxc-usernsexec
コマンドの引数として、テンプレートが呼び出されます。このコマンドを実行すると、lxc.id_map
で設定したユーザ名前空間内で、root
としてタスクが実行されます。その結果、コンテナ内のファイル/ディレクトリは、lxc.id_map
で設定したユーザ名前空間内にマッピングしたUID/GIDで、コンテナのルートファイルシステム上に展開されます。
なお、lxc.id_map
で設定したユーザ名前空間において、キャラクタデバイスやブロックデバイスを作成するmknod
は実行できません。そのため、作成済みコンテナイメージを展開する際、mknod
の実行をともなう処理はスキップして展開されます。代わりに、ユーザ名前空間向けに追加した個別の設定(/usr/share/lxc/config/plamo.userns.conf
)でバインドマウントを行うことで、スキップしたデバイスを見せています。
このように、一般ユーザ権限でダウンロードテンプレートを使って作成したコンテナ環境では、root権限で通常のテンプレートを使って作成したコンテナ環境とほぼ同等の環境になるように、いろいろ工夫されていることがおわかりいただけたかと思います。
Plamoコンテナイメージのバリアント
現在、LXCのダウンロード用サーバには、Plamo Linuxの作成済みコンテナイメージのバリアントとして、default
とmini
が用意されています。先に示した例では、デフォルトのdefault
バリアントのコンテナイメージが使われます。一般ユーザ権限で、mini
バリアントのコンテナ環境を作成する場合は、以下のように実行します。
~$ lxc-create -n ct01 -t download -- -d plamo -r 5.x -a amd64 --variant=mini
また、Plamo Linuxの個別ミラーサーバでは、上記以外にlarge
バリアントとfull
バリアントのコンテナイメージも用意されています。以下のように実行することで、Plamo Linuxの個別ミラーサーバから作成済みコンテナイメージをダウンロードできます。
~$ lxc-create -n ct01 -t download -- -d plamo -r 5.x -a amd64 --variant=large \
> --server=repository.plamolinux.org --keyid=0xC0B578C84772EC0D
各バリアントのパッケージ構成は以下のようになっています。
バリアント
作成済みコンテナイメージのパッケージ構成
サイズ
default
00_base
と01_minimum
カテゴリのパッケージを収録し、若干調整した構成
約240MB
mini
00_base
~03_xclassics
カテゴリのパッケージを収録し、若干調整した構成
約475MB
large
00_base
~05_ext
カテゴリのパッケージを収録した構成
約1.2GB
full
00_base
~10_lof
すべてのカテゴリとcontrib
の一部のカテゴリのパッケージを収録した構成
約3.2GB
large
バリアントやfull
バリアントはサイズが大きく、ダウンロードするのに時間が掛かりますが、興味があれば試してみてください。
コンテナの初期パスワード
前回 の「コンテナ内の設定ファイルの調整」の項で説明したように、lxc-create
コマンドを使ってPlamoコンテナを作成すると、root
のパスワードが暫定的に"root
"に設定されます。この仕様は、Plamoテンプレートに限ったことではなく、筆者らがPlamoテンプレートをマージしてもらった当時、パスワードが不要なテンプレートを除いて、Ubuntuテンプレートを始めとするすべてのテンプレートが、そのようになっていました。
LXCの開発当初は、利用者数が比較的少なかったこともあり、この仕様に異論を唱える開発者は、当時あまりいなかったように思います。しかし、このような牧歌的な状況が長く続くわけでもなく、この連載が始まる少し前のUbuntu 14.04 LTSがリリースされた頃から、各ディストリビューションでのLXCの正式採用が相次ぎ、利用者数が急速に増えていきました。同時に、コンテナの初期パスワードに対する指摘が、定期的にlxc-develメーリングリストに投稿されるようになり、そして今年(2014年)8月、これについて問題視しているバグレポートが2件、Debian Bug report とRed Hat Bugzilla が発行されるに至りました。
この問題を受けて、Michael H. Warfieldさんが解決に向けて精力的に活動されています。彼は、テンプレート内でパスワードを設定する際、ランダム文字列による設定や、パスワード入力による設定、パスワードを期限切れにしたり、アカウントを無効化するなど、さまざまな状況に対応できる共通関数を作成し、まずFedoraテンプレートとCentOSテンプレートに適用し、順次他のテンプレートへの適用を目指しています。
ただし、この方法はroot権限で通常のテンプレートを使って作成したコンテナ環境において効果を発揮するものであり、一般ユーザ権限でダウンロードテンプレートを使って作成したコンテナ環境においては効果的ではありません。はい、パスワード設定済みのコンテナイメージをダウンロードするので、毎回同じパスワードになってしまいますね。実際のところ、Michael H. Warfieldさんは、非特権コンテナは自分の領域ではないと仰っていました。
筆者は、root権限で通常のテンプレートを使って作成したコンテナ環境でも、一般ユーザ権限でダウンロードテンプレートを使って作成したコンテナ環境でも、同等の効果を発揮するように、Michael H. Warfieldさんが適用を目指している初期パスワードの設定を、テンプレート内ではなく、lxc-create
コマンドからテンプレートが呼び出されて、戻ってきた直後に行うように提案しました。しかしながら、Michael H. Warfieldさんの提案と競合しているため、最終的にどうなるか、まだ着地点は見えていません。
一方、LXCメンテナであり、ダウンロードテンプレートの生みの親でもあるStéphane Graberさんが現在考えていることは、大きく以下の2点です。
作成済みコンテナイメージのパスワードを一律無効化にする
ダウンロードテンプレートをメインのLXCソースツリーで管理しない
パスワードの一律無効化は、LXCのダウンロード用サーバにおいて、最近実施されました。この変更によって、一部のディストリビューションのテンプレートを使って作成したコンテナで、初回起動時にパスワード設定のプロンプトを出して止まってしまうなど、意図しない動きをするケースもあるようなので、テンプレート側で何らかの修正が必要でしょう。もう一つ、ダウンロードテンプレートの扱いについては、lxc-1.2での実装を目標として、作成済みコンテナイメージを作っている人たちのブランチに、ダウンロードテンプレートを管理してもらうことを考えているようです。その際、メインのLXCソースツリーで用意しているテンプレートだけでなく、他のいろいろな作りのテンプレートを考慮して、それらをカバーできるように、ダウンロードテンプレートを整備しておく必要があるでしょう。
メインのLXCソースツリーで、ダウンロードテンプレートを管理しなくなると、今までのように、LXCツール単体で非特権コンテナを作ることができなくなります。現実的に可能かどうかわかりませんが、将来的には通常のテンプレートだけで、非特権コンテナを作れるようになると嬉しいのですが。さらに、Plamoテンプレートのように、他のすべてのテンプレートが、任意のディストリビューション上で作成できるようになると素晴らしいですね。
いずれにしても、将来の方向性はこれから議論を重ねることによって定まってくるでしょうから、これからの動向を注意深く見守っていきたいと思います。
複数のユーザによるコンテナの作成とネットワーク構成
ここでは、複数のユーザがコンテナを作成することを考えてみます。
Plamo Linuxでは、lxcパッケージをインストールすると、cgroupサブシステムごとにcgroupファイルシステムをマウントするcgroup-mount
というinitスクリプトと、LXC用ネットワークブリッジを作成するlxc-net
というinitスクリプトは、デフォルトで起動しないようになっています。root権限で、以下の実行して有効にしてください。
~$ sudo chmod +x /etc/rc.d/init.d/cgroups-mount
~$ sudo chmod +x /etc/rc.d/init.d/lxc-net
なお、すでにlibcgroup
パッケージをインストールしていて、cgconfig
を起動させている場合は、cgroup-mount
を起動させる必要はありません。
また、ユーザが書き込めるcgroupを作成するために、以下のinitスクリプトを追加しておきます。
~$ cat /etc/rc.d/init.d/cgroups-mount-user
#!/bin/sh
# mount cgroup filesystems per subsystem for user name space
USERNS="taro hanako"
start() {
echo 1 > /sys/fs/cgroup/memory/memory.use_hierarchy
for c in /sys/fs/cgroup/* ; do
echo 1 > $c/cgroup.clone_children
for u in $USERNS ; do
mkdir -p $c/$u
chown -R $u $c/$u
if [ ${c##*/} == cpuset ] ; then
echo 0 > $c/$u/cpuset.cpus
echo 0 > $c/$u/cpuset.mems
fi
done
done
}
stop() {
:
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
;;
esac
exit 0
新たなユーザでのコンテナの作成に先立ち、root権限でユーザに対する/etc/{subuid,subgid}
の設定を行ってください。200000から65536個のUID/GIDをhanako
というユーザに割り当てます。
~$ sudo usermod -v 200000-265535 -w 200000-265535 hanako
~$ cat /etc/subuid
taro:100000:65536
hanako:200000:65536
~$ cat /etc/subgid
taro:100000:65536
hanako:200000:65536
また、lxc-create
コマンド実行時に読み込まれるhanako
ユーザ用のデフォルトファイル(~/.config/lxc/default.conf
)を用意します。上記で設定した/etc/{subuid,subgid}
の設定と合うように設定してください。
~$ cat ~/.config/lxc/default.conf
lxc.id_map = u 0 200000 65536
lxc.id_map = g 0 200000 65536
lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
hanako
ユーザのコンテナを作成します。
~$ lxc-create -n ct01 -t download -- -d plamo -r 5.x -a amd64
次に、LXCでユーザが使えるネットワークインタフェースの数を設定するため、root権限で/etc/lxc/lxc-usernet
を編集します。各ユーザがveth
タイプのインタフェースをlxcbr0
にアタッチする形で、それぞれ2個利用できるようにします。
~$ cat /etc/lxc/lxc-usernet
taro veth lxcbr0 2
hanako veth lxcbr0 2
これで、コンテナを起動する準備ができました。コンテナを起動するときは、現在実行中のシェルのPIDを、自身のcgroupのタスクに登録します。
~$ for c in /sys/fs/cgroup/* ; do echo $$ > $c/$USER/tasks ; done
いよいよコンテナを起動します。Plamo Linuxのデフォルト設定では、セキュリティ確保のため、inetd経由で起動するサービスについて、外部からのリクエストはすべて拒否されるようになっているので、コンテナ内の/etc/hosts.allow
を適切に設定するのを忘れないでください。
iptablesのNAT(IPマスカレード)機能を利用する方法
Plamo LinuxのLXCパッケージで、デフォルトで用意されているネットワーク構成です。上記の手順に従ってコンテナを作成すれば、ネットワークの設定はすでに出来上がっています。
図1 NAT機能を介して物理NICに接続
ホストOSの物理NICが有線/無線にかかわらず、ネットワークを利用することができます。
外部と通信する際は、図1 のようにNAT機能を介して物理NICに接続します。複数のコンテナがホストOSのIPアドレスを共有するため、コンテナから外部のサーバに接続することはできますが、外部のサーバからコンテナに接続することはできません。
物理NIC(有線)を仮想ブリッジに接続する方法
外部のサーバからコンテナに接続する必要がある場合は、図2 のようにホストOSの物理NIC(有線)に、仮想ブリッジを接続する構成にします。
図2 物理NIC(有線)を仮想ブリッジに接続
ホストOSでのネットワークの設定は、あらかじめ以下のように設定しておきます。br0
という仮想ブリッジを作成し、これに対してホストOS用のIPアドレスを与えています。ネットワーク設定用rcスクリプト(/etc/rc.d/rc.inet1.tradnet
)の適切な場所に入れておくと良いでしょう。
~$ sudo ip link set dev eth0 up promisc on
~$ sudo brctl addbr br0
~$ sudo brctl addif br0 eth0
~$ sudo dhclient br0
各ユーザのLXCのネットワーク設定を以下のように変更します。
~$ cat ~/.config/lxc/default.conf | grep network
lxc.network.type = veth
lxc.network.link = br0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:xx:xx:xx
lxc.network.hwaddr
の"xx:xx:xx
"の部分は、lxc-create
コマンドを実行するとランダムな値に変換して、コンテナの設定ファイル(~/.local/share/lxc/<コンテナ名>/config
)にコピーされます。なお、DHCPサーバにMACアドレスを登録する必要がある場合は、このMACアドレスを登録してください。同一セグメント内で重ならない好きな値に書き換えて、登録することもできます。
LXCでは、MACアドレスのベンダコードを"00:16:3e
"として使うように、慣習的に決まっています。このベンダコードは、Xenで専用OUIとしてIEEEでリザーブされています 。LXCでは、Xenの専用OUIを間借りしている形になっていますが、今のところは特に問題ないでしょう。ちなみに、QEMU/KVMでは、MACアドレスのベンダコードを"54:52:00
"として使うように、慣習的に決まっているようです。こちらは、専用OUIとしてまだ登録されていません。
この接続方法は、外部のサーバからコンテナに接続することができるので、コンテナ内にサーバを設置する場合などに有効です。ただし、ホストOSの物理NICが無線の場合には使えないことに注意してください。
物理NIC(無線)を仮想ブリッジに接続する方法
仮想ブリッジは、ホストOS上に仮想的なレイヤ2スイッチを構成して、レイヤ2のフレーム交換を行う機能です。しかし、無線LANでつながっている場合、レイヤ2レベルの転送をサポートしていないため、簡単にブリッジ接続を構成することができません。
そこで、tunctl
(uml_utilities
パッケージ) 、parprouted
(parprouted
パッケージ) 、bcrelay
(pptpd
パッケージ)を使って、図3 のようにホストOSの物理NIC(無線)に、仮想ブリッジを接続する構成にします。
図3 物理NIC(無線)を仮想ブリッジに接続
ホストOSでのネットワークの設定は、あらかじめ以下のように設定しておきます。tap0
というtapデバイスを作成、仮想ブリッジbr0
とtap0
をブリッジし、br0
にDHCPレンジ外のスタティックIPアドレスを付与して起動します。そして、parprouted
でwlan0
に飛んできたARPリクエストをbr0
にも転送、bcrelay
でブロードキャスト(DHCP情報)をリレーするようにしています(parprouted
は、マルチキャストトラフィックに対応していないためです) 。ネットワーク設定用rcスクリプト(/etc/rc.d/rc.inet1.tradnet
)の適切な場所に入れておくと良いでしょう。
~$ sudo ip link set dev wlan0 up
~$ sudo brctl addbr br0
~$ sudo tunctl -t tap0
~$ sudo brctl addif br0 tap0
~$ sudo ip addr add 192.168.1.100/24 dev br0
~$ sudo ip link set dev br0 up
~$ sudo parprouted wlan0 br0
~$ sudo bcrelay -d -i br0 -o wlan0
~$ sudo wpa_supplicant -B -c /etc/wpa_supplicant.conf -i wlan0
~$ sudo dhclient wlan0
各ユーザのLXCのネットワーク設定は、物理NIC(有線)を仮想ブリッジに接続するときと同じです。
まとめ
今回は、lxc-create
コマンドを使ってコンテナを作成するときの、root権限と一般ユーザ権限での動作の違いや、複数ユーザによるコンテナの作成、状況に応じたネットワークのいろいろな構成などを紹介しました。これらは、特にPlamo Linuxに依存した内容ではありませんので、他のディストリビューション上でも応用できると思います。ぜひお試しください。
次回は、コンテナ内でサウンドを取り扱う方法について紹介します。お楽しみに。