TenForward

技術ブログ。はてなダイアリーから移転しました

Google Chrome の Namespace 利用のメモ

(2016-05-16 Chromium の参考ページが移動していたので更新)

過去に勉強会なんかで「Linux 版の Chrome は Namespace を使ってる」という話をしたことあるけど、そういえば確認したことはなかったので確認したメモ。

参考はこの辺り。

pidns と netns を使ってそうです。

まず Google Chrome を起動します。最近 Linux 版は重くて使ってないけど。

$ pstree -p
    :(snip)
        |-chrome(29616)-+-chrome-sandbox(29618)---chrome(29620)-+-chrome(29630)-+-chrome(29701)-+-{chrome}(29702)
        |               |                                       |               |               |-{chrome}(29720)
    :(snip)
        |               |                                       `-chrome-sandbox(29624)---nacl_helper(29625)
    :(snip)

chrome-sandbox ってのがこの辺り作りそうですね。

まずはinitの名前空間を確認します。

# ls -l /proc/1/ns
合計 0
lrwxrwxrwx 1 root root 0  3月  9日  19:02 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0  3月  9日  19:02 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0  3月  9日  19:02 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0  3月  9日  19:02 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0  3月  9日  19:02 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0  3月  9日  19:02 uts -> uts:[4026531838]

次に chrome-sandbox の子プロセスの chrome の ns を確認。

# ls -l /proc/29620/ns
合計 0
lrwxrwxrwx 1 karma users 0  3月  9日  20:06 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 karma users 0  3月  9日  20:06 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 karma users 0  3月  9日  20:06 net -> net:[4026532408]
lrwxrwxrwx 1 karma users 0  3月  9日  20:06 pid -> pid:[4026532406]
lrwxrwxrwx 1 karma users 0  3月  9日  20:06 user -> user:[4026531837]
lrwxrwxrwx 1 karma users 0  3月  9日  20:06 uts -> uts:[4026531838]

net と pid が異なるのが、上記の特殊なシンボリックリンク先でわかりますね (数字が違う)。他は同じです (数字が同じ)。

実際この Namespace 内に入ってみましょう。

# nsenter -t 29620 -n -p

まずは netns の確認。

# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

新たに netns を作ったので、インターフェースはループバックしかありません。

次に pidns の確認。ps とかのこの辺り確認するコマンドは /proc を見ますので、このままだと親 ns の結果が出ますので使えません (うっかりしててハマった ^^;)。新たに procfs をマウントしてみます。

# mount -t proc proc /mnt
# ls /mnt
1/   acpi/      dma          key-users   mtrr          sysrq-trigger
11/  asound/    driver/      keys        net@          sysvipc/
21/  buddyinfo  execdomains  kmsg        pagetypeinfo  thread-self@
28/  bus/       fb           kpagecount  partitions    timer_list
3/   cgroups    filesystems  kpageflags  sched_debug   tty/
4/   cmdline    fs/          loadavg     scsi/         uptime
58/  config.gz  interrupts   locks       self@         version
6/   consoles   iomem        meminfo     slabinfo      vmallocinfo
82/  cpuinfo    ioports      misc        softirqs      vmstat
9/   crypto     irq/         modules     stat          zoneinfo
93/  devices    kallsyms     mounts@     swaps
97/  diskstats  kcore        mpt/        sys/

pidns 内の PID=1 はこんなです。

# cat /mnt/1/cmdline ; echo
/opt/google/chrome/chrome --type=zygote

LXD でリモートの LXD ホストのコンテナを操作してみる

LXD 0.1 がリリースされたのでLXD を試してみた続きです。

LXD の特徴は複数の LXD ホストをリモートから管理できることです。というわけでリモートの LXD ホストの操作を試してみました。とりあえず動くのを確かめただけです。

  • テスト用の LXD ホストは Ubuntu 14.04.1 LTS です。README通りに設定してあります
  • lxc コマンドを実行するホストは前回のエントリ]で使った Plamo 5.3 ホストです

LXD サーバ

lxd をオプションなしで起動すると、Unix ドメインソケットのみのローカルからの接続のみを受け付けるモードで起動します。リモートから受け付ける場合は "--tcp" オプションを使います。

$ cd ~/go/bin
$ ./lxd --tcp=10.200.200.200:8443 & (10.200.200.200のアドレスのホストの8443番ポートで待ち受け)

リモートから受け付ける際のパスワードを設定します。

$ ./lxc config set pasword hogehoge (パスワードをhogehogeに設定)

クライアント側

クライアントからリモートの LXD ホストを操作する場合は、まずリモートホストを登録します。これでリモートホストの証明書がダウンロードされ、クライアントの証明書が LXD ホストにも登録されます (たぶん)。

$ ./lxc remote add lxdhost 10.200.200.200:8443 (10.200.200.200 のホストを "lxdhost" という名前で登録)
Certificate fingerprint: 8c ea 8b a3 a0 64 dd 9f 5e fb 28 dd f6 89 c6 58 7c 8b e0 ab 62 c1 14 f5 50 dc 44 16 06 83 fa 85
ok (y/n)? y
Admin password for lxdhost: ("lxdhost" で設定したパスワードを入れる)
Client certificate stored at server:  lxdhost

これで準備 OK です。あとはローカルとほぼ同じです。コンテナを指定するときに登録したホスト名の後にコロンをつけて、コンテナ名を指定します。

$ ./lxc init ubuntu lxdhost:test01 ("test01" コンテナを "lxdhost" に作成)
$ ./lxc list lxdhost: ("lxdhost" のコンテナ一覧)
test01
$ ./lxc start lxdhost:test01 ("lxdhost"上の"test01"コンテナの起動)
$ ./lxc exec lxdhost:test01 -- /bin/uname -a ("lxdhost"上の"test01"コンテナでunameコマンド実行)
Linux test01 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

LXD を試してみた

LXD 0.1 がリリースされましたので LXD を試してみました。

こちらも参考に。ただし、現時点では以下とは少しコマンドが違うようです。

Plamo 5.3 で試しています (kernel は独自ビルドの 3.19)。go コマンドはインストール済み。

構築

lxd/README.md at master · lxc/lxd · GitHub の通りです。

$ mkdir -p ~/go
$ export GOPATH=~/go
$ go get github.com/lxc/lxd
$ cd $GOPATH/src/github.com/lxc/lxd
$ go get -v -d ./...
$ make

これで ~/go/bin 以下にコマンドができました。

$ ls ~/go/bin
fuidshift*  lxc*  lxd*

デーモン起動

これも書いてある通り。

$ sudo mkdir -p /var/lib/lxd
$ sudo chown karma:users /var/lib/lxd

subuid, subgid は設定済みです

$ cat /etc/subuid
karma:100000:65536
$ cat /etc/subgid
karma:100000:65536

とりあえず verbose モードで起動してみました。

$ ~/go/bin/lxd --help
Usage: lxd [options]

Options:
    --debug  (= false)
        Enables debug mode.
    --group (= "")
        Group which owns the shared socket
    --help  (= false)
        Print this help message.
    --tcp (= "")
        TCP address <addr:port> to listen on in addition to the unix socket (e.g., 127.0.0.1:8443)
    -v  (= false)
        Enables verbose mode.
    --version  (= false)
        Print LXD's version number and exit.

非特権コンテナのようですから、Plamo の場合、lxd コマンドを動かすシェルを読み書きできる cgroup に登録しないといけません(Ubuntuだとsystemd-logind辺りが作ったグループがあるのでそれを使いますのでこれは不要)。その後おもむろに lxd 起動

$ for d in /sys/fs/cgroup/*
> do
> echo $$ > $d/karma/tasks
> done
$ ~/go/bin/lxd -v

コマンド

$ cd ~/go/bin
$ ./lxc help
Usage: lxc [subcommand] [options]
Available commands:

	config     - Manage configuration.
	delete     - lxc delete <resource>
	exec       - exec specified command in a container.
	file       - Manage files on a container.
	finger     - Fingers the lxd instance to check if it is up and working.
	help       - Presents details on how to use lxd.
	list       - Lists the available resources.
	remote     - Manage remote lxc servers.
	restart    - Changes a containers state to restart.
	snapshot   - Create a read-only snapshot of a container.
	start      - Changes a containers state to start.
	stop       - Changes a containers state to stop.
	version    - Prints the version number of lxd.
コンテナ作成

イメージを勝手に落としてきてコンテナ作ります。help に init がないよw

$ ./lxc init ubuntu test01
$ ./lxc list 
test01
コンテナ起動

特にひねりはありません。素直に start。

$ ./lxc start test01
$
コンテナの状態確認

特に何もなく起動しているようですが、起動している様子を表示することができません ^^;

$ ./lxc info test01
error: unknown command: info
  :(snip)

プロセスを見てみると

$ pstree -p
  :(snip)
        |                      |-bash(24780)---lxd(17197)-+-{lxd}(17198)
        |                      |                          |-{lxd}(17199)
        |                      |                          |-{lxd}(17202)
        |                      |                          `-{lxd}(17203)
  :(snip)
        |-lxd(17207)---init(17218)-+-cron(18639)
        |                          |-getty(18626)
        |                          |-getty(18628)
        |                          |-getty(18629)
        |                          |-getty(18670)
        |                          |-getty(18673)
        |                          |-rsyslogd(17673)-+-{rsyslogd}(17684)
        |                          |                 `-{rsyslogd}(17685)
        |                          |-systemd-udevd(17564)
        |                          |-upstart-file-br(17670)
        |                          |-upstart-socket-(17669)
        |                          `-upstart-udev-br(17540)

