クラスター機能

警告

クラスター機能は実験的機能のため、正式版では仕様が変更される可能性があります

概要

これは Sora でクラスターを構成し、冗長化、負荷分散を行うための仕組みです。

クラスター内では、ひとつのチャネル ID への接続は、担当するひとつの Sora ノードにすべて割り当てられます。 クライアントがクラスターを構成しているいずれかの Sora に接続した際には、 そのチャネル ID で、接続すべき Sora の Signaling URL を提示する仕組みです。

目的

可用性を高めるため Sora 複数台でクラスターを組み、冗長化やロードバランシングを実現します。

仕組み

Sora のクラスター機能の仕組みは、ひとつのチャネル ID への接続は、 担当するひとつの Sora ノードにすべて割り当てるものです。 これを実現するために、Sora のクラスターに参加しているそれぞれの Sora ノードは、 どのノードがどのチャネルを担当するべきかを把握しています。 そして、自分が担当でなかったら担当者にリダイレクトすることにより、 クライアントは担当ノードを意識することなく、任意のノードにアクセスするだけで担当ノードに接続できます。

特徴

注釈

これらの仕組みは sora.conf にてクラスター機能を有効にした場合に使用できます

クライアントへの複数シグナリング設定

Sora SDK にシグナリング URL を複数指定することで、いずれかの Sora ノードが正常に動作していれば Sora に繋がります。

Sora ノード選択 / ロードバランス機能

クラスターを構築している Sora ノードの中で 現在の同時接続数ライセンスの最大同時接続数 で割った値が一番小さい Sora ノードに新規チャネル ID の担当を割り当てます。 値がすべて同じ場合は接続しに行ったノードが担当します。

すでにそのチャネル ID がクラスター内部で利用されている場合は、 そのチャネル ID を担当している Sora ノードへ割り当てられます。

シグナリングのリダイレクト機能

重要

Sora の SDK を利用している場合は、基本的にここに書かれているリダイレクトの 細かい仕様を把握する必要はありません。

"type": "connect" を送った際、認証に入る前に {"type": "redirect", "location": "wss://sora1.example.com/signaling"} が戻ってくる場合があります。

この場合は送られてきたシグナリング URL に切り替えて再度 type: connect を行ってください。 その際は {type: connect, redirect: true} のように redirect: true を追加情報として入れてください。

HTTP API のリダイレクト機能

チャネル ID を指定する HTTP API を利用する場合、リダイレクトが発生することがあります。 指定されたチャネル ID を他ノードが担当している場合に、ステータスコード 307 (Temporary Redirect)の HTTP 応答により、クライアントにそのノードへのリダイレクトを要求します。

ステータス 307 の処理は HTTP のクライアントとするツールやライブラリにより異なります。 必要に応じて、リダイレクト応答の Location ヘッダーへアクセスを継続するようにしてください。

たとえば、curl コマンドの場合は、 -L オプションを指定することでリダイレクト先への再要求を行います。

クラスター自動参加機能

クラスターにノードが自動で参加する機能です。

Sora はクラスターが有効な際、起動時に sora.confcontact_node_name_list に存在する ノード名に対してクラスターの参加を自動で試みます。

そのノードが一度でもクラスターに参加したことがある場合は、そのクラスターに参加していた時の ノード一覧を利用して、クラスターへの参加を自動で試みます。

新規にクラスターを作成する場合には事前に InitCluster API を実行して、 クラスターを初期化しておく必要があります。

クラスター手動参加機能

重要

sora.confcontact_node_name_list を利用した自動参加の利用を推奨しています。

複数の Sora でクラスターを手動で組む機能です。クラスターに参加する際に JoinCluster API を叩きます。

すでにクラスターが存在している場合には、そこに参加しているノードのいずれかを引数の contact_node_name で 指定してください。クラスターに参加していて、初期化済みであれば、どのノードでもかまいません。

新規にクラスターを作成する場合には事前に InitCluster API を実行して、 クラスターを初期化しておく必要があります。

クラスター自動復旧

クラスターで利用しているネットワークに障害が発生した際、個々のノードはクラスターを構成する他のノードへの接続を試み、 復旧処理を行います。

ネットワーク分断時の接続受け付けの停止

ネットワーク分断時には Sora のノード間で通信ができず、クラスター内の情報の整合性が取れなくなる可能性があります。 不整合を回避するために、Sora は自分が過半数未満のグループに属した場合に、既存の接続を切断した上で、 新規接続の受け付けを停止します。

特定ノードへの新規チャネル ID の割り当て停止

モード機能イニシャルモード新規コネクションブロックモード または 新規セッションブロックモード になっている場合は、 そのノードに対して新規チャネル ID の割り当てを行いません。

録画情報の共有

