docker のコンテナをホストと同じネットワークに所属させる備忘録

Networks
Photo by hyt.

docker のコンテナをホストと同じネットワークに所属させる備忘録です.

いつもの通り結論から言うと,

macvlan を使う

で良いみたいですね.ただし,いくつか注意しないといけないことがあるので,以下その辺りをつらつらと書きたいと思います.

macvlan ってなに?

いきなりですが,macvlan というのは docker 特有のものではなくて,linux kernel で実現される

物理インターフェース(eth0とか)に重ねて使う別の mac アドレスを持つ仮想インターフェース

のことみたいです.日本語の分かり易い記事は,

第6回 Linuxカーネルのコンテナ機能[5] ─ネットワーク | gihyo.jp
コンテナに関係する主要な機能2つの説明が済んだので、今回はLXCで使われることが多いネットワーク関連の機能を紹介しましょう。

にあり,macvlan とよく似た ipvlan と合わせて説明してある記事が,英語ですが,

Macvlan and IPvlan basics
Macvlan and ipvlan are Linux network drivers that exposes underlay or host interfaces directly to VMs or Containers running in the host. In this blog, I will co...

にあります(ipvlan の L2 モードだと同じ mac アドレスで通信できる.つまり L2 ブリッジを実現できるのが ipvlan の L2 モード).重ねて使うんだから,当然,同じホストと同じネットワークに所属することになるわけですね.

利点と欠点は以下の通り.

まず,利点は,

  • 別の mac を持つので DHCP でアドレスを割り当てられる
  • 実際の通信は物理インターフェースのドライバで行われるのでソフトウェアで行われる veth に比べパフォーマンスに優れる.

みたいで,逆に欠点は,

  • eth0 との直接通信はできない(仕組み上の制限).

だそう.ただし,docker で使う場合は,DHCP でのアドレス割り当ては(普通は)できないので最初の利点はあるようでないです.

そして,macvlan には,通信可能範囲の違う以下の4つのモードがある.

  1. bridge: 同じインターフェースに割り当てた macvlan どうしが直接通信できる.
  2. vepa: bridge と同じだが,vepa 機能を持つ(物理)スイッチの NIC 経由で通信する.ハードウェア処理されるので高速に通信できる.
  3. passthru: macvlan で tup デバイス (macvtup) が使える.
  4. private: 上記が不可能なモード

使い方が分かりにくいのが passthru なんですが,これはどうも macvlan に複数の仮想マシン(コンテナ)のネットワークをブリッジさせるときなんかに使うようです.あと,面白いのが vepa だと思います.同じインターフェースに割り当てた macvlan どうしの直接通信の高速化をハードウェアで行うためのモードということで,「へー」という感じですね.

docker での使い方

docker で macvlan を使う方法は,

Use macvlan networks
All about using macvlan to make your containers appear like physical machines on the network

が公式みたいですね.docker だと今のところ bridge モードでしか作れない?みたい.以下,この記事に従って色々試してみた結果です.

まずは作り方.labohyt.local ネットワークを bridge モードで作る場合は,

$ docker network create -d macvlan --subnet=192.168.0.0/24 --ip-range=192.168.0.212/31 --gateway=192.168.0.1 -o parent=enp1s0 labohyt.local
d496dc4398b0e4f063e37ec7be5f077aa3f6ded1510301d83ea2db91b2eedab4

$ docker network ls
NETWORK ID          NAME                        DRIVER              SCOPE
34474c7ff0f2        bridge                      bridge              local
2ef24b2b41b9        host                        host                local
d496dc4398b0        labohyt.local               macvlan             local
6a5d6d137792        none

みたいな感じでしょうか.

  • -o parent=enp1s0

ってのは,関連づける物理インターフェースの名称を指定する部分です.ものによっては enp1s0 じゃなくて eth0 とかだと思います.VLAN を指定する場合は,

  • -o parent=enp1s0.10

みたいにやれば良い.

あと注意点として,

  • –ip-range=192.168.100.212/31

みたいにコンテナが使うアドレスの範囲を(使われていないアドレスの範囲に)制限しておくべきです.macvlan の仕組みから言ってホストマシンと同じネットワークを使うので下手をするとアドレスが被ってしまうからです.

では,実際に使ってみます.本家サイトと同じく alpine linux を使います.

$ docker run --rm -itd --network labohyt.local --name alpine1 alpine:latest ash
e37d2432fedd5a61d68ca1cf7e96b311f5c4d6dfb042b75fc5adbb1c3632382b

$ docker run --rm -itd --network labohyt.local --name alpine2 alpine:latest ash
d85d7d92c10af6316f7b3d29d6ebc9718cb18c41a4048d258974a0004f98e718

$ docker exec alpine1 ip a show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
12: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN 
    link/ether 02:42:c0:a8:64:d4 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.212/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::00:00ff:fe00:00d4/64 scope link 
       valid_lft forever preferred_lft forever

$ docker exec alpine1 ip route show
default via 192.168.100.1 dev eth0 
192.168.0.0/24 dev eth0 scope link  src 192.168.0.212

$ docker exec alpine2 ip a show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
13: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN 
    link/ether 02:42:c0:a8:64:d5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.213/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c0ff:fea8:64d5/64 scope link 
       valid_lft forever preferred_lft forever

と言うことで,きちんと,192.168.0.212 と 192.168.0.213 に別の mac アドレスが割り当てられていることが分かります.次に通信可能な範囲を見てみます.

$ docker attach alpine1
/ # ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=119 time=5.730 ms
64 bytes from 8.8.8.8: seq=1 ttl=119 time=5.825 ms
64 bytes from 8.8.8.8: seq=2 ttl=119 time=8.226 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 5.730/6.593/8.226 ms

/ # ping -c 3 192.168.0.213
PING 192.168.0.213 (192.168.0.213): 56 data bytes
64 bytes from 192.168.0.213: seq=0 ttl=64 time=0.363 ms
64 bytes from 192.168.0.213: seq=1 ttl=64 time=0.258 ms
64 bytes from 192.168.0.213: seq=2 ttl=64 time=0.221 ms

--- 192.168.0.213 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.221/0.280/0.363 ms

/ # ping -c 3 192.168.0.14
PING 192.168.0.14 (192.168.0.14): 56 data bytes

--- 192.168.0.14 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss

最後の 192.168.0.14 は docker のホストです.これも予想した通り,

  • ホストの所属するネットワーク経由でインターネットのホスト(8.8.8.8)と通信できる.
  • macvlan を利用するコンテナと通信できる.
  • docker のホストとは通信できない(macvlan の制限事項).

となっています.

ナルホド.かなり素直な感じですね.

以上!

NetworksServer
スポンサーリンク
Following hyt!
hyt adversaria
タイトルとURLをコピーしました