SocketPlaneでマルチホストのコンテナ間ネットワークを作ってみる

May 25, 2015   #docker  #socketplane  #network 

SocketPlaneとは、マルチホストのコンテナ間通信をOpen vSwitchで実現するソフトウェアです。 開発元のSocketPlane, Inc.は2015年3月にDocker, Inc.に買収されました。 ちょっと今更感を感じつつ、さわってみることにします。

公式サイト:SocketPlane: Home
GitHubリポジトリ:socketplane/socketplane

公式のREADME.mdによると、特徴は下記の通りです。

  • Open vSwitch integration
  • ZeroConf multi-host networking for Docker
  • Elastic growth of a Docker/SocketPlane cluster
  • Support for multiple networks
  • Distributed IP Address Management (IPAM)

Open vSwitch(OVS)を使う点と自動クラスタ形成が特徴的ですかね。 Weaveと違って、SocketPlaneはdocker0をOVSに置き換えるようなイメージで動きます。

どんな感じで動くのかは、Issue #8951 docker/dockerを読むのがおすすめです。

構成

ホストはUbuntuで動かします。 どうやらUbuntuとFedoraしか対応してないっぽいです。

EC2で、AMIはUbuntu Server 14.04 LTS (HVM), SSD Volume Type - ami-936d9d93を使いました。

構成はWeaveの時と同じく、Dockerホスト3台で試します。

  • ホストA: 172.31.22.4 /16
    • コンテナa1(ubuntu): 10.0.1.x /24
    • コンテナa2(ubuntu): 10.0.2.x /24
  • ホストB: 172.31.22.216 /16
    • コンテナb1(ubuntu): 10.0.1.x /24
    • コンテナb2(ubuntu): 10.0.2.x /24
  • ホストC: 172.31.31.120 /16
    • コンテナc1(ubuntu): 10.0.1.x /24
    • コンテナc2(ubuntu): 10.0.2.x /24

※コンテナのIPは動的にアサインされます

インストール

socketplane/README.mdで書かれているNon-Vagrant install/deployの手順でインストールします。

ホストAにインストール

下記のコマンドでインストールできます。

curl -sSL http://get.socketplane.io | sudo BOOTSTRAP=true sh

SocketPlaneのバージョンはv0.1です。

sudo socketplane help
VERSION:
    0.1

Dockerはv1.6.2が入りました。

sudo docker version
Client version: 1.6.2

コンテナは2つ立ち上がってます。

sudo docker ps
CONTAINER ID        IMAGE                            COMMAND                CREATED             STATUS              PORTS               NAMES
482fa886c540        clusterhq/powerstrip:v0.0.1      "twistd -noy powerst   5 minutes ago       Up 5 minutes                            powerstrip
174c949bff01        socketplane/socketplane:latest   "socketplane --iface   6 minutes ago       Up 6 minutes                            socketplane

インターフェースはdocker0に加え、docker0-ovsが追加されています。

ifconfig
docker0   Link encap:Ethernet  HWaddr 56:84:7a:fe:97:99
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

docker0-ovs Link encap:Ethernet  HWaddr 8e:31:bc:10:3f:4e
          inet6 addr: fe80::ecaf:60ff:fe32:29d8/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:47 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2598 (2.5 KB)  TX bytes:648 (648.0 B)

ホストBとCにインストール

2台目からは下記のコマンドでインストールします。

curl -sSL http://get.socketplane.io | sudo sh

クラスタを組む

通常であれば、SocketPlaneのノードはBonjour(mDNS)を使って他ノードを検出し、自動的にクラスタを組みます。 今回のAWSではマルチキャストが使えないため、手動でクラスタを組みます。

ホストAでjoinを待ち受ける

socketplane cluster bindで他ホストと繋がっているインターフェースを指定します。

sudo socketplane cluster bind eth0
Requesting SocketPlane to listen on eth0

ホストBとCからjoinを送る

socketplane cluster joinでホストAのIPを指定します。

sudo socketplane cluster join 172.31.22.4
Requesting SocketPlane to join the cluster at 172.31.22.4

クラスタの確認

socketplane agent logsで下記のログが出ればOKです。

2015/05/25 03:40:10 [INFO] serf: EventMemberJoin: ip-172-31-22-216 172.31.22.216
2015/05/25 03:40:10 [INFO] consul: member 'ip-172-31-22-216' joined, marking health alive
INFO[1989] New Node joined the cluster : 172.31.22.216
2015/05/25 03:41:00 [INFO] serf: EventMemberJoin: ip-172-31-31-120 172.31.31.120
2015/05/25 03:41:00 [INFO] consul: member 'ip-172-31-31-120' joined, marking health alive
INFO[2039] New Node joined the cluster : 172.31.31.120

しかし、ログ以外で確認する方法はあるんだろうか…