録画の情報はクラスター内部で共有されます。 たとえば StartRecording API をあるノードに対して実行した後にそのノードが停止しても 録画情報は他のノードに残り続けます。

ポート番号の開放

以下のポート番号を開放して下さい

  • epmd(Erlang Port Mapper Daemon)で利用する TCP/IP ポート番号

    • 4369

  • ノード間通信に利用する TCP/IP ポート番号

    • 49010 - 49020

    • sora.confcluster_listen_(min|max)_port にて指定できます

注意

ライセンス

クラスターの 1 Sora ノードにつき 1 ライセンスが必要になります。 3 台の Sora ノードでクラスターを組む場合は 3 ライセンス必要になります。

注釈

最大ノード数ライセンス を利用することで、同一ライセンスを複数 Sora ノードで利用できるようになります。

クラスターのノード数

クラスター機能を有効にしている場合は 1 ノードだけでは利用できず、必ず 2 ノード以上である必要があります。

注釈

1 ノードの場合は接続を受け付けません

3 ノード以上での運用を強く推奨します。

注釈

2 ノードのクラスターでは片方のノードが停止すると、生きているノードは過半数未満となるため接続を受け付けません。 そのため 1 ノードの場合よりも可用性が落ちます。

クラスターの最大ノード数

クラスターを構築するノードの最大数は 10 ノードを想定しています。 これ以上を検討されている場合はサポートまでご連絡ください。

クラスター構成情報ファイル

危険

このファイルは Sora が内部で利用するためのファイルなので触らないでください。

Sora でクラスターを利用する場合、クラスター参加後のノード情報を永続化する data/ ディレクトリ以下にファイルを生成します。

Sora のバージョンアップ時にこのファイルをコピーする必要はありません。 ファイルが無い場合、クラスターに参加した際に生成されます。 バージョンアップ以外の場合は data/ ディレクトリを消さないでください。

クラスターからのノードの完全消去について

クラスターからノードを完全に消去させる場合は bin/sora stop で停止させた後に、 クラスターを構成してる実行中のノードのいずれかに対し、 PurgeClusterNode API を実行します。

警告

PurgeClusterNode API はクラスターからノードを完全に消去するための API です。 再参加するノードに対しては基本的に使用しないでください。

PurgeClusterNode API で完全消去したノードの再参加

警告

PurgeClusterNode API はクラスターからノードを完全に消去するための API です。 通常は、再参加するノードに対しては使用しないでください。 ここの説明は、長期間に渡ってクラスターに参加できないため、苦肉の策として PurgeClusterNode API を使った場合の説明です。

警告

PurgeClusterNode APIでクラスターから消去したノードは、 以下に示す手順を経ずに再起動してはいけません。

クラスターからノードを完全消去した場合、そのまま再度参加をすることはできません。 再度クラスターに参加をする場合は data/ ディレクトリを削除する必要があります。

PurgeClusterNode API を実行して、さらにそのノードの data/ ディレクトリを削除した場合、そのノードは 完全に新規のノードとして取り扱われます。

この状態になったノードは新規ノードですので、 JoinCluster API をつかうか、 sora.confcontact_node_name_list を利用してクラスターに参加できます。

クラスターから消去されたノードを別クラスターに参加させたい場合

あるクラスター A に参加していたノードを、A から削除して別のクラスター B に参加させたい状況を考えます。

警告

PurgeClusterNode API はクラスターからノードを完全に消去するための API です。 通常は、再利用するノードに対しては使用しないでください。 Sora が稼働するサーバーを再利用して、別のクラスター B に参加する新規ノードが欲しい場合には、 Sora リリースの tar.gz を展開して、まっさらな状態からの新規ノード構築を推奨します。 ここの説明は、どうしても既存の tar.gz 展開ディレクトリを再利用したい場合の説明です。

PurgeClusterNode API で消去されたノードは以下の 2 点で以前参加していたクラスター A のノード群を覚えています。

  • sora.conf の contact_node_name_list

  • sora 起動ディレクトリ以下の data/ ディレクトリ内のデータ

よって、再利用する場合にはこれらの情報を無くす必要があります。

  • contact_node_name_list は新しい別クラスター B のノードのリストにするか空にする必要があります

  • data/ ディレクトリは削除する必要があります

警告

以上の手順を踏まずに別クラスター B に参加させようとすると、最悪の場合には A と B がひとつになった クラスターになってしまう場合があります。

クラスター機能有効時のモード

クラスター機能を有効にした場合、 Sora は イニシャルモード という クラスター機能だけで利用される特殊なモードで起動します。

ネットワーク障害やノード障害

Sora のクラスター機能はネットワーク障害やノード障害が発生した際に、 自動で新規接続の受け付けの停止とそこからの復旧を試みます。

