##概要
docker 1.9.0がリリースされ、docker networkコマンドがproductionでも使えるようになりました。特にマルチホストでのコンテナネットワークがdockerコマンドから作成可能になったので試してみました。
##docker network
コマンドとは
docker network
はコンテナに接続するネットワークを操作・管理するコマンド。
Docker Swarmと連携すればマルチホスト環境でも、コンテナ間でoverlayネットワークを構築してコンテナ間が通信できる。
マルチホストのコンテナネットワークを実現するツールや方法は他にもいろいろある。weave
、etcd+flannel
、runcher
、bridge接続+GRE
などなど。
環境
今回は2つのDockerホストVMをSwarmでクラスタ化し、docker networkコマンドでoverlayネットワークを構築して、マルチホストでのコンテナ通信ができるかを試しました。
あとdocker networkコマンドによるoverlayネットワークはLinux Kernel 3.16以上が必要になります。CentOS7は3.10なので、3.18をビルドしてインストールしています。(kernelビルド部分は省略)Ubuntu 14.10のカーネルは3.16なので、Ubuntuで試せばよかった。
- CentOS7(VM) x2台
- docker01 :192.168.11.48 (consul server)
- docker02 :192.168.11.49 (consul client)
- Linux Kernel 3.18
- Docker 1.9.0
- Docker Swarm 1.0
- consul 0.5.2(Docker SwarmのバックエンドKVS)
やったこと目次
- consulのインストール・設定
- Docker1.9.0のインストール・設定
- Docker Swarmでクラスタ化
- overlay networkの作成
- コンテナにネットワークを接続して起動
- コンテナ間の疎通確認
consulインストール・設定
インストール
バイナリファイルをダウンロードして配置するだけ。合わせて必要な設定ファイル、ディレクトリを作成します。
$ wget https://releases.hashicorp.com/consul/0.5.2/consul_0.5.2_linux_amd64.zip
$ unzip consul_0.5.2_linux_amd64.zip
$ sudo cp consul /usr/local/bin/
$ sudo mkdir -p {/etc/consul,/var/lib/consul,/var/log/consul}
consul設定
consulの設定ファイルをserverとclientの2種類作成します。
docker01(consul server)
{
"datacenter": "docker",
"addresses" : {
"http": "0.0.0.0"
},
"bind_addr": "192.168.11.48",
"node_name": "docker01",
"domain": "consul",
"server": true,
"bootstrap_expect": 1,
"data_dir": "/var/lib/consul"
}
docker02(consul client)
{
"datacenter": "docker",
"addresses" : {
"http": "0.0.0.0"
},
"bind_addr": "192.168.11.49",
"node_name": "docker02",
"domain": "consul",
"retry_join": [ "192.168.11.48"],
"server": false,
"data_dir": "/var/lib/consul"
}
consul起動
$ consul -config-file=/etc/consul/consul.json >> /var/log/consul/consul.log &
$ consul members
Node Address Status Type Build Protocol DC
docker02 192.168.11.49:8301 alive client 0.5.2 2 docker
docker01 192.168.11.48:8301 alive server 0.5.2 2 docker
ちゃんとconsulクラスタにdocker01,02がいますね。
Docker 1.9.0インストール・設定
インストール
CentOS7はまだyumにあるdockerが1.8.2なので(2015/11/9現在)、最新のバイナリをダウンロードして挿し替えています。
$ sudo yum install -y docker
$ curl -o docker-1.9.0 https://get.docker.com/builds/Linux/x86_64/docker-1.9.0
$ sudo cp docker-1.9.0 /usr/bin/docker
$ sudo chmod +x /usr/bin/docker
Docker Engine設定
docker daemonの--cluster-store
--cluster-advertise
オプションを設定して起動します。それぞれKVSのアドレス、ホスト自身のipaddress:port
を設定します。
OPTIONS='--cluster-store=consul://localhost:8500 --cluster-advertise=<ホストIP>:2376 -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock'
Docker起動
$ sudo systemctl start docker
Docker Swarmクラスタ起動
docker01のホストでSwarmのクラスタマネージャコンテナを起動します。
$ docker run -d -p 2377:2375 --name swarm-manage-consul swarm manage consul://192.168.11.48:8500/docker
各ホストでSwarmクラスタへjoinするためのswarmコンテナを起動します。docker
コマンドがswarmマネージャコンテナに向けて実行できればOKです。
# docker01
$ docker run -d --name swarm-join swarm join --advertise=192.168.11.48:2375 consul://192.168.11.48:8500/docker
# docker02
$ docker run -d --name swarm-join swarm join --advertise=192.168.11.49:2375 consul://192.168.11.48:8500/docker
$ docker -H tcp://192.168.11.48:2377 info
Containers: 3
Images: 4
Role: primary
Strategy: spread
Filters: health, port, dependency, affinity, constraint
Nodes: 2
centos7-01: 192.168.11.48:2375
└ Containers: 2
└ Reserved CPUs: 0 / 2
└ Reserved Memory: 0 B / 2.052 GiB
└ Labels: executiondriver=native-0.2, kernelversion=3.18.22, operatingsystem=CentOS Linux 7 (Core), storagedriver=overlay
centos7-02: 192.168.11.49:2375
└ Containers: 1
└ Reserved CPUs: 0 / 2
└ Reserved Memory: 0 B / 2.052 GiB
└ Labels: executiondriver=native-0.2, kernelversion=3.18.22, operatingsystem=CentOS Linux 7 (Core), storagedriver=overlay
CPUs: 4
Total Memory: 4.103 GiB
Name: 755cb58b105c
ここまででdocker network
コマンドでoverlayネットワークを作成する準備ができました。いよいよ次はoverlayネットワーク作成します。
overlay networkの作成
docker network create
コマンドでoverlayネットワークを作成します。
1つのホストで作成したvn01のネットワーク設定はクラスタの全ホストで共有されます。docker inspect
コマンドで作成したコンテナネットワーク情報が見れます。
# docker01
$ docker network ls
NETWORK ID NAME DRIVER
6f9ee8d629d6 none null
0f0d0f12a59f host host
12613b8ef4b7 docker_gwbridge bridge
0ac1dafaa764 bridge bridge
$ docker network create -d overlay vn01
b07f8c4a5cb954e7ff8d387bfc65e3239f67852ee65f68cea8d77e9032b577c5
$ docker network ls
NETWORK ID NAME DRIVER
b07f8c4a5cb9 vn01 overlay
0ac1dafaa764 bridge bridge
6f9ee8d629d6 none null
0f0d0f12a59f host host
12613b8ef4b7 docker_gwbridge bridge
$ docker network inspect vn01
[
{
"Name": "vn01",
"Id": "b07f8c4a5cb954e7ff8d387bfc65e3239f67852ee65f68cea8d77e9032b577c5",
"Scope": "global",
"Driver": "overlay",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {},
"Options": {}
}
]
# docker02
$ docker network ls
NETWORK ID NAME DRIVER
b07f8c4a5cb9 vn01 overlay
65a8ead71e7c none null
ebb12613053e host host
02ca2b4c8d98 docker_gwbridge bridge
071afc5c93e3 bridge bridge
コンテナへのネットワーク割り当て
test01コンテナを作って、vn01ネットワークを付与させてみます。
$ docker run -idt --name test01 --hostname test01 centos:7 /bin/bash
$ docker network connect vn01 test01
$ docker exec test01 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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
40: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
43: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP
link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.2/24 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::42:aff:fe00:2/64 scope link
valid_lft forever preferred_lft forever
test01のコンテナのeth1
に10.0.0.2/24
のネットワークが付いてますね。IPアドレスは自動で割り振られるのかな?
コンテナ起動時に--net
オプションを使うことでも付与できるみたいです。
$ docker run -dit --name test01 --hostname test01 --net vn01 centos:7 /bin/bash
同様に別のホストでもvn01を付与したコンテナを起動してネットワークを付与します。
$ docker run -dit --name test02 --hostname test02 centos:7 /bin/bash
$ docker network connect vn01 test02
$ docker exec test02 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
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
39: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
42: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP
link/ether 02:42:0a:00:00:03 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.3/24 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::42:aff:fe00:3/64 scope link
valid_lft forever preferred_lft forever
こっちは10.0.0.3/24
のネットワークがついてますね。
コンテナ間通信
やっとコンテナの疎通確認!test02(10.0.0.3)コンテナからtest01コンテナ(10.0.02)へpingを打ってみます。
$ docker exec test02 ping -c 4 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.991 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.639 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.650 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.664 ms
--- 10.0.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.639/0.736/0.991/0.147 ms
つながりました!
どうやらコンテナ名で名前解決もできるみたい。便利!
$ docker exec test02 ping -c 4 test01
PING test01 (10.0.0.2) 56(84) bytes of data.
64 bytes from test01 (10.0.0.2): icmp_seq=1 ttl=64 time=0.516 ms
64 bytes from test01 (10.0.0.2): icmp_seq=2 ttl=64 time=0.665 ms
64 bytes from test01 (10.0.0.2): icmp_seq=3 ttl=64 time=0.745 ms
64 bytes from test01 (10.0.0.2): icmp_seq=4 ttl=64 time=0.714 ms
--- test01 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 0.516/0.660/0.745/0.087 ms
静的IPは振れない(?)みたいですが、名前解決できるので問題なさそう。
いろいろオプションがあるみたいですがまだ試せていません…。
コンテナネットワークを外部に公開できる機能があれば最高なのになぁ。weave expose
みたいな。まだないのかな?それとも外部接続用コンテナ作ってそこはブリッジ接続かな。
あとは性能がどんなもんかですね。技術的にはvxlanでoverlayネットワークを作成しているみたいですが、そのオーバーヘッドで性能どうなるか私気になります!