docker
etcd

etcdクラスタを組んでdockerのオーバレイネットワークを手動構築

More than 1 year has passed since last update.

わりと今更ですが初心者で何がセオリーなのかもよくわからず右往左往しつつ調べながらなんとなくできたので備忘録を。

なんでetcdかというと好みの問題というかDocker社がkubernetesデフォルトにするとかなんとかの話をみかけたのとswarmよりはシンプルかなと思ったため。(現時点だと公式サイトのマニュアルはetcdじゃなくてConsulだったりなど)
なんでそれをしたかったかというとrancherをHAでたてるために要るのかなってだけでした。kubernetes on rancher on kubernetesみたいな意味わかんないことになるのもどうなのかと思って一応シンプルにしたかったというか。
初心者なのでよくわかっていませんのでツッコミがあればコメントをください。

etcdと種類

分散KVSの一種。
設定ファイルにクラスタ構成情報を書いとくタイプのスタティックと自律的に見つけ出す感じのディスカバリーという方式を把握しており、残念ながらstaticには成功しなかったのでディスカバリーの方法だけ書きます。

etcdのインストール

環境 Ubuntu16LTS

# apt-get install etcd
# curl https://discovery.etcd.io/new?size=2  ##discoveryに出てきた値を指定
# systemctl edit etcd.service
# vi /etc/systemd/system/etcd.service.d/override.conf 

### **host01**
ExecStart=
ExecStart=/usr/bin/etcd --data-dir=/var/lib/etcd/test --name host01 --initial-advertise-peer-urls http://10.0.0.4:2380 --listen-peer-urls http://10.0.0.4:2380 --advertise-client-urls http://10.0.0.4:2379 --listen-client-urls http://10.0.0.4:2379 --discovery https://discovery.etcd.io/c60fc6c755455369b8452b7d441***** --initial-cluster-state new --initial-cluster-token etcd-cluster-1

### **host02**
ExecStart=
ExecStart=/usr/bin/etcd --data-dir=/var/lib/etcd/test --name host02 --initial-advertise-peer-urls http://10.0.2.5:2380 --listen-peer-urls http://10.0.2.5:2380 --advertise-client-urls http://10.0.2.5:2379 --listen-client-urls http://10.0.2.5:2379 --discovery https://discovery.etcd.io/c60fc6c755455369b8452b7d44***** --initial-cluster-state new --initial-cluster-token etcd-cluster-1

# systemctl daemon-reload
# systemctl restart etcd.service
# systemctl status etcd.service
# journalctl -xe -u etcd.service

etcのしたの設定ファイル編集してもよかったのですがプロセスみた時に設定値が出なくてわかりづらかったのでsystemdのユニットファイルに差分書きました。

etcdクラスタの確認
# export ENDPOINTS='10.0.0.4:2379,10.0.2.5:2379'
# echo $ENDPOINTS
10.0.0.4:2379,10.0.2.5:2379
# etcdctl --endpoint=$ENDPOINTS member list
4f773599dea3d130: name=host01 peerURLs=http://10.0.0.4:2380 clientURLs=http://10.0.0.4:2379
8155bbd84f4a1316: name=host02 peerURLs=http://10.0.2.5:2380 clientURLs=http://10.0.2.5:2379

# etcdctl --endpoint=$ENDPOINTS cluster-health
member 4f773599dea3d130 is healthy: got healthy result from http://10.0.0.4:2379
member 8155bbd84f4a1316 is healthy: got healthy result from http://10.0.2.5:2379
cluster is healthy

なんかポート開いてないかも?な確認方法

# dpkg -l |grep ufw
ii  ufw                                 0.35-0ubuntu2                              all          program for managing a Netfilter firewall
#  ufw status numbered
Status: inactive
# iptables -nL

host02:~# netstat -lnpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      2058/sshd       
tcp        0      0 127.0.0.1:25225         0.0.0.0:*               LISTEN      38161/ruby      
tcp        0      0 10.0.2.5:2379           0.0.0.0:*               LISTEN      71228/etcd      
tcp        0      0 10.0.2.5:2380           0.0.0.0:*               LISTEN      71228/etcd      
tcp        0      0 0.0.0.0:25324           0.0.0.0:*               LISTEN      38161/ruby      
tcp6       0      0 :::22                   :::*                    LISTEN      2058/sshd       