発生しうる問題と新規接続の受け付け停止

ネットワーク障害等が発生した場合には、 Sora のノード間で通信ができず、クラスター内の情報の整合性が取れなくなる可能性があります。

たとえば、5 ノードのクラスターが 3 ノードからなるグループ A と 残りの 2 ノードからなるグループ B の 2 グループに分断されるということが起こりえます。 それぞれのグループ内では通信ができるものの、他グループへの通信ができないという状態です。 この状態ですべてのノードが接続を受け付けると、同じチャネル ID を指定していても、 あるクライアントはグループ A に繋がり、別のクライアントは グルーブ B につながる可能性があります。 その場合はクライアント間で音声と映像が届かなくなります。

このような状況を防止するため、Sora は自分が過半数未満のグループに属した場合に、新規接続の受け付けを停止します。 特に、自分が孤立した場合もこれに含まれます。

その後、クラスター自動復旧により、通信できるノードが過半数以上となった場合には、自動で新規接続の受け付けを再開します。

新規接続の受け付けがまったくできなくなる場合

障害の状況によっては新規接続の受け付けがまったくできなくなる場合もあります。 例えばネットワークの分断によって、5 ノードのクラスターが 2 ノード、2 ノード、1 ノードという 3 つのグループに分断された状況を考えます。 この場合にはどのノードも過半数未満となるため、新規接続の受け付けはまったくできなくなります。

ネットワーク障害ではなくても、5 ノードクラスターで、3 ノードが停止してしまった場合には、残った 2 ノードは 過半数未満となるため、新規接続の受け付けはできません。

通信できるノードが過半数未満となった場合の挙動

ノード数が過半数未満のクラスターに参加しているノードは、接続中のすべての接続を切断し、その後は接続を受け入れません。

また、その時のモードによってモードが変わることがあります。

その後はクラスター自動復旧を試みます。

通信できるノードが過半数以上となった場合の挙動

通信できるノードが過半数未満から過半数以上に変わったタイミングで、そのときのモードによってモードが変わることがあります。

遷移後のモードに従って、新規接続を受け付けます。

全ノードが過半数未満に所属した場合の挙動

ネットワーク障害等が発生したことで、いずれのノードも通信できるノードが過半数未満になった場合、 新規接続はまったく受け付けられない状態になります。

この場合でも、永続化しておいたノード一覧を利用し自動でクラスターの復旧を試みます。 復旧して過半数以上のグループができた場合は新規接続が可能になります。

クラスター環境での録画

録画情報の共有

録画の情報はクラスター内部で共有されます。 たとえば StartRecording API をあるノードに対して実行した後にそのノードが停止しても 録画情報は他のノードに残り続けます。 また StopRecording API はどのノードに対しても実行できます。

たとえば、あるチャネルで StartRecording API が実行された後に、 ノード A に接続がきて録画が開始したとします。 このノード A がノード障害等で終了した後に、同じチャネルで別の接続がノード B に来た場合には ノード B で録画が進行します。

録画ファイルの出力ノード

archive-<connection_id>.json, archive-<connection_id>.webm の録画ファイルは、接続を担当するノードで 出力されます。

次のような場合には同一の recording_id に属する録画ファイルが、 複数ノードにまたがって出力されることがありますのでご注意ください。

  1. 録画開始

  2. ノード A に接続が来てしばらくして終了、録画ファイルがノード A に作られる

  3. ノード A が停止

  4. ノード B に接続が来てしばらくして終了、録画ファイルがノード B に作られる

report-<recording_id>.json ファイルの出力ノード

あるチャネルに対して、 StopRecording API を実行した場合には録画が終了し、 report-<recording_id>.json ファイルが出力されます。

このファイルの出力ノードは次のとおりです。

  • そのチャネルに接続したクライアントがひとつもなかった場合はどのノードで出力されるかは未定です

    • ただし、クラスター内のいずれかのノードで出力されます

  • そのチャネルに接続中のクライアントがいる場合は、チャネルの担当ノードで出力されます

  • そのチャネルに接続したクライアントが過去にいた場合は 2 パターンがありえます

    • クライアントが接続したノードが生存し続けている場合はそのノードで出力されます

    • ノードが落ちている、または停止した後に再起動した場合にはどのノードで出力されるかは未定です

      • ただし、クラスター内のいずれかのノードで出力されます

report-<recording_id>.json ファイルが一時的に出力されない場合

全ノードが過半数未満に所属した場合には report-<recording_id>.json ファイルが出力されません。

5 ノードのクラスターがあるとして、いくつか例を示します。

  • ネットワーク障害が発生し、2 + 2 + 1 に分断された場合

  • ノード障害(運用での停止も含む)が発生し、3 ノードが停止した場合

  • ノード障害で 1 ノードが停止した状態でネットワーク障害が発生し、 2 + 2 に分断された場合

