コンテナ型とハイパバイザ型の仮想化 NW分離覚書き


遅ればせながら、コンテナ型仮想化ツール「Docker」を検証環境で利活用はじめました。

なにぶん自分はNWエンジニアなので、Dockerをはじめとする「コンテナ型仮想化」ツールについて
まず何より最初に、そのNW分離方法の特徴に興味をそそられました。

そこで、これまで多用してきたlibvirt + KVMによる「ハイパバイザ型仮想化」とのLinux内部的な
NW分離の実現方式の比較を、覚書きとして残したいと思います。


「コンテナ型仮想化」(Docker)のNW分離について

まずDockerがホストとコンテナのNWをnamespaceモジュールの機能によって実現している事を
確認します。

root@ubuntu:~# ps -ef | grep docker
root      1219     1  0 Sep11 ?        00:01:53 /usr/bin/docker -d
root     21478  9790  0 05:01 pts/0    00:00:00 docker attach d5bf7b1ae9eb
root     21505 21488  0 05:01 pts/8    00:00:00 grep --color=auto docker

PPID 1219を持つPID 21378のプロセス、これがすなわちDockerコンテナの実行中プロセスに当たります

root@ubuntu:~# ps -ef | grep 1219
root      1219     1  0 Sep11 ?        00:01:53 /usr/bin/docker -d
root     21378  1219  0 04:56 pts/5    00:00:00 /bin/bash
root     21515 21488  0 05:04 pts/8    00:00:00 grep --color=auto 1219



次いで、上で確認したDockerコンテナ実行プロセスのnamespaceをip netnsコマンドで操作可能に
します。

root@ubuntu:~# ls -l /proc/21378/ns/net
lrwxrwxrwx 1 root root 0 Sep 13 05:04 /proc/21378/ns/net -> net:[4026532525]

root@ubuntu:~# ln -s  /proc/21378/ns/net /var/run/netns/ubu

root@ubuntu:~# ip netns exec ubu ip link sh
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
58: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 76:9d:43:de:b4:0f brd ff:ff:ff:ff:ff:ff

これをホストのデフォルトnamespaceでのip link sh出力と比較します。

root@ubuntu:~# ip link sh
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:44:79:fc brd ff:ff:ff:ff:ff:ff
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
59: veth48df: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master docker0 state UP mode DEFAULT group default qlen 1000
    link/ether c2:63:75:4a:69:34 brd ff:ff:ff:ff:ff:ff



以上の確認から、Dockerのホスト~コンテナのNW分離は、ホストのKernelネットワークサブシステムを
namespaceで分離するという、応用的な方法により実現されていることが確認できました。


「ハイパバイザ型仮想化」(libvirt + KVM)のNW分離について

この方式が、原則的にはnamespaceを利用していない事を確認します。
まず、ゲストOSを実行した状態でのnamespaceの新規作成の有無を確認します。

以下のコマンドでは、ホストOSのシステムで作成済みのnamespaceを表示しています。

root@ubuntu:~# ls /proc/*/ns/net -l | awk '//{ print $NF}' | uniq
net:[4026531956]

上の結果から、ゲストOS起動時でも新たなnamespaceの生成は為されていない事が確認されました。



これは、ハイパバイザ型の仮想化がゲストOSというuserlandプロセスとホストOSとの通信を
tapモジュールを利用したプロセス間通信として実現している事に因ります。

ゲストOSが独自のカーネルを実行し、同時にそれはゲストOSというプロセスの中で完結しているため、
ホストOSのNW空間と混信する事は起きないからです。

次の出力は、tunデバイスによってホストOS~ゲストOS間が通信している事を確認するものです。

root@ubuntu:~/clang/rawsend# lsof /dev/net/tun 
COMMAND     PID         USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
qemu-syst 16479 libvirt-qemu   24u   CHR 10,200      0t0 7320 /dev/net/tun
qemu-syst 16479 libvirt-qemu   26u   CHR 10,200      0t0 7320 /dev/net/tun



Dockerについては始めたばかりで、不勉強な点が多いですが、今後キャッチアップ+αを試みたいと
思っております。

今いま気になっている疑問点としては、
・Intel-VT / AMD-VTの稼働有無はパフォーマンスに影響があるか?
・ホストのNWカーネルモジュールを使うため、特にチューニングなくして、SR-IOVに類するような
 ダイレクトなNIC性能の活用が可能か?

アップデートがあれば投稿したいと思います。