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 runn...

にあります(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 を使う方法は,

Macvlan network driver
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!
タイトルとURLをコピーしました