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

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

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

PID名前空間

PID名前空間は文字通りプロセスIDを名前空間ごとに持てます。通常はPIDは一意に決まる数字が振られますが,異なる名前空間にいるプロセスは同じPIDを持つことができます。

新しく作成したPID名前空間の最初のプロセスのPIDは,作成した名前空間内で見ると1となります。このプロセスは,名前空間を作る元となった親の名前空間でも別のPIDを持ちます。つまり親子関係のある名前空間では,それぞれの名前空間ごとにPIDを持っていて,カーネル内部でその対応関係を管理しています。

この機能は,親の名前空間から子の名前空間のプロセスを見ることはできます。逆に子の名前空間から親の名前空間のプロセスは見えません。

言葉で言うとわかりづらいですね。これも実際に実行例を見てみましょう。ここではunshareではなく,第1回で実行例を見た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と実行してログインしても,ssh経由でログインしても構いません。以下はホストOSからsshコマンドで確認しています。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上からは,コンテナのプロセスを全て見ることができています。

コンテナ内では,ホストOSと同様にinitを元にいろいろなプロセスが起動しているのが確認できています。確認できているのはコンテナ内のinitから起動したプロセスのみです。つまりコンテナ内のプロセス以外は見えていません。コンテナ内で見る限りはそこがコンテナでないOSの環境なのか,コンテナ内の環境なのかはわかりません。

コンテナ内での最初のプロセスであるinitのPIDはホストOSのinitと同じで1となっています。つまり名前空間が異なると同じPIDが存在できることがわかります。

また,プロセスのPIDをホストOS,コンテナそれぞれの環境で見ると,それぞれの環境でPIDを持っており,そのPIDは異なっていることもわかります。

異なる名前空間で独立したPIDを持てるということは,コンテナのマイグレーションで異なるホストへコンテナを移動する場合も重要な機能となります。

ネットワーク名前空間

ネットワーク名前空間は各種のネットワークリソースを名前空間ごとに独立して持つことができます。具体的にはネットワークデバイス,IPアドレス,ルーティングテーブル,ポート番号,フィルタリングテーブルなどです。

この機能により,コンテナはホストOSとは別のIPアドレスを持てますし,ホストOS上で使用中のポートがあったとしても,コンテナでも同じ番号のポートを使うことができます。たとえば,ホストとコンテナの両方で,それぞれに割り当てた別のIPアドレスで,同じポート番号で待ち受けるウェブサーバを起動できます。また,ホストOSとコンテナの両方に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,GIDの空間を名前空間ごとに独立して持つことができます。名前空間内のUID,GIDとホストOS上のUID,GIDとが紐づけられ,名前空間の中と外で異なるUID,GIDを持つことができます。

この機能が最も効果を発揮する場面がコンテナ内のrootユーザを扱うときです。先に述べたようにホストOS上のUID,GIDと紐づけを行うことができますので,コンテナ内ではUID,GID共に0のrootユーザを,ホストOS上ではたとえばUID,GID共に100000である一般ユーザとして扱うことができます。

つまり,コンテナのrootがホストOS上では特権を持たないことになりますので,セキュアにコンテナ環境を提供することが可能になります。また一般ユーザがコンテナ環境を構築して起動するということが可能になりました。

独立したユーザ名前空間を作ることで,特権のないプロセスが今まで特権を必要としていた機能にアクセスすることができるようになったので,アプリケーションからこの機能を使うことで,新たな可能性が広がるように思います。

ユーザ名前空間の実例についても,この連載の後で取り上げる一般ユーザが扱うコンテナの話題のところで説明する予定です。

まとめ

今回はコンテナの仕組みを簡単に説明したあと,コンテナを実現するための重要な機能である名前空間機能について説明しました。今回説明したのは3.14カーネルに実装されている機能です。現時点でコンテナを実現するための主要な機能は揃っていると言えるでしょう。一方で,カーネルの開発メーリングリストにはまだいろいろな名前空間機能が提案され,議論がなされています。まだまだ発展途上で目が離せない興味深い機能です。

次回はLinuxカーネルに実装されているもうひとつの重要なコンテナ関連機能であるcgroupについて説明したいと思います。

LXC公式サイトの翻訳

最後にひとつ宣伝を。前回の記事で紹介したLXCの公式サイト有志で日本語に翻訳してhttp://lxc-jp.github.io/で公開しています)⁠

一度ご覧になってみてください。

※)
現在は公式サイトの日本語訳は公式サイト上でご覧になれます。

著者プロフィール

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

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

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

Twitter:@ten_forward
技術系のブログ:http://tenforward.hatenablog.com/

コメント

コメントの記入