CoreOS が提供する flannel を使って、複数の CoreOS マシンを跨いで Docker コンテナ同士通信できるようにする、というお話です。
flannel
もともと Kubernates には似たようなホスト間通信機能がついていたのですが、Google Compute Engine (GCE) 上でしか使えないという欠点がありました。これを取り出し、汎用的に使えるようにしたのが flannel です。
また、似た機能を持つものに weave がありますが、weave は導入が少々面倒な上に相手ホストの IP を明示的に指定してあげないといけません。その点 flannel は CoreOS 上での導入が簡単で、相手の IP を知らなくてもよく透過的に利用できるという利点があります。ホストに割り振られる IP が不定である EC2 + VPC 構成でも使いやすいでしょう。
イメージ図はこんな感じです。
(from https://github.com/coreos/flannel/blob/master/packet-01.png)
試してみる
以下で紹介する CoreOS VM を含めたサンプルリポジトリです。あわせてご利用ください:
dtan4/coreos-flannel-sample
cloud-config
まず cloud-config はこんな感じです。flanneld.service というのを定義しています。
#cloud-config
coreos:
etcd:
discovery: https://discovery.etcd.io/<token>
addr: $public_ipv4:4001
peer-addr: $public_ipv4:7001
fleet:
public-ip: $public_ipv4
flannel:
interface: $public_ipv4
units:
- name: etcd.service
command: start
- name: fleet.service
command: start
- name: flanneld.service
drop-ins:
- name: 50-network-config.conf
content: |
[Unit]
Description=flanneld
After=etcd.service
Requires=etcd.service
[Service]
ExecStartPre=/usr/bin/etcdctl set /coreos.com/network/config '{ "Network": "10.1.0.0/16" }'
command: start
- name: docker-tcp.socket
command: start
enable: true
# After(Requires)=flanneld.service を忘れないこと!
content: |
[Unit]
Description=Docker Socket for the API
After=flanneld.service
Requires=flanneld.service
[Socket]
ListenStream=2375
Service=docker.service
BindIPv6Only=both
[Install]
WantedBy=sockets.target
注意すべきは、unit の起動順序を etcd -> flannel -> docker とする必要があることです。flannel は etcd にマッピング情報を配置し、Docker は flannel が構築したネットワークの上で動作するためです。
余談ですが、flanneld.service は初回起動時に flannel の Docker イメージを pull してきます。docker.service が起動してないのに変ですね。
これは、flanneld.service の中で独自に Docker (early-docker.service) を起動することで実現しています。
詳しくは Configuring flannel Networking の "Under the Hood" を読んでください。
起動
CoreOS クラスタを立ち上げます。サンプルリポジトリだと2台の CoreOS VM (core-01, core-02) が起動します。
$ vagrant up
立ち上がったらもうひとつターミナルを開き、それぞれのマシンにログインします。
$ vagrant ssh core-01
$ vagrant ssh core-02
両方の VM 上で bash コンテナを立ち上げ、コンテナに割り振られた IP アドレスを確認します(Ubuntu イメージを pull するので多少時間がかかります)。
core@core-01$ docker run -it --rm ubuntu /bin/bash
# 略
root@a46062460b1e:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
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
8: eth0: <BROADCAST,UP,LOWER_UP> mtu 1472 qdisc noqueue state UP group default
link/ether 02:42:0a:01:0f:03 brd ff:ff:ff:ff:ff:ff
inet 10.1.15.3/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:aff:fe01:f03/64 scope link
valid_lft forever preferred_lft forever
core@core-02$ docker run -it --rm ubuntu /bin/bash
# 略
root@686f6558b05c:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
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
8: eth0: <BROADCAST,UP,LOWER_UP> mtu 1472 qdisc noqueue state UP group default
link/ether 02:42:0a:01:51:03 brd ff:ff:ff:ff:ff:ff
inet 10.1.81.3/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:aff:fe01:5103/64 scope link
valid_lft forever preferred_lft forever
core-01 上の bash コンテナには 10.1.15.3
、core-02 上の bash コンテナには 10.1.81.34
が割り当てられています。
では、それぞれのコンテナからもう一方のマシン上のコンテナに ping
を打ってみます。
root@a46062460b1e:/# ping -c 5 10.1.81.3
PING 10.1.81.3 (10.1.81.3) 56(84) bytes of data.
64 bytes from 10.1.81.3: icmp_seq=1 ttl=60 time=0.794 ms
64 bytes from 10.1.81.3: icmp_seq=2 ttl=60 time=0.772 ms
64 bytes from 10.1.81.3: icmp_seq=3 ttl=60 time=1.37 ms
64 bytes from 10.1.81.3: icmp_seq=4 ttl=60 time=1.14 ms
64 bytes from 10.1.81.3: icmp_seq=5 ttl=60 time=1.15 ms
--- 10.1.81.3 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4003ms
rtt min/avg/max/mdev = 0.772/1.048/1.378/0.234 ms
root@686f6558b05c:/# ping -c 5 10.1.15.3
PING 10.1.15.3 (10.1.15.3) 56(84) bytes of data.
64 bytes from 10.1.15.3: icmp_seq=1 ttl=60 time=0.868 ms
64 bytes from 10.1.15.3: icmp_seq=2 ttl=60 time=1.38 ms
64 bytes from 10.1.15.3: icmp_seq=3 ttl=60 time=1.59 ms
64 bytes from 10.1.15.3: icmp_seq=4 ttl=60 time=2.06 ms
64 bytes from 10.1.15.3: icmp_seq=5 ttl=60 time=1.05 ms
--- 10.1.15.3 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4011ms
rtt min/avg/max/mdev = 0.868/1.391/2.065/0.423 ms
お互い、相手ホストのコンテナへの疎通確認ができました。めでたいですね
以上が flannel を使った複数ホスト間コンテナ通信の例でした。
注意点
flannel は マルチキャストパケットを通さない ので、例えば Elasticsearch の multicast discovery といったものは使えません。ユニキャストは通るのでなんとかして頑張りましょう。
REF
-
coreos/flannel
- flannel 公式リポジトリ
-
Introducing flannel: An etcd backed overlay network for containers
- CoreOS に flannel が導入されたよ記事
-
Configuring flannel Networking
- CoreOS 上で flannel を設定する方法
- Dockerコンテナ接続パターン (2014年冬) | SOTA