host01:~# nc -vz 10.0.2.5 2379
Connection to 10.0.2.5 2379 port [tcp/*] succeeded!
host01:~# nc -vz 10.0.2.5 2380
Connection to 10.0.2.5 2380 port [tcp/*] succeeded!

なんか書いてみてクラスタのそれぞれから見えることを確認

host01:~# etcdctl --endpoint=$ENDPOINTS set os linux
linux
host01:~# etcdctl --endpoint=$ENDPOINTS get os 
linux

host02:~# etcdctl --endpoint=$ENDPOINTS get os 
linux
dockerにetcdのエンドポイントを設定する
# ps -ef|grep docker
root     128373      1  1 04:59 ?        00:00:00 /usr/bin/dockerd -H fd://
root     128377 128373  0 04:59 ?        00:00:00 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc

# grep -i -A 2 execstart /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd://
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=1048576

## なんとなくリンクを貼っておいた。
# ln -s /lib/systemd/system/docker.service /etc/systemd/system/docker.service
# ls -lh /etc/systemd/system/docker.service 
lrwxrwxrwx 1 root root 34 Nov 22 17:57 /etc/systemd/system/docker.service -> /lib/systemd/system/docker.service

## 起動オプションについて追加が必要。
## (--cluster-advertiseと--cluster-store)
## /lib/systemd/system/docker.serviceを見る限り/etc/default/dockerに設定追加してもExecStartには影響しなさそう。
##  あんま意味なさそうなのでしない。
##  cp -p /etc/default/docker{,.org}
##  vi /etc/default/docker

# systemctl edit docker.service
## nano編集めんどうなのでとりあえず抜ける
# vi /etc/systemd/system/docker.service.d/override.conf 
# cat /etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock -H fd:// --cluster-advertise eth0:2375 --cluster-store etcd://10.0.0.4:2379

# systemctl daemon-reload
# systemctl restart docker

overlayネットワークを作成する
# docker network create --driver overlay --subnet 192.168.0.0/24 common_link
# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
d6c23310b593        bridge              bridge              local
ab6a75885c46        common_link         overlay             global
d981e6f5b649        host                host                local
992edac84635        none                null                local
# docker network inspect common_link

# etcdctl --endpoint=$ENDPOINTS ls docker/network/v1.0/overlay/network
# etcdctl --endpoint=$ENDPOINTS get /docker/network/v1.0/overlay/network/60b8c3d9e8e847246e96f291effeabf06a67783e9fa15c6e1c54038c939cbd05
{"mtu":0,"secure":false,"subnets":[{"SubnetIP":"192.168.0.0/24","GwIP":"192.168.0.1/24","Vni":0}]}

etcdをcluster-storeとしてエンドポイント指定したすべてのホストでoverlayが見えることを確認する。overlayネットワーク指定でコンテナを作るとコンテナにIPが振られている様子がわかる。

docker-compose.ymlかなんかにoverlayネットワークを指定する
~略~
networks:
  default:
    external:
      name: common_link

こんな感じで名前を指定すればよく特に何か変える必要はなさそうだった。

etcd参考

個人的にもっとも参考になったのは公式サイトのデモです。(ただしubuntuのパッケージだと公式よりバージョン旧く無いオプションも。
人が書いたブログだとプラットフォームやバージョンと時期と方式と色々背景によってやってることが違ったりなど。
[入門編]etcdでクラスタを構築する - Qiita
etcdクラスタ構築(static方式) - Qiita
Clustering Guide
etcd/demo.md at master · coreos/etcd
忘れるためのメモ: kubernetesをRaspberry pi 3にインストールする(その2)

docker参考

具体的な手順がプラットフォームや時期によって多岐というか選べるってめんどくさいと思う次第です。
マルチホスト上での、dockerコンテナ間ネットワーク環境整備メモ(Overlay Networking w/ Etcd) - Qiita
マルチホストDockerネットワーキング(etcd+flannel) - Qiita
Dockerのマルチホストネットワークの概要説明と環境構築 – めもたんす(consul)
Kubernetesなしでdockerを複数台で動かしてみる (flannel編) - netmark.jp
Docker1.9のマルチホストネットワーク | Think IT(シンクイット)
containernetworking/cni: Container Network Interface - networking for Linux containers

etcdのはまったとこ

メンバ登録後にデータディレクトリ移動して同じクラスタに登録しようとするとデータがねえぜというようなエラーで起動しないですね。
(そんなおかしなことする人はいないかもしれないけど一応かいときます)
$datadir/memberというフォルダになんか入るようです(もどしたら起動しました)
Endpointを指定しないでetcctlするとよくわかんないポートにつなぎにいこうとしてクラスタ組めてないみたいに見えます
あとはiptablesに変な設定残っててポートが空いてないとだめですね。
static方式は起動コマンド書くのが面倒くさいというかtypoで起動しなかったりなどもしました。
結果的にはdiscoveryのほうが自動的に見つけてきてくれるのでオートスケーリング向きでAnsibleのタスクとか書きやすそうかなと思いました。

以上。