LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術

第2回 コンテナの仕組みとLinuxカーネルのコンテナ機能[1]名前空間とは?

この記事を読むのに必要な時間:およそ 5.5 分

Linuxカーネルのコンテナ関連機能 ~名前空間(Namespace)

コンテナの仕組みを簡単に見たところで,Linuxカーネルに実装されているコンテナに関連する機能のうち,代表的なものをあげて説明していきましょう。実は,Linuxカーネルに実装されているコンテナ関連の機能は,コンテナ専用の機能として実装されているものばかりではありません。もちろん,コンテナで使うことを念頭に開発されていますが,その機能は単独でも使用できます。

名前空間(Namespace)とは

プロセスをグループ化して,コンテナの隔離された空間を作り出す機能に重要な役割を果たすのが 名前空間 ⁠Namespace) という機能です。名前空間は『名前空間』という機能がひとつ存在するわけでなく,独立させたいリソースによっていくつかの機能があります。

どのような名前空間があるかを表1で見てみましょう。

表1 名前空間の種類

名前空間の名前隔離されるリソース実装されたカーネルバージョン
マウント名前空間マウントの集合,操作2.4.19
UTS名前空間ホスト名,ドメイン名2.6.19
PID名前空間プロセスID(PID)2.6.24
IPC名前空間SysV IPCオブジェクト,POSIXメッセージキュー2.6.19
ユーザ名前空間UID,GID3.8
ネットワーク名前空間ネットワークデバイス,アドレス,ポート,ルーティングテーブル,フィルタなど2.6.26

執筆時点のカーネル 3.14 で実装されている名前空間は以上です。

OS起動時にはデフォルトの名前空間が存在し,デフォルトでは全てのプロセスはそのデフォルトの名前空間に属します。プロセスの起動時に独立した名前空間で実行する指定を行うと,そのプロセスは別の名前空間で実行されます。どのリソースを独立させたいかによって,表1に示した名前空間を単独で指定したり,組み合わせて指定したりします。

それでは,それぞれの名前空間を,実際にいくつかの名前空間を作りながらもう少し詳しく見ていきましょう。

ここでは名前空間の体験を行うためにunshareというコマンドを使用します。unshareコマンドはutil-linuxに含まれるコマンドで,引数に与えたコマンドを起動する際,オプションで与えた名前空間を新たに作成して,その名前空間内で実行します。unshareはutil-linux 2.17以降に含まれますが,バージョンによって作成できる名前空間に差があります。ここではUbuntu 14.04LTS上で実行した例を示します。以下では,このベースとなるUbuntuの環境を『ホストOS』と呼ぶことにします。

マウント名前空間

Linuxカーネルに最初に実装された名前空間です。マウント名前空間を使うと,名前空間内で行ったマウント操作を,他の名前空間には反映させないといったことができます。もちろん,他の名前空間に反映させるという設定を行うこともできます。

この機能を使うと,コンテナ内でマウント操作を行った場合でも,そのマウントはホストOSや他のコンテナからは見えません。

それでは,マウント名前空間を試してみましょう。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/hosts/root/hostsにバインドマウントしています。その後で/root/hostsを確認すると,/etc/hostsと同じ内容であり,確かにバインドマウントされているのが確認できます。

さて,ここで別のシェルを実行して,同様に/root/hostsを確認してみます。

$ sudo -s
 # ls -l /root/hosts
 -rw-r--r-- 1 root root 0 May 17 14:01 /root/hosts
 # cat /root/hosts
 #

unshareで作成した名前空間内ではバインドマウントされていましたが,ホストOS上で直接実行しているシェル,つまり別のマウント名前空間から見るとサイズが0で,ファイルの中身は空です。つまりマウントは,unshareコマンドで作成したマウント名前空間内でだけ有効であることがわかります。

マウント名前空間はかなり高機能で細かな制御が可能です。こちらの文書がかなり詳しいのでご参照ください。

補足(2015/06/29)

systemdがinitとして採用されている場合は紹介した例とは異なり,ある名前空間で行ったマウントが他の名前空間で見えてしまうことがあります。これはsystemdが異なる名前空間の間でマウントを共有するという設定を行うためです。本文中で紹介した文書「sharedマウント」として説明されている設定です。

systemd環境で本文中の例のように他の名前空間でマウントを見えないようにするには,以下のようなコマンドを実行するとよいでしょう。

$ sudo mount --make-private /

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名前空間はプロセス間通信(IPC)オブジェクトを名前空間ごとに独立して持つことができます。具体的にはSystem V プロセス間通信オブジェクトと,POSIXメッセージキューです。

著者プロフィール

加藤泰文(かとうやすふみ)

2009年頃にLinuxカーネルのcgroup機能に興味を持って以来,Linuxのコンテナ関連の最新情報を追っかけたり,コンテナの勉強会を開いたりして勉強しています。英語力のない自分用にLXCのmanページを日本語訳していたところ,あっさり本家にマージされてしまい,それ以来日本語訳のパッチを送り続けています。

Plamo Linuxメンテナ。ファーストサーバ株式会社所属。

Twitter:@ten_forward
技術系のブログ:http://d.hatena.ne.jp/defiant/

コメント

コメントの記入