分散アーキテクチャにおけるフェイルオーバーと、Couchbase Serverにおけるその実現

# はじめに

本稿は、以下の２部構成からなっています。

1. 分散アーキテクチャーのフェイルオーバー
2. Couchbase Serverにおけるフェイルオーバー

1部の内容も、Couchbase Serverのアーキテクチャーに基づいてはいますが、分散アーキテクチャーにおけるフェイルオーバーについての解説として、一般に妥当な内容となることを意図して整理しています。

このような構成により、システム固有の要素と、アーキテクチャー上の要請とが、それぞれ理解しやすいものとなることを望んでいます。


# 1. 分散アーキテクチャーのフェイルオーバー

## 序. 分散アーキテクチャーの構成変更

### 計画的なノードの削除（または、グレースフルフェイルオーバー）
クラスタから機能しているノードを削除するには、管理コンソール等を利用し、削除するノードを指定します。 その後クラスタをリバランスし、そのノードへのデータリクエストが他のノードで処理できるようにします。 

削除対象ノードは、リバランスが完了するまでデータリクエストを処理することができます。完了時点で、他のノードでリクエストが処理されることになります。 すなわち、サービスが中断するようなことも、データを消失してしまうこともなく、ノードを削除してクラスタを（グレースフルに）リバランスできます。 

機能しているノードを運用管理目的で削除したい場合、フェイルオーバではなく、ノード削除(Remove)の後、リバランスを実行します。

### 障害時のノードの削除（または、ハードフェイルオーバー）

フェイルオーバー(failover)とは、そのノードをクラスタから削除し、他のノードにあるレプリケートしたデータを利用可能にすることです。

フェイルオーバーはノードの削除とは異なり、正常に動作していないノードに対して実行します。（機能しているノードをフェイルオーバした場合、フェイルオーバは即座にノードをクラスタから削除するため、データロスが発生する可能性があります。）

ノード障害時に他のノードへレプリケートされていないデータが存在していた場合データロスとなります（フェールオーバーしたノード上で、ディスクに永続化されていた場合、そのサーバーが復旧出来た場合には、データを復旧できる可能性があります（デルタリカバリー）。そうでない場合データは、完全に消失することになります。

## フェールオーバー概観

ここからは、フェールオーバー（上記のハードフェイルオーバー）に伴う、諸所の論点を整理します。

### フェイルオーバー手段

ノード障害発生時には、フェイルオーバーを手動で実行するか、あるいは、自動的にフェイルオーバーをトリガーし、縮退モードでクラスタを稼働させるように設定することが考えられます。 フェイルオーバーはクラスタの性能を縮小させてしまうため、フェイルオーバーの状況をどのように処理すべきかをよく検討するべきです。 

自動フェイルオーバーを利用すると、ユーザ操作なしにノードをフェイルオーバーできますが、ノード障害を発生させた問題の調査や特定は難しくなります。

手動フェイルオーバーによりクラスタを管理する場合、クラスタを監視し、問題の発生を検知できるようにします。 問題が発生したら、手動（あるいは外部スクリプト）でフェイルオーバーを実行します。 この手順では、より多くの監視や手動の操作が必要です。

### 復旧
フェイルオーバー実行により、クラスタが縮退運転している間、クラスタ内に残る稼働中のノードに対する負荷は増大します。 クラスタがノード障害前と同じ状態で機能するためには、正常に機能するノードをクラスタに戻し、リバランスを実行して、ノード障害から復旧する必要があります。

手動でフェイルオーバーを実行しても、クラスタが自動的に実行するようにしても、障害の原因を解明する必要があります。 そして、正常に機能するノードをセットアップし、そのノードを追加し、クラスタをリバランスします。 

フェイルオーバーシナリオに対処する際の、ノードの交換および追加に関する選択肢を以下に記します。

- ハードウェアやシステム障害が起因してノードがダウンした場合、新規の交換用ノードをクラスタに追加してリバランスする。

- クラスタのキャパシティ不足が原因でノードがダウンした場合、ノードの交換に加え、必要なキャパシティとするために必要な分だけノードを追加する。