このあとに分断が解消し、過半数以上のグループができたあとに StopRecording API を 実行すると report-<recording_id>.json ファイルが出力されます。

設定

cluster

クラスター機能を利用する場合、 sora.conf にて clustertrue を設定する必要があります。

デフォルトでは cluster は有効になっていません。

重要

cluster = true にして Sora を起動した場合、 Sora はすべての接続を受け付けない イニシャルモード モードで起動します。

自動または手動でクラスターに参加した後、過半数以上のグループになった時点で ノーマルモード へ自動で切り替わります。

cluster = true

node_name

クラスター機能を利用する際のノード名を指定して下さい。

この名前はクラスター内のノードの識別に使われます。 具体的には、クラスターノード間の通信相手の特定や、 sora.confcontact_node_name_listJoinCluster API、 PurgeClusterNode API で指定する名前として利用します。

重要

node_name はクラスター内のすべてのノードでユニークである必要があります

ノード名の @ の前には、正規表現 [0-9A-Za-z_\\-]+ にマッチする文字列を指定してください。 また @ の後ろには、サーバーのドメイン名(FQDN)や、IP アドレスを指定してください。

重要

クラスターどうしの通信は暗号化されていないため、プライベートネットワークを利用するか 暗号化されたネットワークを利用してください。

重要

@ の後ろにホスト名("." を含まない文字列)を指定すると、ノード間で通信が行えなくなってしまいます。

重要

クラスター参加後にノード名を変更する場合には、古い方の名前は PurgeClusterNode API を用いて削除してください。 また data/ のディレクトリ削除も必ずおこなってください。

詳しくは ノード名変更手順 を参照してください。

# ドメイン名を指定する例
node_name = node01@node01.example.com
# IP アドレスを指定する例
node_name = node02@192.0.2.1

contact_node_name_list

クラスター機能が有効な場合で、 sora.confcontact_node_name_list が指定されていた場合、 起動時に自分以外のノード名に対して自動でクラスターの参加を試みます。

注釈

自分自身のノード名が concact_node_name_list に含まれていても無視します。

node_name_list = sora1@192.0.2.1, sora2@192.0.2.2, sora3@192.0.2.3

cluster_auto_reconnect

クラスター機能が有効な場合で、 sora.confcluster_auto_reconnecttrue の場合、 ネットワーク障害やノード障害の発生時に自動で再接続を試みます。

この設定はデフォルトで有効です。

cluster_auto_reconnect = true

external_signaling_url

sora.conf にてシグナリングの URL を指定して下さい。 この URL はクラスター機能を利用した際に "type": "redirect""location" の値として払い出されます。

external_signaling_url = wss://node1.example.com/signaling

上記の設定をした場合は {"type": "redirect", "location": "wss://node1.example.com/signaling"} として払い出されます。

external_api_url

sora.conf にて API の URL を指定して下さい。 この URL はクラスター機能を利用した際に API を適切なノードに HTTP 307 でリダイレクトする際、 HTTP ヘッダー "location" の値として払い出されます。

external_api_url = https://node1.example.com/

cluster_listen_(min|max)_port

sora.conf にてクラスター情報の同期に利用する TCP/IP の受信ポートの範囲を指定してください。

デフォルトでは 49010 - 49020 が指定されています。

cluster_listen_min_port = 49010
cluster_listen_max_port = 49020

API

クラスター初期化 API

クラスターを構築するときは、まずクラスターの初期化を行います。

重要

クラスターの初期化はクラスターを初めて構築する際と、クラスターが破綻した際に行う必要があります。

クラスターの初期化を実行する場合は Sora_20221221.InitCluster API をクラスター構築するノードで実行します。 node_name_list にはクラスターを構成するノードを、 API を実行するノードを含め指定してください。

1 ノードだけを指定した場合には、そのノードは initial モードに留まります。 その後に JoinCluster API を実行すると normal モードに遷移します。

API の詳細は InitCluster API をご確認ください。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20221221.InitCluster \
    node_name_list:='["node-02@192.0.2.7", "node-03@10.99.0.8", "node-01@192.0.2.5"]' \
    -vvv
HTTP/1.1 200 OK
content-length: 646
content-type: application/json
date: Tue, 16 Nov 2021 08:42:25 GMT
server: Cowboy

{
    "node_name_list": [
        "node-02@192.0.2.7",
        "node-03@192.0.2.8",
        "node-01@192.0.2.5"
    ]
}

重要

クラスターのノードが恒久的に破損し、過半数以下になった場合には、 再度クラスターの初期化を行う必要があります。