確かに Plamo の上で Ubuntu が起動しているようです。

試してみると lxc のコマンドが使えそうです。

$ lxc-ls -P /var/lib/lxd/lxc -f
NAME    STATE    IPV4  IPV6  GROUPS  AUTOSTART  
----------------------------------------------
test01  RUNNING  -     -     -       NO         
$ lxc-info -P /var/lib/lxd/lxc -n test01
Name:           test01
State:          RUNNING
PID:            17218
CPU use:        1.17 seconds
BlkIO use:      248.00 KiB
Memory use:     3.94 MiB
KMem use:       0 bytes

コマンド実行

$ ./lxc exec test01 -- /bin/uname -a
Linux test01 3.19.0-plamo64-karma #2 SMP PREEMPT Mon Feb 9 16:13:40 JST 2015 x86_64 x86_64 x86_64 GNU/Linux

lxc-attach コマンドも使えます。

$ lxc-attach -P /var/lib/lxd/lxc -n test01 -- uname -a
Linux test01 3.19.0-plamo64-karma #2 SMP PREEMPT Mon Feb 9 16:13:40 JST 2015 x86_64 x86_64 x86_64 GNU/Linux
コンテナの停止

普通にできます。

$ ./lxc stop test01
$ lxc-ls -P /var/lib/lxd/lxc -fNAME    STATE    IPV4  IPV6  GROUPS  AUTOSTART  
----------------------------------------------
test01  STOPPED  -     -     -       NO         

