リーダーだけコマンドを実行したい
あまりConsulの要件っぽくはないんですが、任意の場所から特定のノード(今回はリーダー)でのみコマンドを発火させたかったのでそれを実現するためのメモです。
リーダーのノード名を知りたい
特定のノードで特定のコマンドを実行するには consul exec
の nodeオプションを指定するのが良さそうです。
しかしおそらく リーダーのノード名を一発で取得できない ようなので、以下のフローで取得する必要があります。
1. リーダーのIP取得
status APIで取得。1
$ curl https://consul.rocks/v1/status/leader
"10.10.10.1:8300"
2. リーダーのノード名取得
Agent Members API でメンバー一覧を取得し、その中からリーダーのNameを抜き出す。2
$ curl https://consul.rocks/v1/agent/members
[
{
"Name": "foobar",
"Addr": "10.10.10.1",
"Port": 8301,
"Tags": {
"bootstrap": "1",
"dc": "dc1",
"port": "8300",
"role": "consul"
},
"Status": 1,
"ProtocolMin": 1,
"ProtocolMax": 2,
"ProtocolCur": 2,
"DelegateMin": 1,
"DelegateMax": 3,
"DelegateCur": 3
}
]
jqで一発取得しようとするとこんな感じでしょうか。
$ curl -s localhost:8500/v1/agent/members | jq -r '.[] | if .Addr == "<リーダーIP>" then .Name else empty end
これでリーダーのノード名が入手できました。
特定のノードで特定のコマンドを実行したい
これは consul exec で -node
オプションを指定すればOKです。
consul exec -node="<リーダーのノード名>" "<お好きなコマンド>"
おまけ
今回の場合、consul exec
でサーバノード全体をワイルドカードフィルタし(ex. consul-server-*)、「実行するコマンド内で自分がリーダーかどうか」を確認して「自分自身がリーダーの時のみ実行する」という手法の方がConsul的なのかなーと思いました。
またその他良い方法があればご教示ください