高可用性機能を設定する

標準のWhatsApp Business APIクライアントのソリューションは、単一のDockerコンテナ上で動作します。複数のDockerコンテナを実行すると、問題が発生してアカウントが一時的に使用禁止になります。このガイドでは、高可用性を設定することにより、主要Dockerコンテナがダウンした場合に備えて複数のDockerコンテナをスタンバイさせておく方法について説明します。

この高可用性ソリューションでは、既存のWhatsApp Business APIクライアントの単一インスタンスインストールを追加実行する必要があります。WhatsApp Business APIクライアントの電話番号をまだ設定していない場合は、このソリューションに進む前に、インストールに関するドキュメントを確認してください。

概要

ハイアベイラビリティクラスタを構成するには、次の図に示すようにマスターノード2台以上、コアアプリノード2台以上が必要です。

ハイアベイラビリティクラスタ

ノードはすべて異なるマシンまたはラックで運用することが推奨されます。1台のマシンまたはラックで障害が発生した場合、同時に複数のノードに影響が及ぶのを避けるためです。

起動

クラスタが起動すると、すべてのマスターノードがプライマリマスターになるためのマスターリースを獲得しようとします。1台のみがマスターリースを獲得し、残りはセカンダリマスターとなります。クラスタ内のマスターノードの数をNとしたとき、プライマリマスターは1台、セカンダリマスターはN-1台となります。プライマリマスターは、登録、データベーススキーマのアップグレード、構成変更の配信開始、データベース統計のレポーティング、クラスタ管理などの役割を担います。プライマリマスターがダウンしてマスターリースを失うと、その他のセカンダリm = マスターがプライマリマスターの立場を引き継ごうとします。

そのうちの1台がプライマリマスターになると、最初にデータベースからシャードマップテーブルを読み込んで現在のプライマリコアアプリがどれかを学習します。クラスタ内に1台もプライマリコアアプリがない場合、ウェブアプリがどのコアアプリノードにAPIリクエストを送信すべきか検索できるよう、プライマリマスターが正常に動作しているセカンダリコアアプリ1台をプライマリコアアプリにプロモートし、データベースのシャードマップテーブルをアップデートします。これにより、たとえすべてのマスターがダウンしてもコアアプリノードでAPIリクエストを処理し、高可用性を実現できます。

コアアプリノードは起動するとセカンダリコアアプリとして動作し、プライマリマスターによってプロモートされて初めてWhatsAppサーバーに接続するためのプライマリコアアプリとなります。プライマリコアアプリになると、APIリクエスト処理の役割を担います。

データベースに基づくモニタリング

各コアアプリノードは毎分データベースをアップデートすることで動作中であることを示します。プライマリマスターは定期的にデータベースをチェックして障害が発生しているコアアプリノードを検出します。プライマリコアアプリによりデータベースのアップデートが行われない時間が2分を超えた場合、プライマリマスターは障害が発生していると見なし、他のコアアプリノードをプライマリにプロモートします。これにより、ダウンタイムは約2分となります。

ハートビートに基づくモニタリング

クラスタ内に動作中のマスターが複数ある場合、ハートビートに基づくモニタリングにより、データベースに基づくモニタリングよりも短時間でノード障害を検出できます。ハートビートに基づくモニタリングでは、すべてのマスターがコアアプリノードに5秒間隔で(heartbeat_intervalにより設定)ハートビートを送信することでコアアプリノードをモニタリングします。プライマリコアアプリからプライマリマスターとセカンダリマスター1台への応答が30秒間(unhealthy_intervalにより設定)途絶えた場合、障害が発生していると見なし、プライマリマスターは正常に動作しているセカンダリコアアプリ1台をプライマリコアアプリにプロモートします。これにより、ダウンタイムはデフォルトで約30秒となります。ダウンタイムの短縮が望ましい場合には、unhealthy_interval値を下げることができます。ペイロードの例については、設定のドキュメントをご覧ください。

初期設定

ハイアベイラビリティクラスタには、Webapp、Master、Coreappの3種類のノードがあります。それらは、別々のマシンで別個に起動可能ですが、互いにやり取りするためには同じネットワーク内になければなりません。

Webappノードは、オリジナルのWebappコンテナなどのAPIトラフィックの処理を担当します。Coreappノードは、WhatsAppとの間のメッセージングトラフィックの処理を担当します。最後のMasterノードは、クラスタ内のCoreappノードのモニタリングを担当します。あるCoreappノードが死んだら、トラフィックを別のCoreappノードにリダイレクトして高可用性を確保します。クラスタ内に複数のWebappノード、Coreappノード、Masterノードが存在する場合もあります。

