[KE16] Azure での冗長構成の構築ガイドライン
# 1. はじめに
Azure 上で Kompira enterprise の冗長構成を構築を計画するときに検討すべき点や、構築する際の手順について説明します。

## 1.1. 変更履歴
| 日付 | 版数 |担当 | 備考 |
| --- | --- | --- | --- |
| 2020/10/15 | 1.0 | FP髙橋 | 初版 |
| 2020/10/23 | 1.1 | FP髙橋 | ハードウェア要件に関連して推奨 VM を修正 |
| 2020/10/27 | 1.2 | FP髙橋 | 「2.6.2. STONITHの設定」について追記<BR>「2.6.2.1. STONITH 利用時の注意点（重要）」を追記<BR>「3.3.5.2. STONITH デバイスの作成」に追記<BR>「3.3.6. pacemaker 自動起動設定の解除」を追記<BR>「4.3.1. マスターノードが電源オフあるいは強制再起動した場合の sync_master による復旧時の注意」を追記 |
| 2020/10/29 | 1.3 | FP髙橋 | 「2.6.2. STONITHの設定」の構成を変更：本文を「2.6.2.1. STONITH による相撃ち対策」に分割、「2.6.2.1. STONITH 利用時の注意点（重要）」を「2.6.2.2. スタートアップ時のフェンシング無効化」として `startup-fencing` について追記<BR> 「3.3.5.2. STONITH デバイスの作成」にスタートアップ時のフェンシング無効化手順を追記<BR>「3.3.3.1. セットアップオプションの確認」にVM間通信用NICを追加したときのローカルIPアドレスについて補足説明を追加 |
| 2020/12/07 | 1.4 | FP髙橋 | 「3.3.5.2. STONITH デバイスの作成」にある表を修正 |
| 2021/09/30 | 1.5 | FP髙橋 | 「2.6.2. STONITH の設定」で、RHEL8 の「フェンシングの概要」がリンク切れであったので、「フェンシングの概念」にリンクを差し替え |
| 2023/07/19 | 1.6 | FP髙橋 | 「1.2. 対象環境」「2.1. OS の種類」について、CentOS Linux 8.x を CentOS Stream 8 に置き換え、および、RHEL 7.x with HA add-on が Microsoft のサポート切れにより推奨仮想マシンから除外 |
| 2023/07/27 | 1.7 | FP髙橋 |「2.6.2.3. PROXY 環境下における STONITH の利用」「3.1.4. PROXY サーバの準備」「3.3.5.1. Pacemaker への PROXY の設定」を追加  |


## 1.2. 対象環境
- Kompira enterprise: v1.6.1 以上
- OS:
    - CentOS Stream 8（推奨）または CentOS Linux 7.6 以上（代替）
    - Red Hat Enterprise Linux (RHEL): 8.0 以上（推奨）または 7.6 以上（代替）
        - 本記事では HA add-on が付属した VM の利用を前提としています。
            - ※ (v1.6追記) RHEL 7.x with HA add-on は Microsoft のサポートが切れたため、推奨仮想マシンから除外しました。
        - <span style="color: #d86e00">独自に HA サブスクリプションを Azure に持ち込むことも可能かもしれませんが、本記事の対象外です。</span>

## 1.3. 注意事項
- 2020/10 時点での Azure の仕様を前提としています。

## 1.4. 制限事項
Azure 環境で冗長構成を構築するうえで、現時点では以下の制限事項があります。
 
 - リージョンをまたいだ冗長構成には対応していません。
 - 仮想ネットワークをまたいだ冗長構成には対応していません。
 - VIP 方式のアクセス振り分けには対応していません。

## 1.5. サポートポリシー
以下に該当する場合は、<span style="color: #d86e00">冗長構成としてのすべてもしくは一部の機能がサポート対象外となります</span>。

- 2 台の VM の OS の種類とバージョンが同一で無い場合
- 2 台の VM の種類や構成が同一で無い場合
- 異なる仮想ネットワークに配置した VM 間で冗長構成を構築した場合
- VM 間通信にパブリック IP アドレスを用いて冗長構成を構築した場合（VM にパブリック IP アドレスを割り当てること自体は問題ありません）
- Azure ロードバランサーを利用しない場合（外部からのアクセス振り分けがサポート対象外となります）

## 1.6. 関連資料
- RHEL8
    - [高可用性クラスターの設定および管理](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html-single/configuring_and_managing_high_availability_clusters/index)
- RHEL7
    - [High Availability アドオンの概要](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html-single/high_availability_add-on_overview/index)
    - [High Availability Add-On リファレンス](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html-single/high_availability_add-on_reference/index)

# 2. 事前検討
Azure 環境において冗長構成を構築する上で、事前に検討しておくべき事項を示します。

| 項目 | 選択肢・設定項目など | 推奨構成 | 
| --- | --- | --- |
| OS の種類 | 1. CentOS Stream 8 または CentOS Linux 7.x 系<BR>2. RHEL 8.x 系 または 7.x 系 | CentOS Stream 8 または RHEL 8.x 系 |
| VM の種類や構成 | メモリ8GB以上の VM サイズ | B2MS 以上 |
|  | なるべく高速なストレージ | SSD |
| VM の配置 | リージョンの選択（東日本／西日本など） | 東日本リージョン |
|  | 可用性ゾーンを利用する／しない | 可用性ゾーンを「利用する」 |
|  | 仮想ネットワークの構成 | 「単一仮想ネットワーク」に配置する |
| ネットワークの設定 | ネットワークセキュリティグループ | VM 間の通信は「すべて透過」 |
|  | ネットワークインターフェースを追加する／しない | 任意 |
|  | パブリック IP アドレスの割り当て | パブリック IP を「割り当てる」 |
| フロントエンドの設定 | Azure LB を利用する／独自に LB を設置する、など | Azure LB を「利用する」 |
| ミドルウェアの設定 | Corosync の設定 | タイムアウト値を「延長する」 |
|  | STONITH を設定する／しない | STONITH を「設定する」 |

## 2.1. OS の種類
どの OS を利用するかを検討してください。**ただし、冗長構成を構築する 2 台の VM の OS は同一のものにしておいてください。**

<span style="color: #d86e00">※ 2 台の VM の OS の種類とバージョンが同一で無い場合は、サポート対象外となります。</span>

OS は以下の選択肢の組み合わせから選ぶことが出来ます。

- CentOS または RHEL
    - RHEL は Red Hat 社によるサポートがありますが、CentOS に比べてコストがかかります。
- 8.x 系 または 7.x 系
    - **8.x 系の利用を推奨します**（冗長構成関連を含むいくつかのミドルウェアのバージョンが新しい・OS のサポート期間が長いため）

なお、CentOS を選択される場合、この項目の以下については関係ありません。

RHEL を選択される場合、冗長構成を組むサーバに Red Hat 社が提供する HA add-on が必要になります。Azure においては HA add-on が付属した VM がいくつか用意されていますので、**HA add-on 付き仮想マシンを利用することを推奨します**。HA サブスクリプションを別途購入して、Azure に持ち込むことも可能かと思われますが、本記事の対象外です。

