ども、cloudpack の かっぱ (@inokara) です。ご無沙汰してます。
追記(お詫び)
- consul と serf を混同していた為、「consul はマルチキャストでノードを探索して勝手にクラスタを組んでくれる」というのは誤りを記載しておりました
- consul は serf とは異なりマルチキャストによるメンバージョインは出来ないようです
- 実際には
-join
オプションが必要になります - 尚、consul 0.5 からは atlas-join オプションが加わり Atlas を利用したクラスタ構成が可能です
はじめに
AWS 環境で Consul を起動する際に -join
オプションを使ってジョイン先を指定していたけど、そもそもジョイン先を確認しなければいけないのはカッタルイなあと思ったので、ジョイン先を AWS のタグで管理して consul 起動の際にタグからジョイン先を判断出来たら面白そうだなと思って試してみた。そもそもタグを利用しなくても出来る方法があるかもしれないのであくまでもアイデアの一つとして…。
参考
consul がクラスタを構成する際には…
ざっくり言うと…
consul はマルチキャストでノードを探索して勝手にクラスタを組んでくれるマルチキャストが利用出来ない場合には-join
オプションでジョイン先を指定する必要がある
ということなので…
AWS 環境の場合には…
残念ながら
Multicast が利用出来ないので consul を起動すると漏れ無くスプリットブレイン状態となる。
以下のようなイメージ。
今までは…
以下のように実行してクラスタを構成している。
/usr/local/bin/consul agent -config-dir=/etc/consul.d -join ${ジョイン先}
思いついたアイデア
- AWS のタグに
consul-join
というタグを作る(タグ名はあくまでも例) consul-join
にtrue
が入っているノード(インスタンス)にジョインする- リーダーノード(
curl -s -X GET http://localhost:8500/v1/status/leader
)の場合にはconsul-join
をtrue
にする consul watch
オプションを使ってクラスタ内に変化があればconsul-join
タグをチェックしてリーダーが変わっていればタグを更新する
以下のようなイメージ。
※図では consul-leader というタグ名になっているが適宜読み替える
実際にやってみる
consul の設定
consul の設定。
{ "bootstrap": false, "bootstrap_expect": 3, "server": true, "data_dir": "/opt/consul", "log_level": "INFO", "node_name": "${HOSTNAME}", "enable_syslog": true }
consul watch の設定。
{ "watches": [ { "type": "nodes", "handler": "/opt/bin/consul-check.sh" } ] }
IAM ロール
EC2 タグを操作する必要があるので、最低でも以下の権限を付与しておく必要がある。
- ec2:DescribeInstances
- ec2:DescribeTags
- ec2:CreateTags
- ec2:DeleteTags
consul を起動する init スクリプト
consul を init スクリプト経由で起動する際のスクリプトは以下のとおり。
なんの変哲も無い init スクリプトだけど、以下のようにジョイン先を EC2 タグから取得している。
(sinp) JOIN_TO=`aws --region ap-northeast-1 ec2 describe-instances --query 'Reservations[].Instances[].[PrivateIpAddress]' --output text --filter 'Name=tag:consul-leader,Values=true'` (snip)
consul watch で利用する監視スクリプト
スクリプトは以下のとおり。
動作確認
現状
リーダーノードを確認。
$ curl -s -X GET http://localhost:8500/v1/status/leader "xxx.xx.xx.37:8300"
リーダーノードの確認も上記のように API にて取得することが可能です。
適当に consul leave
リーダーとなっている consul ノードで consul leave
を実行する。
従来リーダーだったノードにて consul leave
を実行後に他のノードにてリーダーノードを確認すると先ほどと変わっている。更に、マネジメントコントールを見ると…
おお。
再度ジョインする場合には…
先ほど consul leave
したノードを再度ジョインさせる場合には…
/etc/init.d/consul start
で consul を起動するとジョイン先を EC2 タグから取得して正常にジョインが完了する。
ということで…
本日の知見
- マルチキャストでは無い環境では consul のクラスタを構成する際には
-join
オプションは必要(だと思う) consul watch
を利用すればクラスタノードに変化が発生した際に何らかの処理を行うことが出来る- 今回はタグの書き換えを行ったがもちろん通知等も可能
注意
- そもそも consul をまだ理解しきれていないので他にやり方があるかもしれない
お疲れ様でした。
元記事はこちらです。
「consul を EC2 で使う時のちょっとしたアイデア(EC2 Tag 使って Join 先を動的に管理する)」