designetwork

ネットワークを軸としたIT技術メモ

Dockerコンテナを外部ネットワークとVLAN Tag接続する

ネットワークの疎通確認・経路確認などのテストにDockerコンテナを活用する方式を検討している。テストの際に大量のPCを用意するのは非効率なため、軽量・スピーディなDockerコンテナを活用していきたい。

イメージしている構成は以下の通り。802.1Q VLANタグでホストNICを分離して、各VLAN(セグメント)にDockerコンテナをぶら下げて、相互にPing・Tracerouteにより疎通確認・経路確認ができるようにする。

最終的には、以下のような一連の作業をタスク化し、ネットワークテスト自動化環境を構築したい。

  • VLAN Tagネットワーク生成
  • コンテナ起動
  • テスト実行
  • 結果評価

参考にした情報

要素技術として以下の情報を参考にさせていただきました。ありがとうございます。

前提環境

vSphereのスタンドアロン環境で、NICIntel ProなどVLANトランク対応していれば問題なし。標準vSwitchのポートグループでVLANトランクを選択して全VLANを802.1Qタグ付きで通している。また、無差別モード(Promiscuous)を有効にしている。

ゲストOS

CentOSでDockerをインストールして使用する。Dockerが動けば問題なし。Docker構築手順は割愛。

  • CentOS Linux release 7.4.1708 (Core)
  • Docker version 1.13.1, build 774336d/1.13.1
  • docker-compose version 1.21.0, build 5920eb0

環境構築

冒頭の図のような環境を構築する。

Dockerネットワーク作成

MACVLANドライバを指定してDockerネットワークを作成する。parentのens192部分は環境に合わせる。

$ docker network create -d macvlan \
    --subnet=192.168.20.0/24 \
    --gateway=192.168.20.1 \
    -o parent=ens192.20 vlan20

$ docker network create -d macvlan \
    --subnet=192.168.30.0/24 \
    --gateway=192.168.30.1 \
    -o parent=ens192.30 vlan30

Dockerネットワークが作成された。

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
61b2b0b3706c        bridge              bridge              local
e14ebf55d626        host                host                local
112dc8a40c20        none                null                local
cacbb0f62e7e        vlan20              macvlan             local
554515e7aa1a        vlan30              macvlan             local

$ docker network inspect vlan20
[
    {
        "Name": "vlan20",
        "Id": "cacbb0f62e7e971c34f9a556e153c367d81ca23eb7d22a2fce8ce35920f031d9",
        "Created": "2018-05-01T23:33:01.063894797-04:00",
        "Scope": "local",
        "Driver": "macvlan",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.20.0/24",
                    "Gateway": "192.168.20.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {},
        "Options": {
            "parent": "ens192.20"
        },
        "Labels": {}
    }
]

$ docker network inspect vlan30
[
    {
        "Name": "vlan30",
        "Id": "554515e7aa1ad11d7df178ce3b6244f087cecf7ca19bb3792915f4f9f7f73de9",
        "Created": "2018-05-01T23:33:03.007612901-04:00",
        "Scope": "local",
        "Driver": "macvlan",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.30.0/24",
                    "Gateway": "192.168.30.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {},
        "Options": {
            "parent": "ens192.30"
        },
        "Labels": {}
    }
]

DockerホストのCentOSのネットワークは以下のような状態になっている。(抜粋)

$ ip a
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:3a:4c:62 brd ff:ff:ff:ff:ff:ff
4: ens192.10@ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    link/ether 00:0c:29:3a:4c:62 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.80/24 brd 192.168.1.255 scope global ens192.10
       valid_lft forever preferred_lft forever
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
    link/ether 02:42:a6:4a:5b:fe brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:a6ff:fe4a:5bfe/64 scope link
       valid_lft forever preferred_lft forever
19: ens192.20@ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 00:0c:29:3a:4c:62 brd ff:ff:ff:ff:ff:ff
20: ens192.30@ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 00:0c:29:3a:4c:62 brd ff:ff:ff:ff:ff:ff

Dockerコンテナ作成