- ノードの障害が一時的なものである場合、そのノードをクラスタに再追加します。


### 連鎖反応(Thundering Herd)への考慮

自動でコンポーネントを取り除くには、どんな分散システムでも問題が付き物です。 問題の原因を特定できない場合、または残りのシステムにかかる負荷を理解していない場合、自動フェイルオーバーは問題を解決するどころか、より多くの問題を発生させる可能性があります。 次のような状況では、問題を誘発する可能性があります。

クラスタが、キャパシティの80-90%で稼働しているとします。その時点で、順調に稼働していたとしても、クラスタのキャパシティは限界です。 ノード障害が発生し、ソフトウェアが自動的にノードをフェイルオーバーしたとします。 残りの4ノードでは負荷が増大し、正常に処理することはできないでしょう。
結果として負荷が増加することで、他のノードもダウンし、自動的にフェイルオーバーされてしまいます。 これらの障害は連鎖し、結果的にクラスタ全体の消失へとつながる可能性があります。 

この場合の次善策は、単一ノード障害が発生してもクラスタの運用を続け、新しいサーバをクラスタに追加し、失われたキャパシティを補填して、ダウンしたノードを削除し、リバランスを実行することです。 こうすれば、クラスタ全体が利用不可となる代わりに、部分的な障害で済みます。単一ノード障害発生時には、一部のリクエストを処理できない方が、クラスタ全体の障害によってまったくリクエストを処理できないことよりも良いと言えます。

このような状況の予防策としては、ノード障害発生時にも十分な余剰のキャパシティを確保し、縮退運転ができるようにすることです。

### フェイルオーバー実行条件
ネットワークデバイスの故障が原因でネットワークが分割されてしまう、ネットワーク分断やスプリットブレインの状況を考慮し、多くのクラスターは以下の制約付きで自動フェイルオーバーを実装しています:

- 自動フェイルオーバーは最低でも1クラスタに3台のノードを必要とする。 これは、ネットワーク分断が発生した際に、2ノードのクラスタがお互いのノードをフェイルオーバーすることを防ぎます。クラスターによって、データのセットが構成されている場合、これはデータの整合性と一貫性を保護するために重要です。
- 自動フェイルオーバーはレプリカデータによりサービスが継続可能な場合のみ実行される。
- 自動フェイルオーバーは管理操作を必要とする前に一度だけ発動する。 これは、フェイルオーバーの連鎖による、以後の性能や安定性の劣化を防ぐためです。 多くの場合、クラスタが機能できなくなるまで劣化し続けるよりも、データセットの小さな部分にアクセスできなくなる方が望ましいでしょう。
- 自動フェイルオーバーを実行するまでに一定の待機時間を設ける。 これは一時的なネットワーク障害や、システムの遅延によって、誤ってノードがフェイルオーバーされることを防ぎます。

## フェールオーバーの運用

手動フェイルオーバを行う場合、二つ方法があり、一つは人による監視、もう一つは外部システムを利用する方法です。 

### 保守要員による運用
アラートに対して次の行動に関する意思決定をする人員を確保することは一つの選択肢です。 人間が広範囲のデータ、観測、経験を考慮し、最適な方法で状況を解決できるユニークな存在です。 多くの組織では、人が影響に対する考慮をしないままにフェイルオーバを自動化することを許可していません。 マニュアルによる介入を行うことの問題点はコンピュータベースのモニタリングシステムを利用することに比べ、対応が遅くなるということです。

### 外部モニタリング
もう一つの選択肢はREST APIを利用してクラスタをモニタリングするシステムを利用することです。 このような外部システムは、クラスタ以外のシステムコンポーネントに関しても考慮できるため、ノードのフェイルオーバにとって優位な位置に存在します。

例えば、モニタリングソフトウェアは、クラスタが依存するネットワークスイッチがダウンしていることを検知できます。 システムはノードをフェイルオーバしても状況は改善しないことが分かるため、ノードのフェイルオーバーはしません。

モニタリングシステムはクラスタ周辺のコンポーネントが機能しているか、クラスタ内の様々なノードが健全であるかを判断することもできます。 モニタリングシステムが、問題は単一のノードだけで起きており、クラスタ内の残りのノードで集約したトラフィックを処理できると判断すれば、システムからREST APIやコマンドラインツールを利用してそのノードをフェイルオーバーすることもできます。