詳しくは クラスター破綻からの再構築手順 を参照してください。

クラスター参加 API

Tip

sora.confcontact_node_name_list を利用したクラスターへの自動参加の利用を推奨しています。

参加するノードに対して、すでにクラスターに参加しているノードを指定してクラスターへ参加します。

API の詳細は JoinCluster API をご確認ください。

http POST 127.0.0.1:3000/ x-sora-target:Sora_20211215.JoinCluster \
    contact_node_name=sora1@192.0.2.5
HTTP/1.1 200 OK
content-length: 646
content-type: application/json
date: Tue, 16 Nov 2021 08:42:25 GMT
server: Cowboy

{
    "node_name_list": [
        "node-01@192.0.2.5",
        "node-02@192.0.2.7",
        "node-03@192.0.2.8"
    ]
}

クラスターノード完全消去 API

ある Sora ノードが障害で再参加が難しい、またはスケールインのためにノード破棄する場合は PurgeClusterNode API を利用して、そのノード情報を完全消去してください。

これはクラスターのどのノードでもかまわないので 1 回だけ実行すれば、完全消去した結果はクラスター内部で共有されます。

警告

PurgeClusterNode API はクラスターからノードを完全に消去するための API です。 再参加するノードに対しては基本的に使用しないでください。 この API を含めた運用の手順は クラスター運用 をご確認ください。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20220629.PurgeClusterNode \
    target_node_name=sora1@192.0.2.5

詳細は PurgeClusterNode API をご確認ください。

クラスターノード一覧 API

詳細は ListClusterNodes API をご確認ください。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20211215.ListClusterNodes
HTTP/1.1 200 OK
content-length: 1051
content-type: application/json
date: Tue, 16 Nov 2021 08:36:25 GMT
server: Cowboy

[
    {
        "external_api_url": "http://192.0.2.5:3000/",
        "epoch": 1,
        "license_max_connections": 600,
        "license_max_nodes": 10,
        "license_serial_code": "ABCDEF-SRA-E001-203801-400",
        "license_type": "Experimental",
        "node_name": "node-01@192.0.2.5",
        "connected": true,
        "mode": "normal",
        "external_signaling_url": "wss://node-01.example.com/signaling",
        "version": "2022.1.0"
    },
    {
        "external_api_url": "http://192.0.2.7:3000/",
        "epoch": 1,
        "license_max_connections": 600,
        "license_max_nodes": 10,
        "license_serial_code": "ABCDEF-SRA-E002-203801-400",
        "license_type": "Experimental",
        "node_name": "node-02@192.0.2.7",
        "connected": true,
        "mode": "normal",
        "external_signaling_url": "wss://node-02.example.com/signaling",
        "version": "2022.1.0"
    },
    {
        "external_api_url": "http://192.0.2.8:3000/",
        "epoch": 1,
        "license_max_connections": 600,
        "license_max_nodes": 10,
        "license_serial_code": "ABCDEF-SRA-E003-203801-500",
        "license_type": "Experimental",
        "node_name": "node-03@192.0.2.8",
        "connected": true,
        "mode": "normal",
        "external_signaling_url": "wss://node-03.example.com/signaling",
        "version": "2022.1.0"
    }
]

クラスターチャネル割り当て一覧 API

詳細は ListClusterChannels API をご確認ください。

$ http POST 127.0.0.1:3000/ x-sora-target:Sora_20211215.ListClusterChannels
HTTP/1.1 200 OK
content-length: 646
content-type: application/json
date: Tue, 16 Nov 2021 08:42:25 GMT
server: Cowboy

[
    {
        "channel_id": "sora",
        "owners": [
           {
               "node_name": "node-01@192.0.2.5",
               "epoch": 1,
               "epoch_latest": true,
               "connected": true
           }
        ]
    },
    {
        "channel_id": "lemon",
        "owners": [
           {
               "node_name": "node-01@192.0.2.5",
               "epoch": 1,
               "epoch_latest": true,
               "connected": true
           }
        ]
    },
    {
        "channel_id": "hisui",
        "owners": [
           {
               "node_name": "node-03@192.0.2.5",
               "epoch": 2,
               "epoch_latest": true,
               "connected": true
           }
        ]
    },
    {
        "channel_id": "zakuro",
        "owners": [
           {
               "node_name": "node-03@192.0.2.5",
               "epoch": 2,
               "epoch_latest": true,
               "connected": true
           }
        ]
    }
]

クラスター構築

重要

node_name はクラスター内のすべてのノードでユニークである必要があります

ライセンス

Sora ノード数分のライセンスが必要になります。 Sora 3 台でクラスターを組む場合は通常のライセンスが 3 つ、もしくは 3 ノード以上に対応した 最大ノード数ライセンスが 1 つ必要です。

