docker-machine -v
docker-machine version 0.7.0, build a650a40
にて。
週末に VirtualBoxドライバでdocker-machineなんかの動作を確認 。
意外なほどサクッと動いてくれたので意気揚々と出社してみたものの、 いざ 会社の環境(CentOS7サーバ群)でGenericドライバを使って動かそうとするとどうにも上手くいかない …
ありがちなところでファイアウォールかと思いfirewalldを止めてみてもダメ、 色々いじった環境だからかと思いクリーンインストール状態のサーバを用意してもらってもダメ。
だが不思議なことに一部のサーバはすんなり動いている。
-Dオプション付けてみてもイマイチ何が引っかかってるのか分からず探し方に問題があったのかググッてもそれらしい情報も見つからずで今週前半はこの問題に頭を悩ませていたのだが、今日ついに解決法に到達!
なんのことはない、CentOS7からは非推奨になりデフォルトでインストールされなくなった net-toolsをyumで入れれば良かった のだ!!
(どうやらdocker-machineが内部的にnetstat使ってるっぽい)
(あと正確には docker-engine用にfirewalldの2376ポートを開ける 必要がある)
ログの情報も断片的だしぐぐってもドンピシャな情報も無かったしで苦労したけど、 ヒントはGithubのissueにあった。英語苦手だけど、こういうことあると勉強しなきゃなーって思わせられるところ。
そんなわけでいうべき内容はもう全部言っちゃったけど、 検証環境づくりとか詳細とか。
Vagrantで検証環境を作成する
実体サーバを用いることを想定し、 VagrantでCentOS7の仮想マシンを用意した上でGenericドライバを用いてクラスタを作る。
Vagrant自体の準備は↓で。
仮想マシンの作成
ディレクトリの準備
ひとまずホームディレクトリ以下に仮想マシン用のディレクトリを用意する。
便宜的にmaster、node1、node2とする。
mkdir swarm{,/master,/node1,/node2} cd swarm tree . ├── master ├── node1 └── node2
BOXの追加
OSイメージをひとまずダウンロードしておく。
vagrant box add CentOS7 https://github.com/holms/vagrant-centos7-box/releases/download/7.1.1503.001/CentOS-7.1.1503-x86_64-netboot.box
ネットワークの準備
masterの準備をする。
cd master vagrant init CentOS7 vim Vagrantfile # private_network項のコメントアウトを外し、任意のIPアドレスに書き換える vagrant up vagrant ssh-config # 項の鍵のパスを確認しておく
node1、node2についても同様の作業を行い、それぞれのIPと鍵のパスをメモっておく。
本記事では下記の値とする。
VM | ipアドレス | 鍵 |
---|---|---|
master | 192.168.33.10 | ~/swarm/master/.vagrant/machines/default/virtualbox/private_key |
node1 | 192.168.33.11 | ~/swarm/node1/.vagrant/machines/default/virtualbox/private_key |
node2 | 192.168.33.12 | ~/swarm/node2/.vagrant/machines/default/virtualbox/private_key |
☆ Docker Machineのための下準備
VMに入ってdocker-machineのための準備をする。
cd master vagrant ssh # 以下VM内での操作 sudo firewall-cmd --permanent --add-port=2376/tcp sudo yum install -y net-tools exit #VMの外に出る
(ここが今回の記事の本題だったんだけど、全体からするとえらいちっちゃい分量…)
同様の操作をnode1、node2についても行う。
Dockerまわり
Docker Machine
いよいよ肝心のDocker Machine。
tokenを使った方法は前回載せたので、今回はネットワーク内のconsulを使用する形で。
httpl://192.168.77.6:8500/ で起動させていて、今回はswarmというキーの下に情報が収まる感じとする。
クラスタの登録
masterをswarm-masterとしてnode1、node2をクラスタとして登録していく。
(若干不安になる程度には時間かかるのでお茶でも飲んで気長にやろう)
docker-machine create -d generic --generic-ip-address=192.168.33.10 --generic-ssh-key ~/swarm/master/.vagrant/machines/default/virtualbox/private_key --generic-ssh-user vagrant --swarm --swarm-master --swarm-discovery consul://192.168.77.6:8500/swarm master docker-machine create -d generic --generic-ip-address=192.168.33.11 --generic-ssh-key ~/swarm/node1/.vagrant/machines/default/virtualbox/private_key --generic-ssh-user vagrant --swarm --swarm-discovery consul://192.168.77.6:8500/swarm node1 docker-machine create -d generic --generic-ip-address=192.168.33.12 --generic-ssh-key ~/swarm/node2/.vagrant/machines/default/virtualbox/private_key --generic-ssh-user vagrant --swarm --swarm-discovery consul://192.168.77.6:8500/swarm node2
docker-machine lsコマンドで確認。
docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS master * (swarm) generic Running tcp://192.168.33.10:2376 master (master) v1.11.1 node1 - generic Running tcp://192.168.33.11:2376 master v1.11.1 node2 - generic Running tcp://192.168.33.12:2376 master v1.11.1
3台の情報を確認できる。
またconsulで指定したキーの箇所も使われていることが見て取れる。
Swarm Masterに切り替え
クラスタを操作するためにdockerコマンドがmasterに向くように設定。
eval "$(docker-machine env --shell bash --swarm master)"
確認するとクラスタっぽくなってるのが読み取れる。
docker info
略 Nodes: 3 master: 192.168.33.10:2376 略 └ Labels: executiondriver=, kernelversion=3.10.0-229.el7.x86_64, operatingsystem=CentOS Linux 7 (Core), provider=generic, storagedriver=devicemapper └ Error: (none) └ UpdatedAt: 2016-05-26T14:38:43Z └ ServerVersion: 1.11.1 node1: 192.168.33.11:2376 略 └ Labels: executiondriver=, kernelversion=3.10.0-229.el7.x86_64, operatingsystem=CentOS Linux 7 (Core), provider=generic, storagedriver=devicemapper └ Error: (none) └ UpdatedAt: 2016-05-26T14:38:50Z └ ServerVersion: 1.11.1 node2: 192.168.33.12:2376 略 └ Labels: executiondriver=, kernelversion=3.10.0-229.el7.x86_64, operatingsystem=CentOS Linux 7 (Core), provider=generic, storagedriver=devicemapper └ Error: (none) └ UpdatedAt: 2016-05-26T14:38:32Z └ ServerVersion: 1.11.1 #略
Dockerでコンテナを立ち上げてみる
docker-compose.yml作成
前回同様にnginxを立てることを想定してみる。
nginx: image: nginx:latest ports: - "80:80"
前回言及したようにホスト側のポートを固定してしまうのは本来的にはコンテナ運用の趣旨に反するのだが、 案件的には必要だったりするので一応。
起動
てなわけでとりあえず立ち上げ。
docker-compose up -d
例によって全台でイメージはプルされるっぽい。
Pulling nginx (nginx:latest)... node2: Pulling nginx:latest... master: Pulling nginx:latest... node1: Pulling nginx:latest... Creating swarm_nginx_1
確認。
docker ps
どうやら今回はnode1が立ち上がったもよう。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4401ce708eeb nginx:latest "nginx -g 'daemon off" 21 seconds ago Up 14 seconds 192.168.33.11:80->80/tcp, 443/tcp node1/swarm_nginx_1
スケーリング
スケーリング。
docker-compose scale nginx=3
ポートの件警告はされるけど実行してくれる。
WARNING: The "nginx" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash. Creating and starting swarm_nginx_2 ... done Creating and starting swarm_nginx_3 ... done
確認。
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 851f781a7a42 nginx:latest "nginx -g 'daemon off" About a minute ago Up About a minute 192.168.33.10:80->80/tcp, 443/tcp master/swarm_nginx_3 33c702157492 nginx:latest "nginx -g 'daemon off" About a minute ago Up About a minute 192.168.33.12:80->80/tcp, 443/tcp node2/swarm_nginx_2 4401ce708eeb nginx:latest "nginx -g 'daemon off" 2 minutes ago Up 2 minutes 192.168.33.11:80->80/tcp, 443/tcp node1/swarm_nginx_1
ちゃんと分配されることが確認できる。
ポート固定で台数以上を指定しちゃった場合。
docker-compose scale nginx=4
当然エラー。
WARNING: The "nginx" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash. Creating and starting swarm_nginx_4 ... error ERROR: for swarm_nginx_4 Unable to find a node that satisfies the following conditions [port 80 (Bridge mode)]
ちなみにホスト側のポートを指定しなければ勝手にポート番号が変わって開く。
consulとか使って動的にプロキシの設定を変更するとかマルチホストネットワークでゴニョゴニョとかありそうだけど、 今回の案件的にはいらない要素だったのでそこまでは調べてない。
このへんはそのうち。
折角なんで色々
起動するホストを明示したりしてみる。
web-mst: image: nginx:latest environment: - "constraint:node==master" web-api: image: nginx:latest environment: - "constraint:node==node*" web-usr: image: nginx:latest environment: - "constraint:node==node*"
docker-compose up -d
Creating swarm_web-usr_1 Creating swarm_web-api_1 Creating swarm_web-mst_1
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 372204dbd280 nginx:latest "nginx -g 'daemon off" About a minute ago Up 53 seconds 80/tcp, 443/tcp node2/swarm_web-api_1 a513761b8d0d nginx:latest "nginx -g 'daemon off" About a minute ago Up 46 seconds 80/tcp, 443/tcp node1/swarm_web-usr_1 a8ca9785e70f nginx:latest "nginx -g 'daemon off" About a minute ago Up 51 seconds 80/tcp, 443/tcp master/swarm_web-mst_1
サービスごとにスケール数を変えてみる。
docker-compose scale web-api=4 web-usr=5 web-mst=2
Creating and starting swarm_web-api_2 ... done Creating and starting swarm_web-api_3 ... done Creating and starting swarm_web-api_4 ... done Creating and starting swarm_web-usr_2 ... done Creating and starting swarm_web-usr_3 ... done Creating and starting swarm_web-usr_4 ... done Creating and starting swarm_web-usr_5 ... done Creating and starting swarm_web-mst_2 ... done
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ae15a4e493ae nginx:latest "nginx -g 'daemon off" 21 seconds ago Up 16 seconds 80/tcp, 443/tcp master/swarm_web-mst_2 b10b639b5a92 nginx:latest "nginx -g 'daemon off" 41 seconds ago Up 25 seconds 80/tcp, 443/tcp node2/swarm_web-usr_4 e153d6aeae7d nginx:latest "nginx -g 'daemon off" 41 seconds ago Up 26 seconds 80/tcp, 443/tcp node2/swarm_web-usr_3 01e700d25ab4 nginx:latest "nginx -g 'daemon off" 41 seconds ago Up 21 seconds 80/tcp, 443/tcp node1/swarm_web-usr_5 d0df4789fbc1 nginx:latest "nginx -g 'daemon off" 41 seconds ago Up 24 seconds 80/tcp, 443/tcp node1/swarm_web-usr_2 67f9d9ab3f73 nginx:latest "nginx -g 'daemon off" 54 seconds ago Up 40 seconds 80/tcp, 443/tcp node2/swarm_web-api_4 5cf4430e86e7 nginx:latest "nginx -g 'daemon off" 54 seconds ago Up 42 seconds 80/tcp, 443/tcp node1/swarm_web-api_3 7a21657ab3ee nginx:latest "nginx -g 'daemon off" 54 seconds ago Up 40 seconds 80/tcp, 443/tcp node2/swarm_web-api_2 372204dbd280 nginx:latest "nginx -g 'daemon off" 3 minutes ago Up 3 minutes 80/tcp, 443/tcp node2/swarm_web-api_1 a513761b8d0d nginx:latest "nginx -g 'daemon off" 3 minutes ago Up 3 minutes 80/tcp, 443/tcp node1/swarm_web-usr_1 a8ca9785e70f nginx:latest "nginx -g 'daemon off" 3 minutes ago Up 3 minutes 80/tcp, 443/tcp master/swarm_web-mst_1
指定通り、web-mstはmasterでのみ、それ以外はnodeで分散されていることが確認できる。
掃除
Docker側
docker-compose kill eval "$(docker-machine env -u)" docker-machine rm master node1 node2
Consul側
WebUI上からswarmのキーを削除。
Vagrant側
cd master #それぞれのディレクトリで vagrant halt vagrant destory #もうイメージいらないなら
まとめ
そんなこんなでちょっと本題以外の分量が多くなっちゃったけど、一応まとめ。
CentOS7が入った実機でクラスタリングしたい場合には
- ちゃんとグローバルネットワークに接続できる
- 既存のDocker(Engineじゃない)関連のパッケージをアンインストール(yum remove docker*とかで)
- sudoがパスワードなしでできる操作アカウントを用意(generic-ssh-userで指定する)
- 3のユーザでsshアクセス可能な鍵を用意
- 予めnet-toolsをインストール
- 予めdocker-engine用に2376ポート(任意に変更は可能)を開けておく
といった手順を踏めば良さそう。
今回はVM全部にベタに操作していったけど、本来ならイメージをコピーして必要な箇所だけ変えるとかで実験も時短できたかもしれない。
この辺はまだ僕のVagrant力が足りないところなんで、今後学んでいきたいところ。
プログラマのためのDocker教科書 インフラの基礎知識&コードによる環境構築の自動化
- 作者: WINGSプロジェクト阿佐志保,山田祥寛
- 出版社/メーカー: 翔泳社
- 発売日: 2015/11/20
- メディア: 大型本
- この商品を含むブログ (2件) を見る
- 作者: Mitchell Hashimoto,Sky株式会社玉川竜司
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/02/21
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (10件) を見る
追記
やりようはあったようだ。