# 2. Couchbase Serverにおけるフェイルオーバー

## 自動フェイルオーバー仕様・制約

Couchbase Serverの自動フェイルオーバには多くの制約があります。 これは自動フェイルオーバーを利用する際に発生する可能性のある問題を回避するためです。

下記のようなケースでは、自動フェイルオーバーがトリガーされません。

- **イベント同時発生** 複数のイベントが同時に発生した場合、自動フェイルオーバーはトリガーされません。

- **フェイルオーバー連続実行** 管理者が指定したイベントの最大数までしか、自動フェイルオーバーはトリガーされません。許可される最大の最大値は3です。この自動フェイルオーバーの最大数に達すると、管理者がカウントを手動でリセットするまで、自動フェイルオーバーは発生しません。ただし、最大数に達する前にカウントを手動でリセットできます。

- **データ損失発生可能性** データ損失が発生する可能性のある状況では自動フェイルオーバーは発生しません。たとえば、バケットにレプリカがない場合はこのケースです。

- **非フェールオーバーノードの応答状況** （フェールオーバー対象となる）ノードが応答しなくなった後でも、ノードの過半数に接続できる場合のみ、自動フェールオーバーがトリガーされます（グループの場合、グループが応答しなくなった後でも、グループの過半数に連絡できる場合のみ）。



### デフォルト設定
デフォルトでは無効 自動フェイルオーバはデフォルトでは無効となっています。 これは明示的に有効とされるまで、自動フェイルオーバーが発生することを防止するためです。



### 待機時間
ノードがフェイルオーバされるまでに、最低でも30秒の遅延時間が必要です。 この時間を延ばすことはできますが、ソフトウェアはダウンしているかもしれないノードに対して複数回の死活監視を実行するようにハードコーディングされています。 これは機能しているが遅いノードのフェイルオーバや、ネットワーク接続問題によりフェイルオーバが発動することを防ぐためです。


### 通知
REST APIを利用して、ノード障害が発生し、ノードが自動でフェイルオーバーされた際にCouchbase Serverがメールで通知を送信するように設定することができます。

## サービス固有の自動フェイルオーバーポリシー

応答しないノード上の1つまたは複数のサービスのサービス固有の自動フェイルオーバーポリシーに準拠して自動フェイルオーバーがトリガーされます。


### データサービス
自動フェイルオーバーが有効化されるためには、最低、３ノードが必要です。

### インデックスサービス
フェイルオーバーはサポートされません。

### その他のサービス（クエリ、サーチ、アナリティクス、イベント）
最低、２ノードが必要です。

## グループフェイルオーバー
Enterprise Editionでのみ使用できます。デフォルトでは無効とされています。
グループに多数のノードが含まれている場合でも、グループフェイルオーバーは単一のイベントと見なされます。





## フェイルオーバー実行方法
Couchbaseのフェイルオーバーは以下の方法で実行できます。

### Webコンソール
- WebコンソールのManagement -> Server Nodes セクションに移動します。クラスタがDownとして判定したノードのみフェイルオーバできます。フェイルオーバーしたいノードのFail Overボタンをクリックします。 
- 確認・警告メッセージが表示されます。
- Fail Overをクリックし、ノードをフェイルオーバーします。 Cancelを選択することもできます。

### コマンドラインツール
couchbase-cliのfailoverコマンドを利用して、複数のノードをフェイルオーバできます。 ノードをフェイルオーバするには、フェイルオーバーするノードのIPアドレス（および標準ポート番号を利用していない場合でない場合はポート番号）を指定します。 

```
couchbase-cli failover --cluster=<server(available)>:8091\
    -u cluster-username -p cluster-password\
    --server-failover=<server(target)>:8091
```
成功すると、ノードがフェイルオーバされたことを示すメッセージが表示されます。




# 参考情報

Couchbase Server ドキュメンテーション
[Fileover](https://docs.couchbase.com/server/current/learn/clusters-and-availability/failover.html)