ノードの未初期化、初期化済み状態

クラスターの場合、各ノードは「未初期化」または「初期化済み」の状態を持ちます。

bin/sora daemonbin/sora foreground コマンドで最初に起動したとき、そのノードは「未初期化」の 状態で起動します。

この状態のノードが「初期化済み」の状態に遷移するのは以下のどれかのイベントが発生した場合です。

  • InitClusternode_name_list に指定され、クラスターの初期化が成功した場合

    • このとき、 node_name_list に指定された他のノードも同時に「初期化済み」に遷移します

  • sora.conf の contact_node_name_list を利用した自動参加が成功した場合

  • そのノードに JoinCluster API が発行され、成功した場合

sora.conf の contact_node_name_list での参加も、JoinCluster API での参加も、 相手が「初期化済み」である必要があります。 そのため、その前に一度だけ、 InitCluster API を実行し、「初期化済み」ノードを 作る必要があります。

一度「初期化済み」に遷移したノードは、その後も「初期化済み」の状態にとどまります。

「初期化済み」から「未初期化」に遷移する手順は通常の運用では発生しませんが、 bin/sora stop で停止して、 data/ ディレクトリを削除した場合には「未初期化」状態になります。

注釈

Sora の新しいリリースバージョンに更新する場合、 tar.gz を展開した場合にも data/ ディレクトリを 古いバージョンからコピーしない場合は「未初期化」状態から始まります。

3 台での構築

ここでは、3 ノードの Sora クラスターを構築する手順を示します。

クラスター特有ではない Sora の設定や起動方法については チュートリアル を参照してください。

注釈

クラスターを構築する際、クラスター間の通信に使うネットワークは、 可能な限りプライベートネットワークを利用してください。

クラスター間の通信に使う IP アドレスは node_name の @ 以下の IP アドレスまたはドメイン名で指定します。

以下の手順の前提として、3 台のサーバーがそれぞれ TCP/IP で通信できる状態になっていること、 そして Sora の tar.gz が展開されて bin/sora が実行できるようになっていることが必要です。

  1. クラスター間の通信に必要な TCP/IP のポートをすべて開放する

    • TCP/IP 4369

      • ポート番号の変更はできません、必ずこのポートを開放してください

    • TCP/IP 49010-49020

      • sora.conf にて変更できますがデフォルトをお勧めします

  2. 最初のノード(sora1)の sora.conf の設定をクラスター対応にする

    node_name = sora1@192.0.2.101
    cluster = true
    external_signaling_url = wss://sora-node1.example.com/signlaing
    external_api_url = https://sora-node1.example.com/api
    contact_node_name_list = sora1@192.0.2.101, sora2@192.168.0.102, sora3@192.168.0.103
    
  3. 最初のノード(sora1)の Sora を起動する

  4. 次のノード(sora2)の sora.conf の設定をクラスター対応にする

    node_name = sora2@192.168.0.102
    cluster = true
    external_signaling_url = wss://sora-node2.example.com/signlaing
    external_api_url = https://sora-node2.example.com/api
    contact_node_name_list = sora1@192.0.2.101, sora2@192.168.0.102, sora3@192.168.0.103
    
  5. 次のノード(sora2)の Sora を起動する

  6. 最後のノード(sora3)の sora.conf の設定をクラスター対応にする

    node_name = sora3@192.168.0.103
    cluster = true
    external_signaling_url = wss://sora-node3.example.com/signlaing
    external_api_url = https://sora-node3.example.com/api
    contact_node_name_list = sora1@192.0.2.101, sora2@192.168.0.102, sora3@192.168.0.103
    
  7. 最後のノード(sora3)の Sora を起動する

  8. 最初のノード(sora1)の Sora に InitCluster APIを実行し、3 ノードのクラスターとして 初期化する

    $ http POST 127.0.0.1:3000/ x-sora-target:Sora_20221221.InitCluster \
        node_name_list:='["sora1@192.0.2.101", "sora2@192.168.0.102", "sora3@192.168.0.103"]'
    
  9. 最初のノード(sora1)の Sora に ListClusterNodes APIを実行し、ノード一覧を取得する

    $ http POST 127.0.0.1:3000/ x-sora-target:Sora_20211215.ListClusterNodes
    
    • 結果として、sora1 から sora3 の 3 ノードの一覧が取得できれば、クラスターの構築は完了です

構築のトラブルシューティング