(続く)

2014年振り返りコンテナ編

今年は2014年を振り返るみたいなブログやらFacebookの書き込みをよく見かける気がするので私も。もう今年も残り少ないので手短に。

Docker が春くらいからそれまで以上に盛り上がりはじめて、そこら中のベンダーがサポートを表明してましたね。その盛り上がりのおかげというわけでもないのですが、gihyo.jpコンテナとLXCに関する連載 をさせていただきました。つたない文章ですが、それなりにご覧いただいていたようでありがとうございました。

それと第2回 以降、急激に参加人数の増えた コンテナ型仮想化の情報交換会 は、かなり私の趣味に走った勉強会にも関わらず今年も毎回色々な方にお話いただき、多数の方に参加いただき、色々な方と知り合うことができ、色々な勉強ができました。ありがとうございました。

この勉強会をきっかけに他の勉強会に呼んでいただいて登壇できたのも良い経験でした。

どちらかというと人見知りで初めての方とお話するのが苦手な私でも、勉強会主催とか登壇者となるとたくさんの方が話しかけて下さるので、世界も広がったような気がします。

私はコンテナやcgroupなどに関して広く知られて盛り上がる前から調べていたので、今色々偉そうに話したり書いたりできていますが、実際持っている知識はたいしたことがありません。コンテナが盛り上がっている今では、私より頭の良い色々知識が豊富な方が私の興味のある分野について色々なところでお書きになったりお話になったりするようになっていますし、今後はますますそうなっていくでしょうから、今後はそれを勉強させてもらう方が多くなるような気がしています。それはそれで楽しみだなあ、と思ってます。