- [HA 付きの RHEL 仮想マシンの価格](https://azure.microsoft.com/ja-jp/pricing/details/virtual-machines/rhel-ha/)
- [RHEL 8 with HA add-on](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/redhat.rhel-ha)

※ (v1.6追記) RHEL 7.x with HA add-on は Microsoft のサポートが切れたため、推奨仮想マシンから除外しました。

<span style="color: #d86e00">注意：RHEL を用いて冗長構成を構築するときに、後述する STONITH を設定していない（または有効にしていない）場合、Red Hat 社のサポート対象外になることに注意してください。</span>

- [Support Policies for RHEL High Availability Clusters - General Requirements for Fencing/STONITH](https://access.redhat.com/articles/2881341)

## 2.2. VM の種類や構成
どの VM の種類（サイズ）を利用するか、またどういった構成をとるかについて検討してください。**ただし、冗長構成を構築する 2 台の VM の種類や構成は同一にしてください**。

<span style="color: #d86e00">※ 2 台の VM の種類や構成が同一で無い場合は、サポート対象外となります。</span>

まず VM の種類では、Kompira のハードウェア要件のうちメモリについて**「メモリ：8GB以上」**となっていることに、ご注意ください。

上記の仮想マシン価格表で言えば「B2MS」が最小になります。動作させるジョブフローの特性（メモリ使用量が多くなりそう、CPU負荷が高そう、など）に合わせて、利用する VM の種類について検討してください。

次に VM の構成として、「ディスク」についてはその**ストレージの種類としてできれば高速なもの（HDD よりは SSD）を選択することを推奨します**。Kompira はすべてのオブジェクト情報をデータベースに記録して動作するため、I/O 性能によってシステム全体の動作速度に影響を与えることがあります。

また、データベースのサイズが大きくなる見込みの場合は、追加ディスクを割り当ててそこに Postgresql のデータベースクラスタを配置する、あるいは作成済みのデータベースクラスタを移動させる、といったことを検討してください（追加ディスクの設定やデータベースクラスタの配置については本記事の対象外です）。

どの仮想マシンを利用すれば・どういった構成をとれば性能面で十分であるかは一概に示すことは出来ませんので、**実運用を開始する前に実際のジョブフローでの性能評価**などを行なって、必要であればより高性能な仮想マシンに変更する・より高速なストレージを選択する、といったことを検討してください（OS やミドルウェアのチューニングについては本記事の対象外です）。

VM の種類や構成によってコストが大きく変わりますので、非機能要件とコストのバランスを検討してください。

## 2.3. VM の配置
Kompira の冗長構成はサーバ2台で構築します。それぞれのVMをどのように配置するかを検討するかを検討してください。具体的には、リージョンの選択、可用性ゾーンを利用するか否か、仮想ネットワークの構成などが課題となります。

※ なお、現時点では、<span style="color: #d86e00">異なるリージョンをまたいだ冗長構成には対応しておりません</span>。

### 2.3.1. リージョンの選択
まず、ご利用になるリージョンを選択してください。多くの場合、東日本リージョンあるいは西日本リージョンを選択されると思います。日本においては東日本が「推奨リージョン」であり後述する「可用性ゾーン」が利用できますが、西日本は「代替リージョン」であり「可用性ゾーン」が利用できません。弊社では**「可用性ゾーン」を用いて冗長構成を構築することを推奨しますので、推奨リージョン（すなわち東日本リージョン）の利用が適合します**。

可用性ゾーンを利用しない構成を選択する場合は、代替リージョンの選択も可能であり、サポート対象となります。
本記事では、東日本リージョンを利用した構築手順を示します。

### 2.3.2. 可用性ゾーンの検討
Azure では推奨リージョンにおいて「可用性ゾーン(Availability Zones)」が利用できます。可用性ゾーンは Azure リージョン内でのデータセンタレベルの障害に対して高い可用性を提供するサービスということで、可用性ゾーンをまたがって冗長構成を構築することで可用性の向上が期待できます。

- [Azure のリージョンと Availability Zones](https://docs.microsoft.com/ja-jp/azure/availability-zones/az-overview)
- [Azure での Availability Zones をサポートしているリージョン](https://docs.microsoft.com/ja-jp/azure/availability-zones/az-region)

システム全体としての可用性向上のため、Azure で冗長構成を構築する場合は、**可用性ゾーンを利用して異なるゾーンに配置することを推奨**します。

ただし、可用性ゾーンを利用する構成ではコスト増加が見込まれます。また、2021年2月1日から、可用性ゾーンをまたいだデータ転送に対して課金が開始されることも Microsoft から発表されていますので、可用性とコストのバランスを検討してください。

- [帯域幅の料金詳細](https://azure.microsoft.com/ja-jp/pricing/details/bandwidth/)

なお、可用性をそこまで重視しない場合は、可用性ゾーンを利用しない構成も可能であり、サポート対象となります。
本記事では、可用性ゾーンを利用した構築手順について示します。

### 2.3.3. 仮想ネットワークの検討
一般的にクラウド環境では VM を配置する仮想ネットワークを指定できるようになっています。VM を異なる仮想ネットワークに配置することでネットワーク的に分離させることや、そのうえでルーティングを設定して相互に通信できるようにすることも可能であると思います。しかし、Azure 上で冗長構成を構築するときは、**2 台のVMを同一の仮想ネットワークに配置してください**。また、**ネットワークインターフェースは同一サブネットに接続することを推奨します**。同一サブネットに接続していない構成については、本記事の対象外です。

<span style="color: #d86e00">異なる仮想ネットワークに配置した VM 間で冗長構成を組むことも可能かもしれませんが、サポート対象外となります。</span>

VM を作成したときに、ネットワークインターフェースに対してローカル IP アドレスが自動的に割り当てられると思います。VM 間通信は基本的にはこのローカル IP アドレスを用いて互いに通信しますので、これが IP リーチャブルであることは必須です。同一仮想ネットワーク上に VM を配置して、同一サブネットにネットワークインターフェースを関連付けていれば問題ないはずです。

Kompira の冗長構成において、この **VM 間通信に利用するローカル IP アドレスは利用期間中は（VM再起動などにおいても）変化しないことを想定しています**。一般的には再起動などではアドレスの割り当てが変化することはないとおもいますが、利用期間中に VM を停止させることが考えられる場合は、静的にアドレス割り当てることもご検討ください。

なお、ネットワークインターフェースに割り当てた<span style="color: #d86e00">パブリック IP アドレスを用いた冗長構成も可能かもしれませんが、本記事の対象外であり、また、サポート対象外となります</span>。

## 2.4. ネットワークの設定
### 2.4.1. ネットワークセキュリティグループの設定
クラウド環境では仮想ネットワークや VM ごとのセキュリティ対策のひとつとして、特定の通信を遮断したり・透過させたりする、いわばファイアーウォールの設定ができるものがあります。Kompira の冗長構成では、**VM 間の通信はすべてのプロトコル・すべてのポートを通過するように設定することを推奨**します。

Azure であれば「ネットワークセキュリティグループ」が該当しますが、規定のセキュリティ規則である「AllowVnetInBound」と「AllowVnetOutBound」が有効であり、それらより高い優先度に遮断させる設定がなければ問題ありません。冗長構成を構築するときに、既存のネットワークセキュリティグループを流用する場合は、注意してください。

なお、仮想ネットワーク内の通信においても特定ポートのみを通信許可させたいといった場面もあると思いますが、その具体的な設定方法については本記事の対象外です。

本記事では、規定のセキュリティ規則により VM 間通信がすべて透過である前提での構築手順を示します。

### 2.4.2. ネットワークインターフェースの追加
VM 間通信用のネットワークインターフェースを追加するかを検討してください。

Azure 環境で冗長構成を構築するうえで、**VM 間通信用のネットワークインターフェースを追加するかどうかは任意となります**。ただし、追加する場合は以下に注意してください。

- 2 台の VM 両方にネットワークインターフェースを追加してください。
- 追加するネットワークインターフェースは同じサブネットに関連付けてください。
- 冗長構成のセットアップ時には、**VM 間通信用に追加したネットワークインタフェースに割り当てられたローカル IP アドレスを利用してください**。

以下は、補足的な説明となります。

一般的には冗長構成ではサーバ間の通信が安定的に行われることが重要であるため、専用のネットワークインターフェースを（できれば複数）用意してサーバ間を直結するような構成が推奨されています。これは、サーバ間以外の通信トラフィックによる影響をなるべく受けないようにすること、またネットワークインターフェースに故障が生じても通信が継続できるようにすること、などが意図されています。

ただし、仮想化環境においては VM のネットワークインターフェースは仮想化されていて、単独で故障する可能性は物理環境にくらべて低いと考えられます。一方で、VM 間の通信自体についてはこれも仮想化されていることから、仮想的なネットワーク構成を独立させていたとしても、外部の影響を受けうることは十分に考えられます。そうした影響により、冗長構成が過敏に障害であると誤検知してしまうのを軽減するために「Corosync の設定」も参照してください。

本記事では、VM 間通信用のネットワークインターフェースを追加する場合の構築手順を示します。

### 2.4.3. パブリック IP アドレスの割り当て
各 VM にパブリック IP アドレスを割り当てるかを検討してください。

構築時や運用時に Azure の外部から VM にアクセスする場合は、パブリック IP アドレスを割り当ててください。構築時のみに VM への外部アクセスが必要であるような場合は、構築作業が完了したのちにパブリック IP アドレスを開放（または削除）することも可能ですが、その手順などについては本記事の対象外です。

本記事では、各 VM のメインネットワークインターフェースにパブリック IP アドレスを割り当てる場合の手順を示します。

## 2.5. フロントエンドの設定
Kompira の冗長構成はアクティブ・スタンバイ方式であり、ある時点では 2 台のサーバのうちいずれかがアクティブ状態となり、もう一方がスタンバイ状態となります。アクティブ状態のサーバは実際にジョブフローを動作させたり、外部からブラウザでアクセスできるようになります。2 台のサーバは異なる IP アドレスを持っているため、外部からアクセスするときにアクティブなサーバを判断してその IP アドレスを指定してアクセスすることは可能ですが、これは実用性に欠けるため、何らかの方法でアクセスを振り分ける必要があります。アクセスを振り分ける代表的な方式を以下に示します。

- VIP によるアクセス振り分け
- ロードバランサーによるアクセス振り分け

### 2.5.1. VIP によるアクセス振り分け

Kompira 冗長構成の標準のセットアップでは、事前に用意した IP アドレス (VIP) をアクティブ状態のサーバに対して追加で付与する、という方式（VIP 方式）を用います。外部からは常に VIP を指定してアクセスすることで、その時にアクティブなサーバに対してアクセスできることになります。

しかし、クラウド環境では IP アドレスも管理対象のリソースであり、プラットフォームや構成によっては VIP を簡単には利用できないことがあります。

現時点では Azure で冗長構成を構築するときに、<span style="color: #d86e00">VIP 方式のアクセス振り分けには対応していません</span>。

### 2.5.2. ロードバランサーによるアクセス振り分け
VIP 方式以外のアクセス振り分け方法としては、ロードバランサーを利用することが一般的です。Azure 環境においては **Azure ロードバランサーを利用することを推奨します**。

VM が外部からアクセス可能（IP リーチャブルかつ HTTP(s) ポート透過）な構成であれば、Azure 外部に独自にロードバランサーを設置することも可能かもしれません。しかし、<span style="color: #d86e00">Azure ロードバランサーを利用しない場合は、外部からのアクセス振り分けについては、サポート対象外となります（ジョブフローなどの内部で動作する機能についてはサポート対象となります）。</span>

Azure での VM の配置としては可用性ゾーンの利用を推奨していますので、可用性ゾーンをサポートした Azure Standard Load Balancer が適合します。

- [Standard Load Balancer と可用性ゾーン](https://docs.microsoft.com/ja-jp/azure/load-balancer/load-balancer-standard-availability-zones)

本記事では、Azure Standard Load Balancer を利用した構築手順について示します。

## 2.6. ミドルウェアの設定
### 2.6.1. Corosync の設定
ハートビート通信の設定パラメータの調整を検討してください。

冗長構成では複数のノードが協調して動作する必要があるため、各ノードが正常に連携できる状態であるかを常に相互監視しています。これには例えば、他ノードが応答しない（ノード停止・ネットワーク断線など）といった状況判断を含んでいます。こうした監視を実現するため、冗長構成を管理するミドルウェアの一つである Corosync が各ノードで動作しつつ、ネットワークを通して互いの情報を交換しています。これを一般的にハートビート通信と言いますが、この通信の安定性が重要であることは言うまでもありません。

しかし、物理的なネットワークで直結するような場合に比べて、クラウド環境での通信は安定性に欠けることがあると言われています（配置によってはネットワークの遅延が大きくなったり、プラットフォームのメンテナンスの影響を受けたりする、など）。

ハートビート通信が不安定であると、たとえば実際には正常に動作している他ノードがダウンしたなどと誤検知をすることがあります。こうした誤検知をもとに、不要なフェイルオーバが開始されたり、両系がアクティブとなるスプリットブレインと呼ばれる現象が生じたりと、冗長構成全体に悪影響を与えてしまい、最悪システムが利用できない状態になってしまうことも考えられます。

誤検知をなるべく軽減するためには、Corosync のハートビート通信に関連するパラメータを調整することが有効です。基本な対策としては、故障判断に関わる**タイムアウト値を大きくする方向で調整して「故障判断を遅らせる」ことで、一時的な通信の遅延や断絶に対して過敏に反応しないようにします**。当然、本当に故障したときにもその検知が遅くなることを意味しますが、「誤検知の抑制」と「故障判断の早さ」はトレードオフになりますので、用途や要件に合わせてそのバランスを検討してください。

Corosync は様々なパラメータを調整できるようになっていますが、このなかで、先にあげたノード故障の判断に関連する重要なパラメータを以下に示します。

| パラメータ | デフォルト値 | 設定例 |備考 |
| --- | --- | --- | --- |
| totem.token | 1000 | 30000 | トークンを受信しなかった後にトークンの損失が宣言されるまでの時間（ミリ秒） |
| totem.consensus | 1200 | 36000 | メンバーシップ構成の新しいラウンドを開始する前にコンセンサスが達成されるまで待機する時間（ミリ秒） |
| totem.join | 50 | 1000 | メンバーシッププロトコルの join メッセージを待つ時間（ミリ秒） |

他にも多数のパラメータがありますので、詳細については `corosync.conf (5)` のマニュアルを参照してください。

これらのパラメータを調整することで、ノード故障の判断を遅らせて誤検知を軽減させることができます。具体的な設定値については、個別に検討していただきたいですが、以下に推奨値を示しておきます。

#### 2.6.1.1. 推奨値
本記事ではトークン値を大きくすることで、ノードの故障判断を遅らせるように設定します。

| パラメータ | 推奨値 |
| --- | --- |
| totem.token | 30000 |

これは「 [Azure の Red Hat Enterprise Linux に Pacemaker をセットアップする](https://docs.microsoft.com/ja-jp/azure/virtual-machines/workloads/sap/high-availability-guide-rhel-pacemaker)」にある、以下の記述を参考にしています。

> 次のコマンドを実行し、ノードを認証してクラスターを作成します。 トークンを 30000 に設定してメモリ保持メンテナンスを可能にします。 詳細については、Linux の[この記事](https://docs.microsoft.com/ja-jp/azure/virtual-machines/maintenance-and-updates#maintenance-that-doesnt-require-a-reboot)を参照してください。
> ```
> sudo pcs cluster setup --name nw1-azr prod-cl1-0 prod-cl1-1 --token 30000
> ```

※ consensus 値は設定を省略した場合、token 値×1.2 が最小値として自動的に適用されます。


### 2.6.2. STONITH の設定
障害ノードを再起動させるための STONITH を利用するかを検討してください。

クラスタリングを管理する Pacemaker は、障害ノードを強制的に停止または再起動させる STONITH (Shoot The Other Node In The Head) という仕組み（フェンシングとも言います）を持っています。これは例えば、故障して応答しないノードの電源を強制的に落としたり、ネットワーク障害によって複数のノードがマスターになってしまうのを防ぐために１つのマスター以外を強制的に再起動させる、といったために利用します。

フェンシングについての更なる情報は Red Hat のドキュメントを参照してください。
    
- RHEL8
    - [フェンシングの概念](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_high_availability_clusters/con_high-availability-add-on-concepts-overview-of-high-availability#_fencing)
    - [フェンシングの設定](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_high_availability_clusters/proc_configuring-fencing-creating-high-availability-cluster)
    - [RED HAT HIGH AVAILABILITY クラスターでのフェンシングの設定](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/configuring_and_managing_high_availability_clusters/assembly_configuring-fencing-configuring-and-managing-high-availability-clusters)
- RHEL7
    - [フェンシングの概要](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/high_availability_add-on_overview/s1-fencing-haao)
    - [フェンス機能: STONITH の設定](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/high_availability_add-on_reference/ch-fencing-haar)

STONITH の仕組みや設定は複雑です。STONITH を設定しないと冗長構成として動作しないわけではありませんが、いくつかの障害ケースにおいては STONITH でしか救えないと言われています。また、STONITH が有効に設定されていることが Red Hat のサポート要件であることにはご注意ください。

#### 2.6.2.1. STONITH による相撃ち対策
STONITH は他ノードを強制的に停止または再起動させる、という強力な機能を持つために、ある場面では悩ましい課題が生じます。ネットワーク障害などによって複数のノードがマスターとなってしまう、いわゆるスプリットブレイン状態になったときに、**それぞれのノードが相手のノードが故障したと判断して相撃ちしてしまう可能性がある**ということです。この相撃ちが発生してしまうと、2台のサーバが同時に強制停止して完全にすべてのサービスが停止する、という問題が起こりえます。

この相撃ち問題を解消する方法はいくつか考えられていますが、本記事では以下の方式を紹介します。

- 本来は「故障したノードを再起動する」という一つの設定でもよいが、各ノードを再起動させる STONITH を分けて 2 つ設定する。
- それぞれの STONITH 設定で、相手ノードを再起動させるまでの遅延時間に数秒以上の差をつける。

STONITH 設定を分離して遅延時間に差をつけることで、同時に相手ノードの故障を検知した場合でも相撃ちしにくい状況にします（相撃ちを完全に防ぐことは出来ません）。

なお、この遅延時間は固定の設定となり、同時に故障を検知した場合は遅延時間の小さいノードが先に再起動することになり、遅延時間の大きいノードは生き残ることになります（再起動されたノードからの STONITH は発動しないため）。いわば STONITH の遅延時間を大きく設定されたノードが（生き残る）優先度が高くなるとも言えます。

理想的には障害検出時点でマスター状態のノードが生き残る可能性が高くなるように制御できるとよいのですが、現時点ではそのような設定方法は見出されていません。

#### 2.6.2.2. スタートアップ時のフェンシング無効化
デフォルトの STONITH の設定では、以下のような運用上の注意点があります。

- **いずれかのサーバで最初にクラスタを開始したときに、別のサーバの状態が確認できない場合に念のためにフェンシングします（再起動させてしまいます）。**

たとえば、次のようなことが起きることになります。

- プライマリとセカンダリいずれも、サーバとしては起動しているがクラスタは停止している（pacemaker が起動していない）というときに、プライマリでクラスタを開始（`pcs cluster start`）すると、セカンダリサーバを再起動させます。
- セカンダリサーバが停止（シャットダウン）している状態で、プライマリでクラスタを開始すると、セカンダリサーバを起動させます。

デフォルトでは、このように１台目のクラスタ起動時に別のサーバを強制的に再起動させてしまうことに注意してください。この**「スタートアップ時のフェンシング機能」については無効にしておくことを推奨します**。設定値 `startup-fencing` を `false` とすることで無効にできます。

#### 2.6.2.3. PROXY 環境下における STONITH の利用
Azure 環境で STONITH を利用する場合、各 VM から Azure の管理 API を呼び出せるようになっている必要があります。VM からインターネットアクセスが許可されている場合は問題ありませんが、外部アクセスを制限するようなネットワーク構成に VM を配置する場合は、Azure の管理 API を呼び出せるように HTTPS を中継するプロキシサーバを用意する必要があります。

# 3. 構築
## 3.1. 構築前の検討
先に示した事前検討すべき項目以外に、構築作業に必要な事項を確認しておきます。

### 3.1.1. ノード名の決定
VM に付けるノード名を決めておいてください。

VM に付けるノード名は任意ですが、冗長構成では 2 台を「プライマリ」と「セカンダリ」と呼称して説明しますので、区別できるようにしておいてください。プライマリ＝１号機・セカンダリ＝２号機、といったイメージで問題ありませんが、「アクティブ」と「スタンバイ」はある時点での状態によって入れ替わりますのでご注意ください（セカンダリがアクティブになることも冗長構成としては適正です）。

本記事では以下のように名称を付けます。

| 項目 | 本記事での値 |
| --- | --- |
| プライマリ機の名称 | `ke16ha2010-vm1` |
| セカンダリ機の名称 | `ke16ha2010-vm2` |

### 3.1.2. ロードバランサー名の決定
ロードバランサーの名称を決めておいてください。

本記事では以下のように名称を付けます。

| 項目 | 本記事での値 |
| --- | --- |
| ロードバランサー名称 | `ke16ha2010-lb` |

### 3.1.3. サービスプリンシパルの準備
Azure 用の STONITH デバイスである `fence_azure_arm` を利用する場合、Azure で事前の作業と後の手順に必要となる情報の確認を行なっておいてください。手順については「[Azure の Red Hat Enterprise Linux に Pacemaker をセットアップする](https://docs.microsoft.com/ja-jp/azure/virtual-machines/workloads/sap/high-availability-guide-rhel-pacemaker)」を参考にして、以下を実施してください。

- サービスプリンシパルの作成
- カスタムロールの作成
- カスタムロールのサービスプリンシパルへの割り当て

これらの手順において確認できる以下の情報は、STONITH を設定する手順において必要になりますので記録しておいてください。

| 項目 | 確認場所 | 値の例 |
| --- | --- | --- |
| リソースグループ | ご利用のリソースグループ | `Fixpoint-xxxx` |
| サービスプリンシパルのユーザー名 | 新規登録したアプリのアプリケーション ID | `e152145f-xxxx-xxxx-xxxx-ea282284695f` |
| サービスプリンシパルのパスワード | 新しいクライアント シークレットの値 | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` | 
| テナント ID | Azure Active Directory のディレクトリ ID | `59c61752-xxxx-xxxx-xxxx-a44928794411`|
| サブスクリプション ID | ご利用のサブスクリプションの ID | `91cc2f15-xxxx-xxxx-xxxx-2795f5923afe` | 

### 3.1.4. PROXY サーバの準備
STONITH を利用する場合、かつ、VM から外部に直接 HTTPS アクセスできない場合は、別途 VM からの HTTPS アクセスを中継できるプロキシサーバを用意してください。

## 3.2. 構成パラメータの整理
構築時に必要な情報として、事前検討した項目、ノードに付ける名称などを整理しておいてください。

## 3.2.1. 構成パラメータ例

| 項目 | 選択肢・設定項目など | 本記事での構成 | 
| --- | --- | --- |
| OS の種類 | CentOS / RHEL | CentOS |
| OS のバージョン | 8.x / 7.x | 8.2 |
| VM の種類や構成 | VM サイズ | B2MS |
|  | ストレージ | PremiumSSD |
| VM の配置 | リージョン | 東日本 |
|  | 可用性ゾーン | 利用する（ゾーン１とゾーン２に配置） |
|  | 仮想ネットワーク | 単一の仮想ネットワーク |
| ネットワークの設定 | ネットワークセキュリティグループ | VM 間の通信は「すべて透過」 |
|  | VM間通信用ネットワークインターフェース | 追加する |
|  | パブリック IP アドレスの割り当て | パブリック IP を「割り当てる」 |
|  | プロキシサーバ | 利用しない |
| フロントエンドの設定 | アクセス振り分け手法 | Azure Standard Load Balancer を利用する |
| ミドルウェアの設定 | Corosync の設定 | totem.token=30000 |
|  | STONITH の設定 | STONITH を設定する |
| ノード名 | プライマリ機の名称 | `ke16ha2010-vm1` |
|  | セカンダリ機の名称 | `ke16ha2010-vm2` |
| ローカル IP アドレス | プライマリ機の IP アドレス | （構築中に確認する） |
|  | セカンダリ機の IP アドレス | （構築中に確認する） |

## 3.3. 構築手順
実際に構築作業を行うときは、各環境において作業に必要な権限を持っている必要があります。

- クラウド環境の設定や操作をする場合は、必要な権限を持つアカウントで実施してください。
- VM のコンソール上で設定や操作をする場合は root 権限で実施してください。

### 3.3.1. VM のセットアップ
#### 3.3.1.1. ネットワークの準備
VM が接続する仮想ネットワークやサブネットを準備してください。

Kompira 冗長構成では単一の仮想ネットワークを利用してそこにすべてのリソースを配置します。既存の仮想ネットワークを利用するか、あるいは新しい仮想ネットワークを作成してください。

サブネットについては、少なくとも VM のメインネットワークインターフェースが接続するサブネットが 1 つは必要です（標準のサブネットである `default` で問題ありません）。VM 間通信用ネットワークインターフェースを追加する場合には、さらに別のサブネットが必要になります。これらのサブネットについて既存のものを利用するか、あるいは新しいサブネットを作成してください。

![001-仮想ネットワークの作成.png](https://image.docbase.io/uploads/1e8b35d3-7f9f-4b7d-b33c-1e1c53b604db.png =WxH)

ここでは、新しい仮想ネットワーク `ke16ha2010-vnet` を作成して、そこに２つのサブネット `ke16ha2010-subnet1` と `ke16ha2010-subnet2` を作成することにしました。それぞれのアドレス範囲と用途については以下のようにしました。

| サブネット名 | アドレス範囲 | 用途 | 
| --- | --- | --- |
| ke16ha2010-subnet1 | 10.200.1.0/24 | メインネットワークインターフェースの接続 |
| ke16ha2010-subnet2 | 10.200.2.0/24 | VM 間通信用ネットワークインターフェースの接続 |

#### 3.3.1.2. VM 作成
構成パラメータに従って、同じ構成の VM を 2 台分作成してください。

- 「OSの種類」「OSのバージョン」に合ったイメージを選択してください。
- 「リージョン」「VMの種類」「VMの配置」に合った設定を選択してください。
    - 以下では、プライマリ機として 1 台目の VM を、「可用性ゾーン １」に配置しようとしています。
- 「管理者アカウント」についてはお客様のアカウント管理のポリシーなどに合わせて設定してください。
- ネットワークセキュリティの設定については、お客様のセキュリティに関するポリシーなどに合わせて設定してください。
    - 「受信ポートの規則」や「NIC ネットワークセキュリティグループ」では設定せずに、サブネットにネットワークセキュリティグループを関連付けて設定する方法を推奨します。
- ここに記述していない設定項目については基本的にデフォルトのままであることを想定しています。

![002-仮想マシンの作成.png](https://image.docbase.io/uploads/3bf47589-aece-4a16-8599-71ea64db2a78.png =WxH)

#### 3.3.1.3. VM 間通信用ネットワークインターフェースの追加
VM 間通信用ネットワークインターフェースを追加する場合は、この段階で追加してください。各 VM で以下の手順を実施することで、ネットワークインターフェースを追加できます。

- VM を停止
- VM の「ネットワーク」タブから「ネットワークインターフェースの接続」→「ネットワークインターフェースの作成と接続」を選択してください。
    - 名前は任意に設定してください（`ke16ha2010-vm1eth1`,  `ke16ha2010-vm2eth1` など）。
    - サブネットは上で準備した VM 間通信用を指定してください。2 台の VM で同じサブネットを指定するよう注意してください。
    - NIC ネットワークセキュリティグループは「なし」を推奨します。セキュリティグループを指定する場合は、VM 間通信用サブネットにたいして設定することを推奨します。
- VM を開始

![003-NICの追加2.png](https://image.docbase.io/uploads/7bd7c225-30d2-4aab-bf78-82f3ef652193.png =WxH)

#### 3.3.1.4. ローカル IP アドレスの確認
Azure を含む一般的なクラウド環境では VM を作成したときに、ローカル IP アドレスが自動的に割り当てられます。VM 間通信はローカル IP アドレス（パブリック IP アドレスではありません）を用いて互いに通信させるために、**割り当てられたローカル IP アドレスを確認および記録しておいてください**（後のセットアップ手順で利用します）。なお、**VM 間通信用ネットワークインターフェースを追加している場合は、その追加したネットワークインターフェースに割り当てられたローカル IP アドレスを確認するようにしてください**。

![003-NICの追加3.png](https://image.docbase.io/uploads/8ab2d7f9-5678-4025-bc55-028d58443bb0.png =WxH)

本記事では、VM 間通信用ネットワークインターフェースに、以下のようにローカル IP アドレスが割り当てられたこととします。

| 項目 | 本記事での値 |
| --- | --- |
| プライマリ機のローカル IP アドレス | 10.200.2.4 |
| セカンダリ機のローカル IP アドレス | 10.200.2.5 |

### 3.3.2. Kompira のセットアップ
#### 3.3.2.1. Kompira のインストール
通常の手順に従って各VM に Kompira をインストールしてください。

- Kompira のダウンロード
- Kompira のインストール

なお、Azure で VM 作成時に「カスタムデータ」に以下のようなスクリプトを設定しておけば、Kompira を自動でインストールすることもできます。

```
#!/bin/bash
curl -LO https://bitbucket.org/kompira/package/downloads/kompira-1.6.1-bin.tar.gz
tar zxf kompira-1.6.1-bin.tar.gz
cd kompira-1.6.1-bin
./install.sh --locale-lang ja_JP.UTF-8 --locale-timezone Asia/Tokyo
```

この段階で各 VM の Kompira にアクセスできるか確認しておいてください。Azure 外部からアクセス確認する場合は、各サーバにパブリック IP アドレスが必要になります。

#### 3.3.2.2. ライセンスの導入（準備できる場合）
ライセンスを準備できる状況であれば、この段階で各 VM の Kompira にライセンスを導入しておくことをお勧めします。

- ライセンスの発行手続き
- ライセンスの導入

### 3.3.3. 冗長構成のセットアップ
Kompira をインストールしたプライマリ機およびセカンダリ機それぞれにおいて、ダウンロードした kompira パッケージに含まれる `setup_cluster.sh` を実行することで冗長構成のセットアップを行なうことができます。

#### 3.3.3.1. セットアップオプションの確認
冗長構成をセットアップするために `setup_cluster.sh` を実行するとき、事前に検討した構成パラメータを適用させるために環境変数やコマンドオプションを用いて指定しますので、その内容を確認します。

- プライマリ機およびセカンダリ機に付ける内部的な名称を指定するために、環境変数で `PRIMARY_NAME=<プライマリ機ホスト名>` および `SECONDARY_NAME=<セカンダリ機ホスト名>` のように渡します。ちなみに、この指定を省略した場合は `ha-kompira1` および `ha-kompira2` という名称がデフォルトで適用されます。
- VM間通信に利用する IP アドレスを指定するため、`--heartbeat-primary=<プライマリ機ローカルIPアドレス>` および `--heartbeat-secondary=<セカンダリ機ローカルIPアドレス>` とオプションを指定します。VM 間通信用ネットワークインターフェースを追加している場合はそのローカルIPアドレスを、追加していない場合はメインのネットワークインターフェースのローカルIPアドレスを指定することに注意してください。また、このように IP アドレスを直接指定する事を示すために `--manual-heartbeat` というオプションも合わせて指定します。
- VIP によるアクセス振り分けを行なわないため、`--without-vip` というオプションを指定します。
- Corosync の通信パラメータを調整するため、`--token=30000` というオプションを指定します。

これらのオプションなどに加えて、プライマリ機でのセットアップ時には `--primary` オプションを、セカンダリ機でのセットアップ時には `--secondary` オプションを指定して `setup_cluster.sh` を実行するようにしてください。

なお、**プライマリ機のセットアップが成功して、冗長構成としてのすべてのリソースが片系で正常に動作を開始するのを確認してから、セカンダリ機のセットアップを開始するようにしてください**。

#### 3.3.3.2. プライマリ機で setup_cluster.sh 実行
先に検討した構成パラメータをもとに、プライマリ機では以下のように setup_cluster.sh を実行します。

```
PRIMARY_NAME=ke16ha2010-vm1 SECONDARY_NAME=ke16ha2010-vm2 \
  ./setup_cluster.sh --primary \
  --manual-heartbeat --heartbeat-primary=10.200.2.4 --heartbeat-secondary=10.200.2.5 \
  --without-vip --token=30000
```

※ この段階で、プライマリ機の Kompira にアクセスできることを確認してください。

#### 3.3.3.3. セカンダリ機で setup_cluster.sh 実行
先に検討した構成パラメータをもとに、セカンダリ機では以下のように setup_cluster.sh を実行します。

```
PRIMARY_NAME=ke16ha2010-vm1 SECONDARY_NAME=ke16ha2010-vm2 \
  ./setup_cluster.sh --secondary \
  --manual-heartbeat --heartbeat-primary=10.200.2.4 --heartbeat-secondary=10.200.2.5 \
  --without-vip --token=30000
```

※ この段階で冗長構成の正常性を確認してください。またフェイルオーバや障害系の復旧が出来ることを確認しておくことを推奨します。正常性確認等の基本的な手順については「4. 冗長構成の管理」を参考にしてください。

### 3.3.4. ロードバランサーの設定
#### 3.3.4.1. ロードバランサーの作成
Azure ポータルからロードバランサーの「＋追加」 ボタンを押下して、ロードバランサーを作成してください。

- 「名前」は任意です。ここでは `ke16ha2010-lb` としました。
- 「種類」は、ここでは外部アクセスを振り分けるために「パブリック」を選択します。
- 「SKU」は、可用性ゾーンを利用するために「Standard」を選択します。
- 「パブリック IP アドレス」は既存のものを使用するか新規作成します。ここでは新規作成して `ke16ha2010` と名前を付けました。
- 「可用性ゾーン」は、VM を複数の可用性ゾーンに配置しているため「ゾーン冗長」を選択します。

![006-ロード バランサーの作成1.png](https://image.docbase.io/uploads/7067622a-6e23-4b2d-b022-00215a5d1d2f.png =WxH)

#### 3.3.4.2. バックエンドプールの設定
作成したロードバランサーの「バックエンドプール」を表示して「＋追加」ボタンで、バックエンドプールを新規作成します。

- 「名前」は任意です。ここでは `ke16ha2010-pool` としました。
- 「仮想ネットワーク」は VM を作成したときのものを選択してください。ここでは `ke16ha2010-vnet` を選択します。
- 「IP バージョン」は IPv4 を選択してください。
- 「仮想マシン」に 2 台の VM を追加してください。
    - VM 間通信用ネットワークインターフェースを追加している場合は、ある VM について複数行表示されますが、「IP 構成」の列がメインネットワークインターフェースを示している行を選択してください。

![007-バックエンドプールの作成1.png](https://image.docbase.io/uploads/86945324-e456-45b3-87a2-ec7d80a881f3.png =WxH)

![007-バックエンドプールの作成2.png](https://image.docbase.io/uploads/dbb09f95-c3c3-4414-a979-2142e27fad53.png =WxH)

#### 3.3.4.2. 正常性プローブの設定
作成したロードバランサーの「正常性プローブ」を表示して「＋追加」ボタンで、正常性プローブを新規作成します。

- 「名前」は任意です。ここでは `ke16ha2010-probe` としました。
- 「プロトコル」は `TCP` を選択し、「ポート」は `443` としてください。
- 「間隔」と「異常しきい値」を調整してください。ここではデフォルトのままとしました。

![008-正常性プローブの作成1.png](https://image.docbase.io/uploads/5f8e845f-1557-4ccd-b28c-e334f3367c2e.png =WxH)

#### 3.3.4.3. 負荷分散規則の設定
作成したロードバランサーの「負荷分散規則」を表示して「＋追加」ボタンで、負荷分散規則を新規作成します。

- 「名前」は任意です。ここでは `ke16ha2010-rule` としました。
- 「フロントエンド IP アドレス」は、ロードバランサを作成したときに割り当てられた `LoadBalancerFrontEnd` が選択されているはずですので、これをそのまま利用します。
- 「ポート」および「バックエンドポート」は `443` としてください。
- 「バックエンドプール」は上で作成した `ke16ha2010-pool` が選択されていると思いますので、これをそのまま利用します。
- 「正常性プローブ」は上で作成した `ke16ha2010-probe` が選択されていると思いますので、これをそのまま利用します。
- 他の項目については、ここではデフォルトのままとしました。

![009-負荷分散規則の追加1.png](https://image.docbase.io/uploads/f6d21344-6dd7-4bc1-87c8-bd1b080eb541.png =WxH)

#### 3.3.4.4. ロードバランサー経由での Kompira アクセスの確認
この段階で外部アクセスをアクティブ状態のサーバに振り分けるようになっているはずなので、ブラウザでロードバランサー経由で Kompira に確認できることを確認してください。

ロードバランサーに割り当てられたフロントエンド IP アドレスで直接アクセスすることもできますが、ここではフロントエンド IP アドレスとして関連付けられたパブリック IP アドレスに DNS を設定してアクセス確認を実施してみます。

パブリック IP アドレス `ke16ha2010` の「構成」タブで、「DNS 名ラベル（オプション）」に名前を設定します。ここでは `ke16ha2010` と入力して「保存」しました。

![010-パブリックIPアドレスにDNS設定.png](https://image.docbase.io/uploads/660f576c-0479-49cc-a601-a67e1cda0195.png =WxH)

これでこのパブリック IP アドレスに `ke16ha2010.japaneast.cloudapp.azure.com` という DNS 名が設定されたので、ブラウザでこのアドレスを入力してアクセスできることを確認します。なお、本記事でのロードバランサーの設定では https アクセスになることに注意してください。

![010-DNSでのロードバランサーアクセス.png](https://image.docbase.io/uploads/d8186c07-d52e-4d2a-97d1-32d54a0fabe4.png =WxH)

### 3.3.5. STONITH の設定
#### 3.3.5.1. Pacemaker への PROXY の設定
STONITH を利用する場合、かつ、VM から外部に直接 HTTPS アクセスできない場合は、事前に用意したプロキシサーバに関する情報を Pacemaker に設定する必要があります。

Pacemaker の設定ファイル `/etc/sysconfig/pacemaker` の末尾に以下の行を追加してください。このとき `<proxy>:<proxy_port>` の部分は用意したプロキシサーバのアドレスに合わせてください。

```
http_proxy=http://<proxy>:<proxy_port>
https_proxy=http://<proxy>:<proxy_port>
no_proxy="localhost,169.254.169.254"
```

この設定を適用するには Pacemaker を再起動する必要があります。以降の設定に進む前に、一度両系をスタンバイ系・アクティブ系の順に停止して、再度アクティブ系・スタンバイ系の順に開始してください。

#### 3.3.5.2. VM へのロールの割り当て
事前に準備しておいたロールを各 VM のアクセス制御（IAM）で割り当てておく必要があります。

![010-ロールの割り当ての追加.png](https://image.docbase.io/uploads/9055dc48-4f7d-44d9-9c83-4adcff7ac34c.png =WxH)

#### 3.3.5.3. STONITH デバイスの作成
事前に確認しておいたサービスプリンシパルのユーザ名やパスワードなどの情報を用いて、STONITH デバイスを作成します。

まず、両系のサーバに Azure 対応のフェンスデバイスである `fence-agents-azure-arm` をインストールする必要があります。

```
yum install -y fence-agents-azure-arm
```

次に、フェンスデバイスを作成します。これは pacemaker が起動しているいずれのノードでも実行できますが、アクティブ状態のノードで作業することを推奨しておきます。

本記事では相撃ち対策のために、STONITH を 2 つ作成してそれぞれに異なる遅延時間を指定する、という設定方法をとります。ここではプライマリ機を優先して生き残らせるために、プライマリ機を再起動させる STONITH の遅延時間を大きく、セカンダリ機を再起動させる STONITH の遅延時間を小さく、することとします。

| フェンスデバイス | 再起動対象ノード | STONITH実行ノード | 遅延時間(秒) |
| --- | --- | --- |  --- |
| res_stonith1 | ke16ha2010-vm1 | ke16ha2010-vm2 | 5 |
| res_stonith2 | ke16ha2010-vm2 | ke16ha2010-vm1 | 1 |

`pcs stonith create` コマンドで以下のように 2 つフェンスデバイスを作成します。ここで「3.1.3. サービスプリンシパルの準備」で用意した各パラメータが必要になります。また、たくさんあるパラメータのうち `pcmk_host_list` と `delay` が異なっていることに注意してください。

```
pcs stonith create res_stonith1 fence_azure_arm \
    pcmk_host_list=ke16ha2010-vm1 delay=5 \
    login="e152145f-xxxx-xxxx-xxxx-ea282284695f" \
    passwd="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
    resourceGroup="Fixpoint-xxxx" \
    tenantId="59c61752-xxxx-xxxx-xxxx-a44928794411" \
    subscriptionId="91cc2f15-xxxx-xxxx-xxxx-2795f5923afe" \
    power_timeout=240 \
    pcmk_reboot_timeout=900 \
    pcmk_monitor_timeout=120 \
    pcmk_monitor_retries=4 \
    pcmk_action_limit=3 \
    op monitor interval=3600
pcs stonith create res_stonith2 fence_azure_arm \
    pcmk_host_list=ke16ha2010-vm2 delay=1 \
    login="e152145f-xxxx-xxxx-xxxx-ea282284695f" \
    passwd="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
    resourceGroup="Fixpoint-xxxx" \
    tenantId="59c61752-xxxx-xxxx-xxxx-a44928794411" \
    subscriptionId="91cc2f15-xxxx-xxxx-xxxx-2795f5923afe" \
    power_timeout=240 \
    pcmk_reboot_timeout=900 \
    pcmk_monitor_timeout=120 \
    pcmk_monitor_retries=4 \
    pcmk_action_limit=3 \
    op monitor interval=3600
```

次に、それぞれの STONITH が自身を再起動するノードでは起動しないように、リソースの場所制約を設定します。これにより、`res_stonith1` は `ke16ha2010-vm2` で起動し、`res_stonith2` は `ke16ha2010-vm1` で起動するようになります。

```
pcs constraint location res_stonith1 avoids ke16ha2010-vm1
pcs constraint location res_stonith2 avoids ke16ha2010-vm2
``` 

スタートアップ時のフェンシングを無効化するために、プロパティ `startup-fencing` を `false` にセットします。

```
pcs property set startup-fencing=false
```

最後に STONITH を有効化するために、プロパティ `stonith-enabled` を `true` にセットします。
    
```
pcs property set stonith-enabled=true
```

#### 3.3.6. pacemaker 自動起動設定の解除
マスター状態で動作していたノードが電源オフあるいは STONITH で強制再起動させられたような場合も、スレーブ動作していたノードがフェイルオーバしてマスター動作を引き継ぎます。しかし、元々マスターで動作していたノード（とくに故障などはしていなかったと仮定）を起動後そのまま冗長構成に参加させると Postgresql がマスター同士のために、レプリケーション接続でエラーが発生してフェイルオーバした現在のマスターノードがダウンしてしまう場合があります。

再起動ノードのクラスタ復帰は慎重に作業するべき作業になるので、pacemaker サービスおよび corosync サービスの自動起動設定を解除しておくことを推奨します。

```
systemctl disable pacemaker
systemctl disable corosync
```

ただし、1 台目のサーバを起動したときもクラスタが自動起動しなくなりますので、以下のコマンドで起動させてください。

```
pcs cluster start
```

<span style="color: #d86e00">※ なお、STONITH が有効で、かつ、スタートアップ時のフェンシングを無効にしていない場合は、１台目のサーバを起動したときに、別のサーバを強制的に再起動させてしまうことにも注意してください。</span>

## 3.4. その他の設定手順
### 3.4.1. Pacemaker アラートの設定
冗長構成を構築していても、サーバやサービスに不具合が生じることがあります。冗長構成を管理する Pacemaker というミドルウェアは、各サーバ自体やサーバ上で動作しているサービスの動作を監視しており、その結果から状況に応じてフェイルオーバを開始するなどの制御を担っています。

冗長構成を運用するうえでは、Pacemaker が監視しているリソース（サーバ自体やサービス）の状態が変化したことの記録を取ったり、変化したことを通知してほしい、という場合があります。

Pacemaker にはアラートという機能があり、こうした状態変化のログへの記録やメールでの通知が出来ますので、その設定方法について紹介しておきます。

#### 3.4.1.1. ログの設定
Pacemaker アラートをログファイルに記録したい場合、Pacemaker に付属する `alert_file.sh.sample` というサンプルスクリプトを利用することが出来ます。

まず、各サーバ上で以下の手順を実行して、`alert_file.sh` スクリプトの有効化とログファイルの準備をしてください。なお記録するログファイル名は指定できますが、ここでは `/var/log/pacemaker_alert.log` としています。

```
install -m 0755 /usr/share/pacemaker/alerts/alert_file.sh.sample /var/lib/pacemaker/alert_file.sh
install -m 0600 -o hacluster -g haclient /dev/null /var/log/pacemaker_alert.log
```

次に、アクティブ状態のサーバ上で以下の手順を実行して、Pacemaker アラートの設定を行なってください。

```
pcs alert create id=alert_file description="Log events to a file." path=/var/lib/pacemaker/alert_file.sh \
    meta timestamp-format="%Y-%m-%d %H:%M:%S.%06N"
pcs alert recipient add alert_file id=alert_logfile value=/var/log/pacemaker_alert.log
```

停止していたセカンダリ機を復旧作業を行なってスタンバイ状態に回復したときに、`pacemaker_alert.log` に記録された内容を以下に例示します。

```
2020-10-15 18:31:02.468937: Resource operation 'notify' for 'res_rabbitmq' on 'ke16ha2010-vm2': ok
2020-10-15 18:31:02.563073: Resource operation 'notify' for 'res_pgsql' on 'ke16ha2010-vm2': ok
2020-10-15 18:31:02.863247: Resource operation 'stop' for 'res_pgsql' on 'ke16ha2010-vm2': ok
2020-10-15 18:31:05.205019: Resource operation 'stop' for 'res_rabbitmq' on 'ke16ha2010-vm2': ok
2020-10-15 18:32:05.868236: Resource operation 'start' for 'res_pgsql' on 'ke16ha2010-vm2': ok
2020-10-15 18:32:06.189398: Resource operation 'notify' for 'res_pgsql' on 'ke16ha2010-vm2': ok
2020-10-15 18:32:06.505747: Resource operation 'monitor (7000)' for 'res_pgsql' on 'ke16ha2010-vm2': ok
2020-10-15 18:32:23.243576: Resource operation 'start' for 'res_rabbitmq' on 'ke16ha2010-vm2': ok
2020-10-15 18:32:23.265452: Resource operation 'notify' for 'res_rabbitmq' on 'ke16ha2010-vm2': ok
2020-10-15 18:32:24.559497: Resource operation 'monitor (10000)' for 'res_rabbitmq' on 'ke16ha2010-vm2': ok
```

#### 3.4.1.2. メール通知の設定
Pacemaker アラートをメールで通知したい場合、Pacemaker に付属する `alert_smtp.sh.sample` というサンプルスクリプトを利用することが出来ます。

まず、各サーバ上で以下の手順を実行して、`alert_smtp.sh` スクリプトの有効してください。

```
install -m 0755 /usr/share/pacemaker/alerts/alert_smtp.sh.sample /var/lib/pacemaker/alert_smtp.sh
```

次に、アクティブ状態のサーバ上で以下の手順を実行して、Pacemaker アラートの設定を行なってください。このとき、アラートメールの送信元と送信先を指定することが出来ますので、ご利用の環境に合わせて設定してください。

```
pcs alert create id=smtp_alert path=/var/lib/pacemaker/alert_smtp.sh options email_sender=pacemaker@example.co.jp
pcs alert recipient add smtp_alert value=staff@example.co.jp
```

ただし、`alert_smtp.sh`では `sendmail` コマンドを用いてメールの送信を行ないますので、各サーバのメール配送に関する設定が適切になされていないと正しくメールが送信されない、または届かないことがありますのでご注意ください。とくにクラウド環境では迷惑メール対策として `OP25B` と呼ばれる仕組みで、外部へのメール送信がブロックされていることがあります。

- [Azure でのアウトバウンド SMTP 接続に関する問題のトラブルシューティング](https://docs.microsoft.com/ja-jp/azure/virtual-network/troubleshoot-outbound-smtp-connectivity)

アラートメールを外部に送信したい場合は必要に応じて個別に対策を行なってください。その方法などにつきましては、本記事の対象外となります。

# 4. 冗長構成の管理
## 4.1. pcs コマンドによる正常性確認
root 権限で `pcs status` コマンドを実行することで、冗長構成の状態を確認できます。

### 4.1.1. 通常運転時（両系）の正常性確認
```
[root@ke16ha2010-vm1 ~]# pcs status
Cluster name: ha-kompira-3aaaa8
Cluster Summary:
  * Stack: corosync
  * Current DC: ke16ha2010-vm1 (version 2.0.3-5.el8_2.1-4b1f869f0f) - partition with quorum
  * Last updated: Thu Oct 15 18:02:55 2020
  * Last change:  Thu Oct 15 16:58:03 2020 by root via cibadmin on ke16ha2010-vm2
  * 2 nodes configured
  * 9 resource instances configured

Node List:
  * Online: [ ke16ha2010-vm1 ke16ha2010-vm2 ]

Full List of Resources:
  * Resource Group: webserver:
    * res_memcached     (systemd:memcached):    Started ke16ha2010-vm1
    * res_httpd (ocf::heartbeat:apache):        Started ke16ha2010-vm1
    * res_kompirad      (systemd:kompirad):     Started ke16ha2010-vm1
    * res_kompira_jobmngrd      (systemd:kompira_jobmngrd):     Started ke16ha2010-vm1
    * res_lsyncd        (systemd:lsyncd):       Started ke16ha2010-vm1
  * Clone Set: res_pgsql-clone [res_pgsql] (promotable):
    * Masters: [ ke16ha2010-vm1 ]
    * Slaves: [ ke16ha2010-vm2 ]
  * Clone Set: res_rabbitmq-clone [res_rabbitmq]:
    * Started: [ ke16ha2010-vm1 ke16ha2010-vm2 ]

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
```

- チェックポイント
    - `Online:` に 2 台表示されている。
    - リソースグループ `webserver` の全てのリソースが `Started` になっている。
    - クローンセット `res_pgsql-clone` で、`Masters:` と `Slaves:` に1台ずつ表示されている。
    - クローンセット `res_rabbitmq-clone` で、`Started:` に 2 台表示されている。

### 4.1.2. 縮退運転時（片系）の正常性確認

```
[root@ke16ha2010-vm1 ~]# pcs status
Cluster name: ha-kompira-3aaaa8
Cluster Summary:
  * Stack: corosync
  * Current DC: ke16ha2010-vm1 (version 2.0.3-5.el8_2.1-4b1f869f0f) - partition with quorum
  * Last updated: Thu Oct 15 18:07:26 2020
  * Last change:  Thu Oct 15 18:07:22 2020 by root via crm_attribute on ke16ha2010-vm1
  * 2 nodes configured
  * 9 resource instances configured

Node List:
  * Online: [ ke16ha2010-vm1 ]
  * OFFLINE: [ ke16ha2010-vm2 ]

Full List of Resources:
  * Resource Group: webserver:
    * res_memcached     (systemd:memcached):    Started ke16ha2010-vm1
    * res_httpd (ocf::heartbeat:apache):        Started ke16ha2010-vm1
    * res_kompirad      (systemd:kompirad):     Started ke16ha2010-vm1
    * res_kompira_jobmngrd      (systemd:kompira_jobmngrd):     Started ke16ha2010-vm1
    * res_lsyncd        (systemd:lsyncd):       Started ke16ha2010-vm1
  * Clone Set: res_pgsql-clone [res_pgsql] (promotable):
    * Masters: [ ke16ha2010-vm1 ]
    * Stopped: [ ke16ha2010-vm2 ]
  * Clone Set: res_rabbitmq-clone [res_rabbitmq]:
    * Started: [ ke16ha2010-vm1 ]
    * Stopped: [ ke16ha2010-vm2 ]

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
```

- チェックポイント
    - `Online:` に少なくとも1台表示されている。
    - リソースグループ `webserver` の全てのリソースが `Started` になっている。
    - クローンセット `res_pgsql-clone` で、`Masters:` に 1 台表示されている。
    - クローンセット `res_rabbitmq-clone` で、`Started:` に 1 台表示されている。
    - `res_pgsql-clone` の `Masters:` と `res_rabbitmq-clone` の `Started:` が同じになっている。


## 4.2. 手動フェイルオーバ
両系で正常に冗長構成が動作している状態において、手動でフェイルオーバさせたい場面もあるかと思います。手動でフェイルオーバさせる方法はいくつかあります。

- アクティブ状態にあるサーバをシャットダウンする
- アクティブ状態にあるサーバ上のクラスタを停止させる

ここでは、アクティブ状態にあるサーバ上のクラスタを停止させる方法を紹介します。以下のコマンドをアクティブ状態のサーバで実行してください。

```
pcs cluster stop
```

アクティブ状態のサーバが停止して、しばらくするとフェイルオーバが開始するはずです。フェイルオーバに成功すると、これまでスタンバイ状態であったサーバがアクティブ状態に昇格して、サービスを継続します。ただし、この時点では、もともとアクティブ状態であったサーバは動作を止めているため、冗長構成としては片系での縮退運転をしている状態になりますので注意してください。

## 4.3. 障害系の復旧
片系での縮退運転になっている状態で、動作を止めていた系のサーバを冗長構成に復旧させるためには `sync_master.sh` というコマンドを実行する必要があります。このコマンドはアクティブ状態で動作中のサーバとデータベースなどの同期を行なって、適切にスタンバイ状態として動作を開始することで、両系での通常運転に復旧することを試みます。

以下はクラスタが停止しているセカンダリ機で `sync_master.sh` を実行したときの様子です。

```
[root@ke16ha2010-vm2 ~]# /opt/kompira/bin/sync_master.sh                    
[2020-10-15 18:18:42] ****: ****************************************************************
[2020-10-15 18:18:42] ****: Kompira-1.6.1:
[2020-10-15 18:18:42] ****: Start: Sync with the Master
[2020-10-15 18:18:42] ****:                      
[2020-10-15 18:18:42] INFO:     SYSTEM                   = CENT
[2020-10-15 18:18:42] INFO:     SYSTEM_NAME              = cent8  
[2020-10-15 18:18:42] INFO:     SYSTEM_RELEASE           = CentOS Linux release 8.2.2004 (Core)
[2020-10-15 18:18:42] INFO:     SYSTEM_RELEASEVER        = 8.2.2004
[2020-10-15 18:18:42] INFO:     PLATFORM_PYTHON          = /usr/libexec/platform-python
[2020-10-15 18:18:42] INFO:     PYTHON                   = /bin/python3.6
[2020-10-15 18:18:42] INFO:     SYSTEMD                  = true
[2020-10-15 18:18:42] INFO:     TMPDIR                   = /tmp      
[2020-10-15 18:18:42] ****: ----------------------------------------------------------------
[2020-10-15 18:18:42] ****: Check cluster status.
[2020-10-15 18:18:42] ****:              
[2020-10-15 18:18:43] INFO: Pacemaker is stop.   
[2020-10-15 18:18:43] ****: ----------------------------------------------------------------
[2020-10-15 18:18:43] ****: Start pacemaker service.                
[2020-10-15 18:18:43] ****:                
[2020-10-15 18:18:43] INFO: Start service: pacemaker
[2020-10-15 18:18:43] VERBOSE: run: systemctl start pacemaker        
[2020-10-15 18:18:43] INFO: Waiting Current DC                             
[2020-10-15 18:18:46] INFO: Pacemaker has stablized.               
[2020-10-15 18:18:46] INFO: HA_LOCALNAME=ke16ha2010-vm2 
[2020-10-15 18:18:46] INFO: HA_OTHERNAME=ke16ha2010-vm1            
[2020-10-15 18:18:47] WARN: PostgreSQL is stop (rc=2)
[2020-10-15 18:18:47] INFO: Pacemaker is running (SLAVE)       
[2020-10-15 18:18:47] INFO: Waiting for the resources to stabilize.
    PostgreSQL   | RabbitMQ                                      
    -1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
    -1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
    -1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
    -1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1      
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1 
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1                             
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1                                      
     1000,  1001 |                  #NA, rabbit@ke16ha2010-vm1
     1000,  1001 | rabbit@ke16ha2010-vm2, rabbit@ke16ha2010-vm1
[2020-10-15 18:19:07] INFO: Resources stabilized.
[2020-10-15 18:19:07] INFO: PostgreSQL is running as a hot standby.   
[2020-10-15 18:19:07] INFO: PostgreSQL on this node is running as a Slave.
[2020-10-15 18:19:07] INFO: Enter the pacemaker in maintenance mode.  
[2020-10-15 18:19:07] VERBOSE: run: pcs property set maintenance-mode=true            
[2020-10-15 18:19:08] VERBOSE: run: crm_failcount -r res_vip -D       
Resource 'res_vip' not found                            
Error performing operation: No such device or address
[2020-10-15 18:19:08] VERBOSE: status=105                                                                                                                                                                                                       
[2020-10-15 18:19:08] VERBOSE: run: crm_failcount -r res_httpd -D
Cleaned up res_memcached on ke16ha2010-vm2      
Cleaned up res_httpd on ke16ha2010-vm2
Cleaned up res_kompirad on ke16ha2010-vm2                          
Cleaned up res_kompira_jobmngrd on ke16ha2010-vm2                                           
Cleaned up res_lsyncd on ke16ha2010-vm2
[2020-10-15 18:19:08] VERBOSE: run: crm_failcount -r res_kompirad -D
Cleaned up res_memcached on ke16ha2010-vm2
Cleaned up res_httpd on ke16ha2010-vm2
Cleaned up res_kompirad on ke16ha2010-vm2
Cleaned up res_kompira_jobmngrd on ke16ha2010-vm2
Cleaned up res_lsyncd on ke16ha2010-vm2
[2020-10-15 18:19:08] VERBOSE: run: crm_failcount -r res_kompira_jobmngrd -D
Cleaned up res_memcached on ke16ha2010-vm2
Cleaned up res_httpd on ke16ha2010-vm2
Cleaned up res_kompirad on ke16ha2010-vm2
Cleaned up res_kompira_jobmngrd on ke16ha2010-vm2
Cleaned up res_lsyncd on ke16ha2010-vm2
[2020-10-15 18:19:08] VERBOSE: run: crm_failcount -r res_lsyncd -D
Cleaned up res_memcached on ke16ha2010-vm2
Cleaned up res_httpd on ke16ha2010-vm2
Cleaned up res_kompirad on ke16ha2010-vm2
Cleaned up res_kompira_jobmngrd on ke16ha2010-vm2
Cleaned up res_lsyncd on ke16ha2010-vm2
[2020-10-15 18:19:08] VERBOSE: run: crm_failcount -r res_memcached -D
Cleaned up res_memcached on ke16ha2010-vm2
Cleaned up res_httpd on ke16ha2010-vm2
Cleaned up res_kompirad on ke16ha2010-vm2
Cleaned up res_kompira_jobmngrd on ke16ha2010-vm2
Cleaned up res_lsyncd on ke16ha2010-vm2
[2020-10-15 18:19:08] VERBOSE: run: crm_failcount -r res_rabbitmq -D
Cleaned up res_rabbitmq:0 on ke16ha2010-vm2
Cleaned up res_rabbitmq:1 on ke16ha2010-vm2
[2020-10-15 18:19:08] INFO: Exit the pacemaker from maintenance mode.
[2020-10-15 18:19:08] VERBOSE: run: pcs property set maintenance-mode=false
[2020-10-15 18:19:09] INFO: PostgreSQL is running as a hot standby.
[2020-10-15 18:19:09] INFO: Pacemaker is running (SLAVE)
[2020-10-15 18:19:09] INFO: Waiting for the resources to stabilize.
    PostgreSQL   | RabbitMQ
     1000,  1001 | rabbit@ke16ha2010-vm2, rabbit@ke16ha2010-vm1
[2020-10-15 18:19:09] INFO: Resources stabilized.
[2020-10-15 18:19:09] INFO: Display failcount for each resources.
scope=status  name=fail-count-res_vip value=0
scope=status  name=fail-count-res_httpd value=0                   
scope=status  name=fail-count-res_kompirad value=0
scope=status  name=fail-count-res_kompira_jobmngrd value=0
scope=status  name=fail-count-res_lsyncd value=0
scope=status  name=fail-count-res_memcached value=0
scope=status  name=fail-count-res_pgsql value=0
scope=status  name=fail-count-res_rabbitmq value=0                   
[2020-10-15 18:19:09] INFO: Display constraint setings of resources.
Location Constraints:                 
Ordering Constraints:                    
  promote res_pgsql-clone then start webserver (kind:Mandatory)
  Resource Sets:                       
    set res_rabbitmq-clone role=Started set webserver               
Colocation Constraints:                    
  webserver with res_pgsql-clone (score:INFINITY) (rsc-role:Started) (with-rsc-role:Master)
  res_pgsql-clone with res_rabbitmq-clone (score:INFINITY) (rsc-role:Master) (with-rsc-role:Started)
Ticket Constraints:                                                        
[2020-10-15 18:19:10] INFO: Display state of resources.            
  * Resource Group: webserver:                          
    * res_memcached     (systemd:memcached):    Started ke16ha2010-vm1
    * res_httpd (ocf::heartbeat:apache):        Started ke16ha2010-vm1
    * res_kompirad      (systemd:kompirad):     Started ke16ha2010-vm1
    * res_kompira_jobmngrd      (systemd:kompira_jobmngrd):     Started ke16ha2010-vm1
    * res_lsyncd        (systemd:lsyncd):       Started ke16ha2010-vm1
  * Clone Set: res_pgsql-clone [res_pgsql] (promotable):
    * Masters: [ ke16ha2010-vm1 ]              
    * Slaves: [ ke16ha2010-vm2 ]                  
  * Clone Set: res_rabbitmq-clone [res_rabbitmq]:         
    * Started: [ ke16ha2010-vm1 ke16ha2010-vm2 ]
[2020-10-15 18:19:10] ****:                        
[2020-10-15 18:19:10] ****: Finish: Sync with the Master (status=0)
[2020-10-15 18:19:10] ****: ****************************************************************
```

最終的に `status=0` で正常終了しており、冗長構成が正常に復旧したことがわかります。

### 4.3.1. マスターノードが電源オフあるいは強制再起動した場合の sync_master による復旧時の注意

マスター状態で動作していたノードが電源オフあるいは STONITH で強制再起動させられるような場合、Postgresql のディスク上の状態はマスター動作していたときのままとなっています。再起動後にフェイルオーバが成功しているクラスタに参加させると、Postgresql がマスター同士であるためレプリケーション接続でエラーが発生してフェイルオーバした現在のマスターノードがダウンしてしまう場合があります。

こうした事態が想定されるときは、再起動したノードで sync_master.sh を実行する前に、手動でデータベースを現在のマスターからコピーしておくことを推奨します。

```
rm -rf /var/lib/pgsql/12/data.old
mv -f /var/lib/pgsql/12/data /var/lib/pgsql/12/data.old
(cd /; sudo -u postgres pg_basebackup -h ha-kompira-other -U repl -D /var/lib/pgsql/12/data -X stream -P)
```