クラスター構築時に躓きやすいポイントと確認事項を示します。

  • ノード間通信ができない場合

    • Sora はノード間通信を行うため、ファイアウォールの開放が必要です

    • ポート番号の開放 にあるとおりに、EPMD と sora の Listen ポートの開放を確認してください

  • ライセンス違反のエラーが出る場合

    • 最大ノード数ライセンス ではないライセンスを使っている場合には、すべてのノードで 異なるライセンスが設定されている必要があります

    • 最大ノード数ライセンス のライセンスを使っている場合には、指定されたノード数まで 同じライセンスを利用できます

    • 最大ノード数ライセンス とそうではないライセンスを混在させて利用することも可能ですが、 それぞれについて上記の条件が満たされている必要があります

  • contact_node_not_intialized エラーが出る場合

    • 未初期化のノードを contact_node_name に指定した場合に発生します

    • concact_node_name に指定するノードは InitCluster で初期化したノードか、 JoinCluster API でクラスターに参加したノードを指定する必要があります

クラスター運用

ノード数

Sora は 2 ノードからクラスターを構築できますが、 2 ノードの場合は可用性が 1 ノードの場合より低下するため、 3 ノード以上でのクラスター構築をお勧めしています。

クラスターからの一時的な離脱

モード切り替え API を利用し、 新規コネクションブロックモード または 新規セッションブロックモード に 切り替えます。 その後、すべての接続がいなくなったタイミングで Sora ノードを終了してください。

一時的に離脱したノードは、再起動するとそのままクラスターに参加して動作します。

一時的に離脱したノードを含めるクラスターノード一覧

ListClusterNodes API では現在クラスターに参加しているノード一覧が返ります。 結果に一時的に離脱したノードを含めるには、 include_all_known_nodestrue に指定し API を実行すると、そのノードが知っているすべてのノードを返します。

クラスターからノード情報の完全消去

重要

恒久的にノードを破棄する場合には、必ず、この作業を行ってください。

特定のクラスターノードが障害が起きた後、復旧が難しい場合は PurgeClusterNode API を利用して、 クラスターに参加しているノードから、障害が起きたノードの情報を完全消去してください。

また、スケールインのためにノードを破棄する場合も同様に PurgeClusterNode API を 利用して、破棄したノードの情報を完全消去してください。

この作業はクラスターの新鮮さを保つために必要な作業となります。 この作業を行わないと存在していないノードが残り続けることで過半数かどうかの判断を誤る場合があります。

警告

PurgeClusterNode API はクラスターからノードを完全に消去するための API です。 近い将来に再び参加するノードに対しては基本的に使用しないでください。

クラスターのアップデート

注釈

ローリングアップデートを推奨しています。

  1. アップデート対象の Sora ノードを ChangeMode API で 新規コネクションブロックモード または 新規セッションブロックモード に切り替えます

  2. すべての接続がなくなったら Sora を停止させます

  3. 新しいバージョンの Sora へ入れ替えます

  4. 新しいバージョンの Sora を起動します

  5. JoinCluster API を叩いて起動ノードをクラスターに参加させます( sora.confcontact_node_name_list が指定されている場合にはこの手順は不要です)

  6. ListClusterNodes API で新しいバージョンの Sora がクラスターに参加できているかを確認します

警告

自動でクラスターに参加する処理がエラーになる可能性もあるため、 ListClusterNodes API で新しいバージョンの Sora がクラスターに参加できているかを必ず確認してください。 確認せずに他ノードのローリングアップデートを行った場合、クラスターに参加できていないままのノードが出てしまう 可能性があります。 さらに、複数のノードが参加できずに過半数を割ってしまうと、クラスターがまったく稼働しなくなる可能性もあります。

上の手順を 1 ノードごとに繰り返してください。

クラスター破綻からの再構築手順

クラスターのうち、過半数のノードが停止した場合、クラスターのすべての Sora ノードは接続を受け付けなくなります。 この状態からでも、停止したノードを再開させ、過半数のノードが正常に戻ったタイミングで、接続を受け付け始めます。 その場合は、ここで書かれている手順は必要ありません。

ただし、停止したノードがディスク障害などで data/ ディレクトリを失ってしまったときや、使っていた IP アドレスが使えなくなってしまうなどの理由で、再開できないこともあります。

ここでは、3 ノードクラスターを組んでいたものの、うち 2 つのサーバーがディスク障害で data/ ディレクトリを失った状態からの再構築手順を示します。

注釈

data/ ディレクトリを失ってしまうと、「未初期化」状態になるため、再度クラスターへの参加手順が必要です。

注釈

node_name に IP アドレスを使う場合、IP アドレスが変わると node_name も変える必要があります。 その際は data/ ディレクトリを削除する必要があります。

  • まずすべての Sora プロセスを停止状態にします

  • ディスク障害がおきたサーバーでは

    • Sora をインストールしなおします

    • 必要に応じて sora.conf 設定を行います

  • ディスク障害がおきなかったサーバーでは

    • data/ ディレクトリを削除します

    • これを忘れると正しい再構築ができません、必ず削除してください

  • ここまでで、完全にまっさらの Sora クラスターを組む準備ができたことになります

  • すべての Sora ノードを起動します

  • InitCluster API を発行し、クラスターを初期化します

