遅ればせながら、コンテナ型仮想化ツール「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性能の活用が可能か?
アップデートがあれば投稿したいと思います。