作成したネットワーク、IPアドレスを指定してコンテナを作成する。Ping・Tracerouteができればよいので、Alpineを使用する。WARNINGが出るが今回は無視する。

$ docker run -it -d --rm \
    --net=vlan20 \
    --ip=192.168.20.201 \
    --name container-vlan20 \
    alpine /bin/sh

WARNING: IPv4 forwarding is disabled. Networking will not work.
4b5dd6ab28bdaa49b8a64221177b942a3754ae058854081318b14f6e79b9e038

$ docker run -it -d --rm \
    --net=vlan30 \
    --ip=192.168.30.201 \
    --name container-vlan30 \
    alpine /bin/sh

WARNING: IPv4 forwarding is disabled. Networking will not work.
c68efffc09fffb01f44054293bb71213db3f7fb7c72f85300771a5aa11cabb64

コンテナが作成された。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c68efffc09ff        alpine              "/bin/sh"           3 seconds ago       Up 2 seconds                            container-vlan30
4b5dd6ab28bd        alpine              "/bin/sh"           43 seconds ago      Up 43 seconds                           container-vlan20

動作確認

それぞれのコンテナから疎通確認する。

$ docker exec -it container-vlan20 /bin/sh

/ # ip a
23: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether 02:42:c0:a8:14:c9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.20.201/24 scope global eth0
       valid_lft forever preferred_lft forever

/ # ping 192.168.20.1
PING 192.168.20.1 (192.168.20.1): 56 data bytes
64 bytes from 192.168.20.1: seq=0 ttl=64 time=1.201 ms
64 bytes from 192.168.20.1: seq=1 ttl=64 time=0.295 ms

/ # ping 192.168.30.201
PING 192.168.30.201 (192.168.30.201): 56 data bytes
64 bytes from 192.168.30.201: seq=0 ttl=63 time=23.294 ms
64 bytes from 192.168.30.201: seq=1 ttl=63 time=0.521 ms

/ # traceroute 192.168.30.201
traceroute to 192.168.30.201 (192.168.30.201), 30 hops max, 46 byte packets
 1  192.168.20.1 (192.168.20.1)  0.343 ms  0.157 ms  0.251 ms
 2  192.168.30.201 (192.168.30.201)  0.323 ms  0.294 ms  0.238 ms

逆側からも疎通・経路確認。

$ docker exec -it container-vlan30 /bin/sh

/ # ip a
24: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UNKNOWN
    link/ether 02:42:c0:a8:1e:c9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.30.201/24 scope global eth0
       valid_lft forever preferred_lft forever

/ # ping 192.168.30.1
PING 192.168.30.1 (192.168.30.1): 56 data bytes
64 bytes from 192.168.30.1: seq=0 ttl=64 time=0.281 ms
64 bytes from 192.168.30.1: seq=1 ttl=64 time=0.293 ms

/ # ping 192.168.20.201
PING 192.168.20.201 (192.168.20.201): 56 data bytes
64 bytes from 192.168.20.201: seq=0 ttl=63 time=0.392 ms
64 bytes from 192.168.20.201: seq=1 ttl=63 time=0.444 ms

/ # traceroute 192.168.20.201
traceroute to 192.168.20.201 (192.168.20.201), 30 hops max, 46 byte packets
 1  192.168.30.1 (192.168.30.1)  0.240 ms  0.176 ms  0.303 ms
 2  192.168.20.201 (192.168.20.201)  0.463 ms  0.216 ms  0.306 ms
/ #

SUCCEEDED!! 期待通り相互に疎通確認・経路確認ができている。Tracerouteの結果からわかる通り、ホストNICはVLANタグを透過して、外部ルータでVLAN間ルーティングされている。

まとめ - Dockerコンテナを外部ネットワークとVLAN Tag接続する

DockerのMACVLANネットワークドライバをすることで、Dockerコンテナを外部ネットワークと802.1Q VLAN Tag接続することができた。Dockerコンテナを活用することで、ネットワークのテストのために大量のPCを用意する必要がなくなる。

(追記) Docker-Composeはこちら

本記事と同内容をDocker-Composeで実装しました。

designetwork.hatenablog.com