今年一年どうもありがとうございました。来年もよろしくおねがいたします!!良い年をお迎えください!!

コンテナの歴史と Linux カーネルのコンテナ関連機能についての割とどうでも良い愚痴

この記事は Linux Advent Calendar 2014 の 18 日目のエントリとして書いています。

Docker が盛り上がって、Docker が使ってる「コンテナ」という技術が盛り上がって、Doker の解説がそこら中にあふれるようになったので「Docker? そんなの FreeBSD が jail でずっと前からできてたぞ」というちょっと的外れな発言を見かけることは少なくなりました。一方でコンテナの歴史を追って見る的な企画をみかけるようになりました。

みかけた歴史の解説でいくつか「ちょっと違うやろー」というものを見かけたのでここで愚痴ります。

コンテナの歴史として大体書かれているのが

1979 年 chroot(2) システムコールの Version 7 Unix への導入
1983 年 chroot(2) システムコールの 4.2BSD への導入
2000 年 FreeBSD jail が FreeBSD 4.0 に導入
2005 年 Solaris Containers 登場
2008 年 Cgroup が Linux カーネル 2.6.24 にマージ
2014 年 Docker 1.0 リリース

というものです。

もちろん「chrootFreeBSD jail → Linux のコンテナ」という大きな流れを否定するつもりはありません。しかし、前述の年表のようなものにはかなり違和感を覚えます。

しかも私が見たいくつかの記事では「FreeBSD jail (相当|と同様) の機能として cgroup が実装」「ここで初めてLinuxにコンテナの機能が実装された」というような説明がなされています。つまり「FreeBSD jail≒Linux Cgroup≒Linuxカーネルに実装されたコンテナ」というわけですな。これはおかしい!!

どこが!? そう、LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術:連載|gihyo.jp … 技術評論社 を読んでいただいている方はおわかりいただけるのではないでしょうか!? (宣伝)

Linux カーネルに実装されているコンテナ関連の機能

Linux カーネルに実装されているコンテナ関連の機能の主要なものは大きく 2 つあると言えるでしょう。もちろん Cgroup はその一つです。しかし Cgroup だけではコンテナは実現できません。

ここでその 2 つの機能のおさらいです。

Cgroup
コンピュータに備わる物理的なリソース(cpu, memory, etc)を隔離/制限するための機能
Namespace(名前空間)
カーネル/OSが扱うリソース(ホスト名、ネットワークスタック、PID、etc)を隔離するための機能

そう、この 2 つです。なんで Cgroup だけが取り上げられるん? (もちろんこの2つの他にも使っている技術は様々あります)

そもそも前述の流れだと FreeBSD jail からの流れになっており、FreeBSD jail 相当の機能として Cgroup となっています。FreeBSD jail ってディレクトリツリーとかプロセスとかネットワークスタックとか (これは Vimage か) の隔離ですよね?

この流れからいくと取り上げるべきは Cgroup ではなく Namespace じゃないですか? 今の所 6 つある Namespace のうち、最初にカーネルにマージされたのは Mount Namespace で、なんと 2.4.19 でのマージです (2002 年)。*1

jail 相当とも言える PID Namespace が導入されたのは 2.6.24 で 2008 年なので、前述の年表で「Linuxのコンテナ機能がとりあえず実装されたとき」として 2008 年を取り上げるのは問題ないと思いますが、jail に対応する機能としては Namespace を取り上げるべきなのです

歴史を語るのは重要なんですが、ちゃんと機能を理解して書いてほしいなあというわりとどうでもよい愚痴でした。

ああ、Linux Advent Calendar 2014 の他のに比べて著しくレベル低いですね… (^^;)

*1:ちなみにMount Namespaceを表すカーネル内の定義は、当時他にNamespaceがなかったためCLONE_NEWNS(Clone New Namespace)というなんとも一般的でマウントなのかどうかわからないものになってます。