ここ一週間ほどDocker周辺ツールをいじっていて、 どうせだからマルチホストネットワークの雰囲気も掴んでおこうと試行錯誤していた今日この頃。
ツールそのものの使い方は把握できたしサクッといけるだろうと高をくくっていたら意外と苦戦してしまった。
結果的にいえば引っかかりどころは
- CentOS7&firewalld環境において自動で開こうとしては失敗するポートを手動で開けておかなければいけない
- Docker ComposeのVersion2フォーマットを把握し、単体でのlink機能から置き換える必要がある
あたりだろうか。
そんなわけで、これまで同様にVagrantで検証環境を用意して試してみた。
前提
以下のような環境を対象とする。
- 既にConsulサーバがネットワーク内で立ち上がっている
- プロビジョニング対象はCentOS7
- あくまでfirewalldを使用する
幸いなことに別件である程度使い慣れていたConsul。
無ければ公式であるようにDockerで立ち上げても良いし、 普通に導入するのもさほど難しくはないだろう。
Docker Machineは本来であれば必要なことを全てお膳立てしてくれるツールなのだが… 残念ながらCentOS7ではそうすんなり行かない。
firewalldを止めてiptablesを使うか、 もしくは予めポートを開けておく必要があるのだ。
非推奨のツールを使い続けるのは気が進まないわけで、 手動でポートを開ける方を選択した。
(もっともDocker Machine自体netstatが必要だったりするわけだけど)
Vagrant
先にも述べたけどCentOS7を対象としてDocker MachineやSwarmを動かすには、 net-toolsをインストールして必要なポートを開ける必要がある。
この必要なポートというのを調べるのが意外と難儀したんだけど、 結果的に言えば
- Docker Engine用に2375/tcp、2376/tcp
- Swarmで他のコンテナとの通信用に4789/udp、7946/tcp、7946/udp
- Swarm Managerを立ち上げるマシンは更に3376/tcp
あたりを開けておけば良い。
その辺りを加味して下記のように検証環境をセッティングした。
Vagrant.configure(2) do |config| config.vm.box = "CentOS7" config.vm.box_url = "https://github.com/holms/vagrant-centos7-box/releases/download/7.1.1503.001/CentOS-7.1.1503-x86_64-netboot.box" config.vm.define "master" do |server| server.vm.network "private_network", ip: "192.168.33.10" server.vm.provision "shell", inline: <<-SHELL sudo firewall-cmd --permanent --add-port=3376/tcp sudo firewall-cmd --reload SHELL end config.vm.define "node1" do |server| server.vm.network "private_network", ip: "192.168.33.11" end config.vm.define "node2" do |server| server.vm.network "private_network", ip: "192.168.33.12" end config.vm.provision "shell", inline: <<-SHELL sudo yum update sudo yum install -y net-tools sudo firewall-cmd --permanent --add-port=2375/tcp --add-port=2376/tcp --add-port=4789/udp --add-port=7946/tcp --add-port=7946/udp sudo firewall-cmd --reload SHELL end
Swarmクラスタ作成
前回同様に192.168.77.6:8500でConsulが動いているという前提で。
マルチホストネットワークのためにengine-opt項が2つほど足されていることに注意。
# master docker-machine create -d generic --generic-ssh-user vagrant --generic-ssh-key ~/cluster/.vagrant/machines/master/virtualbox/private_key --generic-ip-address 192.168.33.10 --swarm --swarm-master --swarm-discovery consul://192.168.77.6:8500 --engine-opt cluster-store=consul://192.168.77.6:8500 --engine-opt cluster-advertise=eth1:2376 master #node1 docker-machine create -d generic --generic-ssh-user vagrant --generic-ssh-key ~/cluster/.vagrant/machines/node1/virtualbox/private_key --generic-ip-address 192.168.33.11 --swarm --swarm-discovery consul://192.168.77.6:8500 --engine-opt cluster-store=consul://192.168.77.6:8500 --engine-opt cluster-advertise=eth1:2376 node1 #node2 docker-machine create -d generic --generic-ssh-user vagrant --generic-ssh-key ~/cluster/.vagrant/machines/node2/virtualbox/private_key --generic-ip-address 192.168.33.12 --swarm --swarm-discovery consul://192.168.77.6:8500 --engine-opt cluster-store=consul://192.168.77.6:8500 --engine-opt cluster-advertise=eth1:2376 node2 #switch eval "$(docker-machine env --shell bash --swarm master)"
Version2フォーマットのdocker-compose.yml
マルチホストネットワークを使うにはVersion2のフォーマットを使うのが良いようだ。
頭にversion: '2'
をつけるのと、
ネットワークはnetworks
項に定義して用いる。
そしてservices
項のそれぞれコンテナのところで定義されたネットワークを指定する。
(もっちょい面白い例を思いつけばよかったんだけど・・・)ひとまずdebianでも動かしてみる。
master
固定のコンテナfront
とnode1
とnode2
用のback
というコンテナを動かしてみる。
environment
項にconstrait:node
を指定することで、コンテナを動かすホストを固定することができる。
version: "2" services: front: image: debian:latest command: tail -f /dev/null environment: - constraint:node==master networks: - test back: image: debian:latest command: tail -f /dev/null environment: - constraint:node==node* networks: - test networks: test: driver: overlay
立ち上げた上でback
を2つに増やしてみる。
docker-compose up -d docker-compose scale back=2 docker ps
意図通りmaster
にfront
コンテナ、node1or2
にback
が収まっている。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4fd7e89b38aa debian:latest "tail -f /dev/null" 7 hours ago Up 3 seconds node2/cluster_back_2 0c28f9134b22 debian:latest "tail -f /dev/null" 8 hours ago Up 2 seconds node1/cluster_back_1 a5b01227e59a debian:latest "tail -f /dev/null" 8 hours ago Up 4 seconds 192.168.33.10:80->80/tcp master/cluster_front_1
master
に入って…
docker-compose exec front bash
ひとまずdigでもインストールしてみてback
という名を引くと接続先のIPがかえってくることが確認できる。
apt-get update && apt-get install -y dnsutils dig back ; <<>> DiG 9.9.5-9+deb8u6-Debian <<>> back ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21661 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;back. IN A ;; ANSWER SECTION: back. 600 IN A 10.0.1.4 back. 600 IN A 10.0.1.3 ;; Query time: 0 msec ;; SERVER: 127.0.0.11#53(127.0.0.11) ;; WHEN: Sun May 29 12:40:31 UTC 2016 ;; MSG SIZE rcvd: 62
実際的な例としてはプロキシ用のコンテナなんかを固定のホストでポート開けて動かしておいて、 そこにスケール可能なアプリケーションサーバを接続していくようなイメージになるだろうか。
この辺りの用例はそのうちやってみようと思うところ。
ちょっと前まではlink機能使った環境変数によるコンテナ間連携が"イケてる方法"だったけど、 それではマルチホスト環境の動的な運用には対応しきれないケースも出てくる。
マルチホストネットワークを見据えた上での非推奨だったわけだ。
単一ホストでVersion1フォーマットでの運用とは感覚的に変わってしまう部分が少なからずあって、 前からDocker Composeを使ってた身とするとちょっと戸惑う面もある。
だが、考えてみればホスト名でIP引いてくる形というのはより一般的なネットの方法論なわけで、 例え単一ホスト環境でもこのような方法とVersion2フォーマットに慣れていった方が良さそうな気がする。