アクティブノードを、スレーブノードとは呼ばなくなりました。それらはCoreappノードと呼ばれます。

注: 多くの場合、本番環境では、CoreappコンテナやWebappコンテナとは別の物理サーバーでデータベースを稼働するべきです。真の高可用性実現のため、Master、Webapp、およびCoreappの各コンテナをそれぞれ別個の物理マシン上で実行することをおすすめします。

メディアメッセージ用の共有ファイルシステムを設定する

メディアメッセージを扱うことがない場合、この手順はスキップしてください。

メディアメッセージの送受信をサポートするためには、NFSファイルシステムを設定し、それをWebapp、Master、Coreappの各ノードのローカルディレクトリにマウントすることが必要です。その共有ディレクトリの読み取り/書き込みアクセス許可が付与されていることを確認してください。

NFS mountコマンドの例

mkdir new-local-directory
mount -t nfs nfs_server_IP_addr:/share_directory new-local-directory

Docker Composeによるインストール

このガイドでは、WhatsApp Business APIクライアントを実行するためのコンテナプラットフォームとなるDockerが必要になります。さらに、Docker Composeも必要です。Docker Composeは、macOSやWindowsの場合はDockerとバンドルになっていますが、Linuxの場合は別途インストールする必要があります。

単一サーバーでの開発者設定

  1. システム上にDockerをインストールします。
  2. Docker ComposeがDockerのインストールにバンドルされていない場合は、Docker Composeもインストールします
  3. multiconnect-compose.ymlおよびdb.envの構成ファイルWhatsApp_Configuration_Files.zipをダウンロードします。
  4. コンソールを開き、ダウンロードしたファイルを保存したディレクトリに移動します。
  5. MySQLインストールを実行している場合、MySQLの構成に応じてdb.envファイルの値を変更します。MySQLをインストールしていない場合、multiconnect-compose.ymlファイルとdb.envファイルはデフォルトの構成であり、ローカルコンテナでインスタンスを起動します。
  6. 高可用性を実現するために複数のコンテナを起動する前に、単一接続コンテナが実行されていないことを確認してください。
      docker-compose -f your-single-connect-yml-filename stop
    
  7. コンソールで次のコマンドを実行します。
    docker-compose -f multiconnect-compose.yml up
    スクリプトによってDockerイメージがダウンロードされすべてが設定されている間に、出力が得られます。コンテナをバックグラウンドで実行するには、-dパラメーターを指定します。
    docker-compose -f multiconnect-compose.yml up -d

これらのステップを実行したら、以下のコマンドを使用してコンテナが実行されていることを確認します。

docker-compose ps

デフォルトでは、Webappコンテナはポート9090で実行されます。

各コンテナのサーバーが複数ある本番設定

  1. システムにDockerをインストールします。
  2. DockerインストールにDocker Composeがバンドルされていない場合は、Docker Composeをインストールします。
  3. multiconnect-coreapp.ymlmulticonnect-master.ymlmulticonnect-webapp.yml、およびdb.env 構成ファイルであるWhatsApp_Configuration_Files.zipをダウンロードし、それぞれを対応するサーバーに保存します。
  4. 各サーバー上で、コンソールを開き、ダウンロードしたファイルを保存したディレクトリに移動します。
  5. 本番設定では、スタンドアローンのMySQLインスタンスを使用することを強くおすすめします。そうする場合、MySQLの構成に応じてdb.envファイルの値を変更します。
  6. 高可用性を実現するために複数のコンテナを起動する前に、単一接続コンテナが実行されていないことを確認してください。
    docker-compose -f your-single-connect-yml-filename stop
    
  7. それぞれ対応するマシンのコンソールで、次のコマンドを実行します。

    環境変数EXTERNAL_HOSTNAMEは、他のコンテナを実行しているマシンからアクセス可能なIPアドレスまたはホスト名でなければなりません。サービスYMLファイルで公開されているポートは、他のコンテナを実行しているマシンからの接続を受け入れる必要があります。例えば、multiconnect-coreapp.ymlCOREAPP_EXTERNAL_PORTSとして定義されているポートは、coreappコンテナを実行するホスト上で受信トラフィックを受け入れる必要があります。

    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml up # on the Coreapp server
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml up # on the Master server
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml up # on the Webapp server
    スクリプトによってDockerイメージがダウンロードされすべてが設定されている間に、出力が得られます。コンテナをバックグラウンドで実行するには、-dパラメーターを指定します。
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml up -d # on the Coreapp server
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml up -d # on the Master server
    EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml up -d # on the Webapp server

