前回は、
コンテナの仕組み
コンテナをまだ使ったことがない方でも、
![図1 VMとコンテナの仕組み(1)仮想マシン 図1 VMとコンテナの仕組み(1)仮想マシン](/assets/images/admin/serial/01/linux_containers/0002/thumb/TH800_001.jpg)
VMでは図1のように、
![図2 VMとコンテナの仕組み(2)コンテナ(OSレベル仮想化) 図2 VMとコンテナの仕組み(2)コンテナ(OSレベル仮想化)](/assets/images/admin/serial/01/linux_containers/0002/thumb/TH800_002.jpg)
一方コンテナは、
この隔離された空間を作り出すのは、
VMが仮想的なハードウェアの環境を作り出すのに比べて、
コンテナのメリット
簡単にコンテナの仕組みを説明したところで、
高密度化が可能
コンテナではカーネルが直接プロセスを操作して隔離された空間を作り出すので、
オーバーヘッドが少ない
ハードウェアの仮想化が不要で、
起動が速い
コンテナの起動は、
アプリケーションのみの起動が可能
VMと異なり、
このような環境は アプリケーションコンテナ と呼ばれます。もちろんinitを最初に起動して、
コンテナのデメリット
逆にコンテナでは仕組み上、
異なるOSのシステム、プログラムは動かせない
起動しているOSは1つで、
Linuxの任意のディストリビューションはインストールできます。しかし、
カーネルに関わる操作はできない
正確にはカーネルに関わる操作は可能です。しかしコンテナごとに異なる操作を行うことはできません。カーネルの機能で実現している環境ですので、
以上、
Linuxカーネルのコンテナ関連機能 ~名前空間(Namespace)
コンテナの仕組みを簡単に見たところで、
名前空間(Namespace)とは
プロセスをグループ化して、
どのような名前空間があるかを表1で見てみましょう。
名前空間の名前 | 隔離されるリソース | 実装されたカーネルバージョン |
---|---|---|
マウント名前空間 | マウントの集合、 | 2. |
UTS名前空間 | ホスト名、 | 2. |
PID名前空間 | プロセスID(PID) | 2. |
IPC名前空間 | SysV IPCオブジェクト、 | 2. |
ユーザ名前空間 | UID、 | 3. |
ネットワーク名前空間 | ネットワークデバイス、 | 2. |
執筆時点のカーネル 3.
OS起動時にはデフォルトの名前空間が存在し、
それでは、
ここでは名前空間の体験を行うためにunshare
というコマンドを使用します。unshare
コマンドはutil-linuxに含まれるコマンドで、unshare
はutil-linux 2.
マウント名前空間
Linuxカーネルに最初に実装された名前空間です。マウント名前空間を使うと、
この機能を使うと、
それでは、unshare
コマンドでマウント名前空間を指定して、mount
コマンドを実行してみます。
$ sudo unshare --mount /bin/bash # touch /root/hosts # mount -o bind /etc/hosts /root/hosts # ls -l /root/hosts -rw-r--r-- 1 root root 224 Jul 13 2012 /root/hosts # cat /root/hosts 127.0.0.1 localhost :(略)
ここでは/etc/
を/root/
にバインドマウントしています。その後で/root/
を確認すると、/etc/
と同じ内容であり、
さて、/root/
を確認してみます。
$ sudo -s # ls -l /root/hosts -rw-r--r-- 1 root root 0 May 17 14:01 /root/hosts # cat /root/hosts #
unshare
で作成した名前空間内ではバインドマウントされていましたが、unshare
コマンドで作成したマウント名前空間内でだけ有効であることがわかります。
マウント名前空間はかなり高機能で細かな制御が可能です。こちらの文書がかなり詳しいのでご参照ください。
UTS名前空間
UTS名前空間はシンプルな機能です。名前空間ごとにホスト名やドメイン名を独自に持つことができます。この機能によりコンテナごとにホスト名を指定できます。
UTS名前空間もunshare
コマンドを使って試してみましょう。
$ hostname (unshare実行前にホスト名確認) lxctest.example.jp $ sudo unshare --uts /bin/bash (UTS名前空間を指定してunshare実行) # hostname container.example.jp (ホスト名をcontainer.example.jpに変更) # hostname (ホスト名を確認) container.example.jp (指定したホスト名に変更されている)
以上のようにホスト名が変わっています。ここで別のシェルを開いてホスト名を確認してみてください。
$ hostname lxctest.example.jp
unshare
を実行したシェル上ではホスト名が変わっていました。しかしホストOS上では変わっていない事がわかります。unshare
を実行したシェルを抜けて元の名前空間に戻った後にhostname
コマンドを実行しても、
# hostname container.example.jp # exit exit $ hostname lxctest.example.jp
IPC名前空間
IPC名前空間はプロセス間通信
PID名前空間
PID名前空間は文字通りプロセスIDを名前空間ごとに持てます。通常はPIDは一意に決まる数字が振られますが、
新しく作成したPID名前空間の最初のプロセスのPIDは、
この機能は、
言葉で言うとわかりづらいですね。これも実際に実行例を見てみましょう。ここではunshare
ではなく、lxc-start
コマンドで実際にシステムコンテナを起動してみましょう。
$ sudo lxc-start -n ubuntu01 -d $ pstree -p init(1)-+-acpid(1069) :(略) |-lxc-start(3060)---init(3071)-+-cron(3475) | |-dhclient(3393) | |-getty(3461) | |-getty(3464) | |-getty(3465) | |-getty(3507) | |-getty(3628) :(略)
lxc-start
コマンドを実行して、pstree
コマンドを実行してみてください。ここで表示されているPIDはlxc-start
を実行したホストOS上でのPIDです。
ここでコンテナ内に入ってプロセスを確認してみましょう。sudo lxc-console -n ubuntu01
と実行してログインしても、lxc-create
で作成したUbuntu環境にはpstree
コマンドがないのでインストールしています。
$ ssh -l ubuntu 10.0.3.18 apt-get install psmisc $ ssh -l ubuntu 10.0.3.18 pstree -p init(1)-+-cron(380) |-dhclient(282) |-getty(355) |-getty(358) |-getty(359) |-getty(400) |-getty(548) :(略)
ホストOS上でプロセスを確認すると、lxc-start
の子プロセスとしてinit
が起動しており、init
の子プロセスとしていろいろなプロセスが起動しているのを見ることができています。つまりホストOS上からは、
コンテナ内では、init
を元にいろいろなプロセスが起動しているのが確認できています。確認できているのはコンテナ内のinit
から起動したプロセスのみです。つまりコンテナ内のプロセス以外は見えていません。コンテナ内で見る限りはそこがコンテナでないOSの環境なのか、
コンテナ内での最初のプロセスであるinit
のPIDはホストOSのinit
と同じで1となっています。つまり名前空間が異なると同じPIDが存在できることがわかります。
また、
異なる名前空間で独立したPIDを持てるということは、
ネットワーク名前空間
ネットワーク名前空間は各種のネットワークリソースを名前空間ごとに独立して持つことができます。具体的にはネットワークデバイス、
この機能により、eth0
という同じ名前のネットワークデバイスを持つこともできます。
この機能も簡単に体験しておきましょう。
$ sudo unshare --net /bin/bash # ip link show 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 # route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface # iptables -L -n -v Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
新しいネットワーク名前空間を作成すると、
この新しくできた名前空間をどう使うかを理解するには、
ユーザ名前空間
ユーザ名前空間は名前空間機能の中で最も最近実装された機能です。この機能はUID、
この機能が最も効果を発揮する場面がコンテナ内のrootユーザを扱うときです。先に述べたようにホストOS上のUID、
つまり、
独立したユーザ名前空間を作ることで、
ユーザ名前空間の実例についても、
まとめ
今回はコンテナの仕組みを簡単に説明したあと、
次回はLinuxカーネルに実装されているもうひとつの重要なコンテナ関連機能であるcgroupについて説明したいと思います。
LXC公式サイトの翻訳
最後にひとつ宣伝を。前回の記事で紹介したLXCの公式サイトを有志で日本語に翻訳してhttp://
一度ご覧になってみてください。
- ※)
- 現在は公式サイトの日本語訳は公式サイト上でご覧になれます。