クラスターソフトをスクリプトで書いてみよう～理論編

# 概要

- クラスターソフトの概要を説明
- 技術的に悩ましいところを説明

# はじめに
障害検知をしてフェイルオーバーするスクリプトで書いてみることでクラスターソフトへの理解が深まります。今回は理論編ということでクラスターソフトの概要について説明します。[次回の実践編](https://qiita.com/tsunenorikan/items/7351c5d3abeee4276b28 "クラスターソフトをスクリプトで書いてみよう~実践編")ではクラスターソフトをPowerShellで実際に書いてみます。

# クラスターソフトとは
データベースサーバーはWebサーバーと違って単純に台数を増やして冗長構成を取ることができません。理由はデータの同期や排他制御が必要なためです。障害対策としてよく用いられるのがアクティブスタンバイ方式です。データベースサーバーを2台用意し、1台を稼働系(アクティブ)として運用、もう1台を待機系(スタンバイ)として運用します。クラスターソフトはアクティブにハードウェア障害が発生した場合、障害検知をしてスタンバイへの切り替えを行うソフトウェアです。
# クラスターソフトの主な機能
### 生死監視
アクティブが正常かどうかを監視し、障害発生時には障害検知します。以下のやり方があります。
**【ハートビート】**
アクティブとスタンバイ間で信号を送信します。これをハートビートといいます。ハートビートが一定期間、途切れたら障害とみなします。簡単にやるならスタンバイからアクティブにpingをして応答があるかを確認します。クラスターソフトの中には信号に制御情報を乗せるものもあります。
**【サービス監視】**
データベース等のサービスが稼働しているかを監視します。具体的にはプロセスの存在やポートが使用されているかを確認します。
### データの引き継ぎ
データベース等が使っているデータは通常時はアクティブのみが使用(書き込み)ができ、スタンバイは使用できません。障害時にスタンバイがデータを使用できるようにする必要があります。データの共有方法によってやり方が異なります。
**【共有ディスク】**
サーバーとデータのあるディスクがハードウェアとして別れていて、アクティブサーバーとスタンバイサーバーが一つの共有ディスクに接続されています。ディスクは通常時はアクティブにマウントされており、障害時はスタンバイにマウントしなおす必要があります。
![共有ディスク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/1713fa39-ac6b-98c0-fef6-f8f115f6ae18.png)

**【レプリケーション】**
サーバー間でデータを継続的にコピーすることをレプリケーションといいます。データベースの場合、レプリケーションはデータベースの標準機能やオプション機能で実装されます。通常時はアクティブのみが書き込み可能でスタンバイはアクセス不可か読み取りのみになります。障害時はスタンバイが書き込みできるように設定変更する必要があります。
![レプリケーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/52d45f8f-8968-4075-e074-95cd9e52b172.png)

### ネットワークの引き継ぎ
PCやWebサーバーなどのクライアントは通常時はアクティブサーバーに接続します。障害時にはスタンバイに接続しなおす必要があります。以下のやり方があります。

**【仮想IP】**
サーバーごとに設定されているIPアドレスとは別にサービスに接続するための仮想IPを用意します。通常時は仮想IPをアクティブサーバーに割り当て、障害時にはスタンバイサーバーに割り当てます。
**【ロードバランサー】**
ローバーバランサーを介してデータベース等へ接続します。通常時はロードバランサーはアクティブサーバーに割り振り、障害時にはスタンバイサーバーに割り振ります。
**【代替IP】**
クラスターソフトの機能でなく、データベース(IBM Db2)の機能になります。クライアントがデータベースに接続する際に代替IPの情報を取得します。アクティブのデータベースに接続できない場合、代替IPを使ってスタンバイのデータベースに接続を試みます。

# 技術的に悩ましいところ
### スタンバイに切り替えてよいかの基準
サーバーが落ちていて起動できないなら迷わずスタンバイに切り替えますが単純なケースばかりではありません。考え出すと悩ましくて夜も寝れません。特にいやなのは切り替える必要がないのに切り替わってしまうケースです。

- pingに応答しない
 - サーバーが起動できないのかも → 〇スタンバイに切り替え
 - OSがハングしているのかも → △切り替えよりもOS再起動 
- データベースのプロセスがない、ポートが開いていない
 - データベースが起動できないのかも → 〇スタンバイに切り替え
 - メンテナンス中かも → ×切り替えると大惨事になる可能性
- データベースに新規接続できない (pingに応答、ポートも開いている)
 - 最大接続数に達しているのかも → ×切り替えよりも最大接続数の増加
 - データベースのバグかも → ×切り替えよりもパッチの適用
- データベースの応答が遅い (pingに応答、ポートも開いている)
 - 処理が重いかも → ×切り替えよりも重い処理を強制終了
 - データベースがハングしているのかも → △切り替えよりもデータベース再始動

スタンバイへの切り替えは、アクティブにハードウェア障害が発生して起動できない場合、もしくはアクティブがネットワーク的に孤立してクライアントから接続できない場合に行うべきです。そうでない場合、OS再起動した方がスムーズです。

### サーバーが落ちてるのかネットワークが切れているのか
ハートビートが切れた場合、以下のケースが考えられます。

1. アクティブサーバーが落ちている
2. アクティブサーバーのネットワークカードが故障している
3. アクティブサーバーのネットワーク(サブネット)が落ちている
4. スタンバイサーバーのネットワーク(サブネット)が落ちている
5. スタンバイサーバーのネットワークカードが故障している
![ネットワーク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698263/29b83092-2a78-dfd5-be4a-6918a18bec75.png)

1～3ならスタンバイに切り替えるべきですし、4～5ならスタンバイに切り替えるべきではありません。4～5で切り替えを強行すると両方のサーバーがサービス提供中になり、**スプリットブレイン**という不正な状態になります。正しく判断するにはどのようにすればいいでしょうか。

**【クォーラムディスク】**
共有ディスク方式によく用いられるやり方で判定用のクォーラムディスクに対してロックを取得できた方を正とするものです。最近ですと、パブリッククラウドのオブジェクトストレージ(AWSのS3等)でクォーラムディスクを実装することもできます。

**【ネットワークタイブレーカー】**
タイブレーカーというレフェリー役の第三者をネットワークに設定します。やり方の一つとして、アクティブサーバー以外のネットワーク(ルーター等)にpingを出して応答するならネットワークが生きていると判断します。

|  | スタンバイ→ルーター | スタンバイ→アクティブ |
|:-----------|:------------:|:------------:|
| サーバー障害でスタンバイに切り替え       | 応答        | 不通         |
| ネットワーク障害のため切り替えない     | 不通      | 不通       |

# さいごに
どのケースならスタンバイに切り替えるのかを明確にしておくべきでしょう。ただし、機械的に判断できることだけになるので割り切りも必要です。こういったことをユーザーの意図通りに行えるかがクラスターソフトの巧拙になります。
# 次回
今回は理論編でしたが、[次回の実践編](https://qiita.com/tsunenorikan/items/7351c5d3abeee4276b28 "クラスターソフトをスクリプトで書いてみよう~実践編")は実際にクラスターソフトをPowerShellで書いてみます。