これらのステップを実行したら、以下のコマンドを使用してコンテナが実行されていることを確認します。

EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml ps # on the Coreapp server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml ps # on the Master server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml ps # on the Webapp server

同じサービスで複数実行されているインスタンスの場合(例えば、同じホスト上で2つのCoreappsが実行されている場合)、ホストポートの競合によりデフォルトのままでは動作しません。ポートの競合を回避するには、各サービスの YML ファイル(この場合はmulticonnect-coreapp.yml)を変更して、インスタンスごとに異なるホストポートを次のように公開する必要があります。

ports:
- "HOST_PORT_RANGE:6250-6253"

デフォルトでは、Webappコンテナはポート9090で実行されます。

アップグレード

単一サーバーでの開発者設定

multiconnect-compose.ymlファイルには、コンテナのバージョンを示すフィールドがあります。以下はその例です。

services: ... waweb: image: docker.whatsapp.biz/web:v2.19.4 ... master: image: docker.whatsapp.biz/coreapp:v2.19.4 ... wacore: image: docker.whatsapp.biz/coreapp:v2.19.4

インストールをアップグレードするには、multiconnect-compose.ymlファイルのバージョン番号を変更します。

services: ... waweb: image: docker.whatsapp.biz/web:v2.19.7 ... master: image: docker.whatsapp.biz/coreapp:v2.19.7 ... wacore: image: docker.whatsapp.biz/coreapp:v2.19.7

その後、Dockerコンテナを再起動します。

docker-compose -f multiconnect-compose.yml up

各コンテナのサーバーが複数ある本番設定

YAMLファイルには、コンテナのバージョンを示すフィールドがあります。以下はその例です。

services: ... waweb: image: docker.whatsapp.biz/web:v2.19.4
services: ... wacore: image: docker.whatsapp.biz/coreapp:v2.19.4

services: ... master: image: docker.whatsapp.biz/coreapp:v2.19.4

インストールをアップグレードするには、対応するファイル内でバージョン番号を変更します。

services: ... waweb: image: docker.whatsapp.biz/web:v2.19.7
services: ... wacore: image: docker.whatsapp.biz/coreapp:v2.19.7

services: ... master: image: docker.whatsapp.biz/coreapp:v2.19.7

その後、Dockerコンテナを再起動します。

EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml up # on the Coreapp server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml up # on the Master server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml up # on the Webapp server

既存ボリュームの付加

前回のインストールによるメディアボリュームがある場合は、YAMLファイルの中で、ボリューム定義

volumes:
  whatsappData:
      driver: local
  whatsappMedia:
      driver: local

を次のように置き換えます。

volumes:
  whatsappData:
      external: true
  whatsappMedia:
      external: true

バインドマウント

これは、既存のバインドマウントボリュームを維持する場合にのみ推奨されます。

ホストパス(ホスト上の既存の位置)をコンテナに直接マウントしたい場合、サービスセクション内のボリュームの行を、ホストパスをポイントするように変更してください。

wacore:
    volumes:
        /filepath/waent/data:/usr/local/waent/data
        /filepath/wamedia:/usr/local/wamedia

アンインストール

単一サーバーでの開発者設定

ノードが実行されているすべてのマシンについて、この操作を繰り返す必要があります。

すべてのコンテナを削除して開発環境をリセットする必要がある場合は、multiconnect-compose.ymlファイルを配置したディレクトリから次のコマンドを実行します。

docker-compose -f multiconnect-compose.yml down

コンテナに加え、multiconnect-compose.ymlファイル内に定義されているすべてのボリュームも削除する場合は、-vパラメーターを指定してdownを実行します。

docker-compose -f multiconnect-compose.yml down -v

各コンテナのサーバーが複数ある本番設定

すべてのコンテナを削除して開発環境をリセットする必要がある場合は、各サーバー上でYAMLファイルが含まれるディレクトリから直接次のコマンドを実行します。

EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml down # on the Coreapp server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml down # on the Master server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml down # on the Webapp server

コンテナに加え、YAMLファイル内に定義されているすべてのボリュームも削除する場合は、-vパラメーターを指定してdownを実行します。

EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-coreapp.yml down -v # on the Coreapp server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-master.yml down -v # on the Master server
EXTERNAL_HOSTNAME=MACHINE_HOSTNAME docker-compose -f multiconnect-webapp.yml down -v # on the Webapp server

トラブルシューティング用のログ

トラブルシューティングのためのログを取得するには、サーバーで以下のコマンドを実行します。

  docker-compose logs > debug_output.txt