Kubernetesクラスタを運用するということは、etcdクラスタも運用することになりますよね1
ところが、H/Aなetcdクラスタを楽に運用するためにはどうしたらいいのか、というまとまった情報がなかったので、ここに書いていきます。
TL;DR;
色々調べたり読んだりした結果、英語が大丈夫なら以下のブログを読むのが一番よいと思いました。
Building a Robust etcd cluster in AWS · crewjam.com
etcdにおけるH/Aとは?
- 最低でも読み書きがNetwork Parittionに耐えられるように1 node * 3リージョンの構成で、5、7、9のようにどう障害が起きてもスプリットブレーンにならないノード数
メンテナンスとは?
- CoreOSの自動アップデート
- あえて無効化しなければ、設定したタイミングで自動リブートされる
- 自動リブートのときにダウンタイムが発生しないようにしたい
- あえて無効化しなければ、設定したタイミングで自動リブートされる
- etcd自体の更新
- CoreOSに含まれるetcdを起動するなら、CoreOSの更新と一緒にアップデートされるはず
- なので↑と一緒
- etcdのバックアップ・復元
- 全ノードが落ちることがあったら、データを全消失させる以外に、バックアップから復元する方法がある
- スケールアウト
- 読み書きが追いつかなくなった場合に、安全にノード数を増やしたい
- 安全とは
- スケールアウト中にネットワーク障害が発生してもスプリットブレーン状態にならない
そもそもetcdクラスタの安全なスケールイン手順は?
おおまかにいうと、リーダーでなくしてからノードをquorumから削除する。そのためには、現在のクラスタから削除する+ディスカバリ対象にならないようにDiscovery Endpointからも削除する。
-
etcdctl member list
でノードIDを知る - リーダーを削除したい場合は、まず他のノードをリーダーに昇格させる
-
etcdctl member remove NODE_ID
で対象ノードをquorumから削除する -
etcdctl member list
でノードが削除されてることを確認する -
etcdctl cluster-health
でクラスタが正常に稼働してることを確認する(確認した限り、リーダーを削除してしまうと、cluster-healthが返ってくるのにleader election timeout時間分かかる気がするので、cluster-healthの応答がすぐ返ってこなかったら、手順が間違ってたことになる) - etcd discovery endpointを使ってる場合(=
MonsantoCo/etcd-aws-cluster
とかを使ってない場合)-
curl -XDELETE https://discovery.etcd.io/DISCOVERY_ID/ノードID
でノードを削除 -
curl https://discovery.etcd.io/DISCOVERY_ID
でノードが削除されてることを確認
-
参考: kocho/etcd-operations.md at master · giantswarm/kocho
リーダーを起動しているノードの場合、書き込みが一時的にできなくなる状態を避けるためには、ノードがシャットダウンされる前にリーダーを他のノードに譲りたい。
etcd live cluster reconfiguration on CoreOS
CoreOS, AWS, Fleet issue - Google グループ
quorum
上の手順の前提は、ノードが一つ落ちたくらいではスプリットブレーンの危険もなく、かつ合意が形成できるようなノード数を保つ、またはquorumを下回らないようにする、ということです。
etcd界隈だと冒頭で紹介したcrewjamさんのブログ記事や、CoreOSの公式ドキュメントあたりにしか明確に書かれてない気がするのですが、例えばそもそも2ノードのetcdクラスタだと、quorumが1なのでネットワーク障害等でそれぞれのノードが自分をリーダおと思い込んで書き込み要求を受け付けてしまって、ネットワーク障害から復旧したときにリーダー同士のデータ不整合で自動復旧ができなくなってしまいます。
単一のノード障害でquorumを下回らない、かつネットワーク障害等でスプリットブレーンが起きないノード数を選ぶことは、書き込みのコミットにquorumが必要なElasticsearchなどでも重要視されています。
How many nodes should an Elasticsearch cluster have?
etcdの場合、例えば単一AZの障害に耐えたいなら、最低3ノードを別々のAZやRegionに置く必要があります。
仮にap-northeast-1aに2ノード、ap-northeast-1bに1ノードおいたとき、1aが落ちると書き込みが完全にできなくなります。1bにいる1ノードがリーダーになるために合意を募っても、quorum=2以上の合意は得られず、結果quorumが必要な書き込みもコミットできないからです。
参考
-
AWS etcd Serviceこないかなぁ〜〜 ↩