Consul 0.4.x から 0.5.2 へのバージョンアップ

このエントリは HashiCorp Advent Calendar 2015 - Qiita 1日目の記事です。

Consul クラスタは一度稼働を始めたら基本的に落とせないため、いわゆるローリングアップグレードによってクラスタ全体を停止せずにバージョンを上げることが考慮されています。

consul.io

ということで基本的には上記のURLを参照して、順番にagentを新しいバイナリで起動し直すことによって新しいバージョンに切り替えられるわけですが、Consul 0.5.0, 0.5.1 についてはいくつか留意点がありますので記録しておきます。

consul.io

0.5.0 未満から 0.5.0 以上にする場合

  • acl 機能を使っている場合、あらかじめ acl_policy を設定してからアップグレードする必要があります
    • が、自分は使用していなかったのでスルー
  • Leader が Consul 0.5 の場合、followerもすべて 0.5 である必要があります
    • Followerをすべて 0.5 にして、最後に Leader を 0.5 に上げる
    • 任意の順番で上げてもよいが、その場合は15分以内にすべてを 0.5 にする

なぜ15分なのかよく分かっていませんが、厳しい時間制限があると心臓によろしくないので、Leaderを最後にする方法でやるのがよいでしょう。

バージョンアップの作業の順番を間違えなければ問題はありませんが、サーバが最小構成の3台しかない状態では、1台作業中に他のサーバに障害が発生すると危険なので、可能であれば一時的に5台構成にするのをおすすめします。

また、新しく起動したサーバがちゃんと 0.5 で、クラスタに正常に組み込まれているかはよくよくログなどで確認しましょう。もし新しいサーバが join できず、サーバが足りない状態で別のを作業開始してしまうとクラスタ崩壊コースです。

0.5.1 未満から 0.5.1 以上にする場合

Consul 内部で使用している DB が、LMDB から BoltDB に変更になっています。

0.5.x では起動時に自動で migration が行われますので、特に事前準備する必要はなくバイナリを入れ替えて起動し直すだけです。上記ページには以下のようなログがでたら完了だよ、と書いてあるので、

==> Successfully migrated raft data in 5.839642ms

つい「ふんふん数msでおわるのね」と思ってしまいますが……環境によってはもっと時間がかかるようです。 手元のEC2 (t2.medium, gp2 disk) のインスタンスで migrate すると、data_dir 内に100MBある状態で約45秒掛かりました。

migration が終わるまで consul agentは起動しないため、その間は名前解決などの機能も当然使用できません。consul serverのみで他の機能を提供していないホストであればともかく、そうでない場合はちょっとつらい。

ではどうすればいいのか。まず、自分の環境で migration にどれぐらいの時間が掛かるかを計測することができます。

hashicorp/consul-migrate · GitHub が手動での migration tool なので、これを使って、

  • consul agent を一旦止める
  • data_dir を rsync で別の場所に copy する
  • consul agent を起動する

として、copy された data_dir に対して consul-migrate コマンドを実行すれば Migration completed in x.xxxs と表示されて完了までの時間が分かります。

ちなみに consul-migrate 実行時の iostat -x は以下のようになっていました。大量の disk write が発生していますね。

Device:         rrqm/s   wrqm/s     r/s     w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
xvda              0.00   455.30    0.00 1159.70     0.00 33680.80    29.04     1.24    1.07   0.81  93.60

これで計測した migration に要する時間が運用上耐えられない場合の対応ですが、tmpfs に置いて migration することで劇的に高速化しました。同環境で 2.3 秒程度です。

  • consul (0.4.1) agent 停止
  • rsync で tmpfs に data_dir をコピー
  • 旧 data_dir から symlink を張る
  • consul (0.5.2) agent 起動

この手順で、合計ダウンタイムは数秒に抑えることができました。普通の disk に戻したい場合は、もう一度 consul agent を停止して、symlink を削除して書き戻してから起動することになります。

ただ、自分の場合は Consul server のホストが落ちたらまっさらな状態から同期し直してもたいしたコストではない(なんなら別のインスタンスを立てる) と判断したのと、Server が 5台あるので耐障害性もそれなりにある、ということで tmpfs のまま運用しています。

皆さんはどうしてるんでしょうか。教えてください。