fstaidというHAデーモンを作りました。
HeartbeatとかCorosyncとかPacemakerの代替を考えて作ったソフトウェアです。
なぜ作ったのか?
それほど多くはないんですがたまに「先方の許可するIPアドレスは1つしかないから、フェイルオーバー時にElasticIPを付け替える感じで」という案件がたまにあるんですよ。 そうすると「Corosync/Pacemakerでクラスタ組むか。だるいな…」ということになって、Heartbeat/Corosync/Pacemakerを使いたくない欲が高まった結果、作成されました。 KeepalivedやSerfを使ってクラスタを組むこともできるんですが、どうもやりたいことに対して、オーバーキル感とか明後日の方向感がぬぐえない感じでいました。
話は変わってMHAです。 MHAいいですよね。安定した動作もレプリケーションの付け替えもすばらしいんですが
- 監視対象外の第三者サーバによるモニタリング
- セカンダリチェック
- CLIツール群による設定・環境まわりのチェック
- フェイルオーバー完了後の起動ロック
などなど、「ああ、わかってる…」感がすごく好きでした。 fstaidにはMHAにインスパイアされたこれらの設計を取り入れた(つもり)です。
サーバ構成イメージ
使い方
以下のような感じで起動します。
fstaid -config fstaid.toml
設定ファイルは以下の通り。
[global] port = 8080 interval = 1 maxattempts = 3 #lockdir = "/tmp" #log = "/var/log/fstaid.log" #mode = "debug" [handler] command = "/usr/libexec/fstaid/handler.rb" timeout = 300 [primary] command = "curl -s -f server-01" timeout = 3 [secondary] command = "curl -s -f -x server-02:8080 server-01" timeout = 3 [self] command = "curl -s -f 169.254.169.254/latest/meta-data/instance-id" timeout = 3 [[user]] userid = "foo" password = "bar"
動作
- 2〜4までを一定時間ごとに繰り返す
- self-checkを実行→失敗したら即終了
- maxattemptsまでprimary-checkを実行。すべて失敗したら4に進む
- secondary-checkを実行。失敗したら5に進む
- 監視対象を死亡と見なして、ハンドラスクリプトを実行
- フェイルオーバーが完了。ロックファイルを作成してfstaidは終了 (ロックファイルを削除しないと、起動できない)
self-checkの必要性が微妙な感じなんですが、今のところ
- self-checkでsecondary-checkの踏み台サーバとの疎通を確認
- secondary-checkで踏み台サーバ経由で監視対象の動作を確認(ssh、http proxy等々)
- primary-checkで監視対象の動作を直接確認
とするといいんじゃないかと考えております。
ハンドラ
ハンドラはこんな感じです。
#!/usr/bin/env ruby # The handler is called when both the primary check and the secondary check fail primary_exit_code = ARGV[0].to_i primary_timeout = (ARGV[1] == 'true') secondary_exit_code = ARGV[2].to_i secondary_timeout = (ARGV[3] == 'true') def failover # to fail over end if primary_exit_code != 0 if secondary_timeout # Nothing to do if the secondary-check times out exit 1 end failover elsif primary_timeout # Nothing to do if the primary-check times out exit 2 end
Rubyで書いてますが、実行できればシェルスクリプトでもなんでも。
ARGV[0]
: primary-checkの終了コードARGV[1]
: primary-checkがタイムアウトしたか否かARGV[2]
: secondary-checkの終了コードARGV[3]
: secondary-checkがタイムアウトしたか否か
ここに、ElasticIPの付け替えとか、ENIの付け替えとかを仕込むとよいかと。
その他
curl localhost:8080/fail
をたたくことで、手動でフェイルオーバーを実行することもできます。
まとめ
今のところ、まだそのような案件が降ってきていないので、まだ実戦投入はできていないのですが、つらみが出てきそうなら積極的に使っていこうかと考えています。 あるいは、まだ知らない便利ソリューションがあるとしたら是非知りたいところですが…