以上の手順で、あたらしい 3 ノードのクラスターが動き始めます。

ノード名変更手順

sora.conf の node_name を変更する際の手順を示します。

この手順は、例えば Sora が動作するサーバーの IP アドレスが変わり、 node_name の IP アドレス部分を 変更する場合に必要になります。

  • 対象の Sora ノードを停止します

  • data/ ディレクトリを削除します

    • これを忘れるとノード名変更が正しく実行できません、必ず削除してください

  • クラスターの起動しているノードのいずれかに対し、 PurgeClusterNode API を発行し、 対象のノードをクラスターから削除します

  • sora.conf の node_name を変更します

  • 対象の Sora ノードを起動します

  • JoinCluster API でクラスターにあらたに参加します

警告

この手順では、 data/ ディレクトリの削除を含むため、対象のノードは「未初期化」状態になります。 複数のノードの名前変更が必要な場合には、1 ノードずつこの手順を実行することを推奨します。 1 ノードの変更のたびに、 ListClusterNodes を使ってクラスターに正しく 参加したことを確認して次のノードの手順に取り掛かってください。

ノード名を変更する場合の contact_node_name_list の扱い

ノード名の変更をするときに、クラスター自動参加を利用する方法を示します。 クラスター自動参加を使わずに JoinCluster API を使う場合は この説明は関係しません。

関連する sora.conf の設定は contact_node_name_list です。 この設定は sora 起動時のときのみ利用されます。 また、一度クラスターに参加して初期化済みとなった場合には、正しいノードリストを知っているため、 この設定は無視されます。

以下、具体的に、3 ノードクラスターがあり、全ノードの IP アドレスが変わる状況を考えます。

状況:

  • 現状のノード名: sora1@192.0.2.101, sora2@192.168.0.102, sora3@192.168.0.103

    • 既にクラスターを組んでいる

  • それぞれを新規のノード名 sora1@10.0.0.1, sora2@10.0.0.2, sora3@10.0.0.3 に変更する

    • まず sora1 を入れ替える

    • それが成功した後に sora2 を入れ替える

    • それが成功した後に sora3 を入れ替えと進める

現状のノードでは、既にクラスターを組んでいるため concact_node_name_list は利用されません。 そのため、sora.conf の設定を変更する必要はありません。

新しいノードでは、起動時に contact_node_name_list が利用されます。 入れ替えは順番に実行する必要があるため、現状のノードのみが起動中である状態や 新規ノードのみの状態、または混在している状態がありえます。

  • 最初に sora1 を入れ替える際には、残り2ノードは現状のノード sora2@192.168.0.102, sora3@192.168.0.103 である

  • 途中で sora2 を入れ替える際には、残り2ノードは現状のノード sora3@192.168.0.103 と新規 sora1@10.0.0.1 が混在している

  • 最後に sora3 を入れ替える際には、残り2ノードは新規のノード sora1@10.0.0.1, sora2@10.0.0.2 である

このパターンに対して、ノード個別に contact_node_name_list を設定するのは複雑になってしまいます。 しかし、 contact_node_name_list に指定したノードのうち、起動していないノードは無視されますので、 既存ノードと新規ノードをすべて sora1@192.0.2.101, sora2@192.168.0.102, sora3@192.168.0.103 sora1@10.0.0.1, sora2@10.0.0.2, sora3@10.0.0.3 指定することで、全ノードの入れ替えに対応できます。

注釈

既存と新規の対応するノードが同時に起動することがないようにしてください。 たとえば、 sora1@10.0.0.1 を起動する前には、かならず sora2@192.168.0.102 を停止した上で、 sora2@192.168.0.102 再び起動することがないようにしてください。

シーケンス図

type: redirect

sequenceDiagram participant クライアント participant Sora1 participant Sora2 participant Sora3 participant アプリケーションサーバー クライアント->>Sora1: "type": "connect" Sora1->>クライアント: "type": "redirect" クライアント->>Sora2: "type": "connect", "redirect": true Sora2->>+アプリケーションサーバー: 認証ウェブフック アプリケーションサーバー-->>-Sora2: 200 OK<br />{"allowed": true} Sora2->>クライアント: "type": "offer" クライアント->>Sora2: "type": "answer" note over クライアント, アプリケーションサーバー: WebRTC 確立 Sora2->>+アプリケーションサーバー: イベントウェブフック<br />"type": "connection.created" アプリケーションサーバー-->>-Sora2: 200 OK
© Copyright 2023, Shiguredo Inc Created using Sphinx 5.3.0