ネットワークを作る

ホストAでコンテナが繋がるネットワークを2つ作ります。 ホストBとCは、正しくクラスタが組めていれば同期してくれます。

sudo socketplane network create net1 10.0.1.0/24
{
    "gateway": "10.0.1.1",
    "id": "net1",
    "subnet": "10.0.1.0/24",
    "vlan": 2
}
sudo socketplane network create net2 10.0.2.0/24
{
    "gateway": "10.0.2.1",
    "id": "net2",
    "subnet": "10.0.2.0/24",
    "vlan": 3
}

vlan番号が2から始まってますが、1は既にデフォルトのネットワークに採番されています。 socketplane network listでネットワークの一覧を表示できます。

sudo socketplane network list
[
    {
        "gateway": "10.1.0.1",
        "id": "default",
        "subnet": "10.1.0.0/16",
        "vlan": 1
    },
    {
        "gateway": "10.0.1.1",
        "id": "net1",
        "subnet": "10.0.1.0/24",
        "vlan": 2
    },
    {
        "gateway": "10.0.2.1",
        "id": "net2",
        "subnet": "10.0.2.0/24",
        "vlan": 3
    }
]

gatewayのIPはホストAが持っています。 ifconfigで見ると、ネットワーク名と同じ名前のインターフェースが作成されています。

ifconfig
default   Link encap:Ethernet  HWaddr 56:a7:26:72:bf:93
          inet addr:10.1.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::54a7:26ff:fe72:bf93/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1440  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:239 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:12286 (12.2 KB)

net1      Link encap:Ethernet  HWaddr de:93:31:5c:af:b5
          inet addr:10.0.1.1  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::dc93:31ff:fe5c:afb5/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1440  Metric:1
          RX packets:11 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:906 (906.0 B)  TX bytes:648 (648.0 B)

net2      Link encap:Ethernet  HWaddr b2:bd:47:ce:f0:d7
          inet addr:10.0.2.1  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::b0bd:47ff:fece:f0d7/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1440  Metric:1
          RX packets:11 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:906 (906.0 B)  TX bytes:648 (648.0 B)

コンテナを立ち上げる

コンテナを作るには、socketplane runを使います。 基本的にdocker runと同じ使い方ですが、先ほど作成したネットワーク名を指定します。

ホストA:

sudo socketplane run -n net1 -itd --name a1 ubuntu
sudo socketplane run -n net2 -itd --name a2 ubuntu

ホストB:

sudo socketplane run -n net1 -itd --name b1 ubuntu
sudo socketplane run -n net2 -itd --name b2 ubuntu

ホストC:

sudo socketplane run -n net1 -itd --name c1 ubuntu
sudo socketplane run -n net2 -itd --name c2 ubuntu

a1コンテナでネットワークの状態を見てます。

sudo docker attach a1
ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

ovsa5c831d Link encap:Ethernet  HWaddr 02:42:0a:00:01:02
          inet addr:10.0.1.2  Bcast:0.0.0.0  Mask:255.255.255.0
          inet6 addr: fe80::ce5:61ff:fe0e:6483/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1440  Metric:1
          RX packets:24 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2064 (2.0 KB)  TX bytes:906 (906.0 B)

指定したネットワークで動的にIPがアサインされているようです。 また、docker0に繋がるインターフェースが存在しません。

a1から他のコンテナにPingしてみます。

b1(ホストB上の同セグコンテナ)宛:

ping -c 2 10.0.1.3
PING 10.0.1.3 (10.0.1.3) 56(84) bytes of data.
64 bytes from 10.0.1.3: icmp_seq=1 ttl=64 time=1.46 ms
64 bytes from 10.0.1.3: icmp_seq=2 ttl=64 time=1.04 ms

--- 10.0.1.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 1.045/1.253/1.461/0.208 ms

c2(ホストC上の別セグコンテナ)宛:

ping -c 2 10.0.2.4
PING 10.0.2.4 (10.0.2.4) 56(84) bytes of data.
64 bytes from 10.0.2.4: icmp_seq=1 ttl=63 time=0.954 ms
64 bytes from 10.0.2.4: icmp_seq=2 ttl=63 time=0.463 ms

--- 10.0.2.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.463/0.708/0.954/0.246 ms

同じセグメントはもちろん、異なるセグメントに対してもマルチホストで通信できています。

ホストAをダウンさせてみる

ホストAを停止させてみたところ、残念ながら他のコンテナにPingが届かなくなりました。 ホストAで持っていたnet1net2が他のホストに動いていないですね。

ホストBで新しくコンテナを立てても、スタンドアロンで作られてしまいます。

sudo socketplane run -n net2 -itd --name b3 ubuntu
sudo docker attach b3
ifconfig
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

何か上手いことやる方法があるのかな?