Skip to content

クラスター負荷のリバランス

タスク対象

MQTT接続のリバランス方法。

なぜ負荷リバランスが必要か

クラスター負荷のリバランスとは、クライアント接続およびセッションをあるノード群から別のノード群へ強制的に移行する操作です。ノード間のバランスを取るために移行すべき接続数を自動的に計算し、高負荷ノードから低負荷ノードへ対応する数の接続とセッションを移行することで、ノード間の負荷分散を実現します。この操作は通常、新規ノードの参加やノードの再起動後にバランスを取るために必要となります。

リバランスの価値は主に以下の2点です:

  • システムのスケーラビリティ向上:MQTT接続は永続的な性質を持つため、クラスターのスケールアウト時に既存ノードへの接続が自動的に新規ノードへ移行されません。これを解決するために、負荷リバランス機能を使って過負荷のノードから新規追加ノードへ接続をスムーズに移行できます。このプロセスにより、クラスター全体の負荷分布が均等化され、スループット、応答速度、リソース利用率が向上します。
  • 運用コストの削減:負荷が偏っているクラスターでは、一部のノードが過負荷で他のノードがアイドル状態となることがあります。負荷リバランス機能を使うことで、クラスター内の負荷を自動調整し、作業負荷の均等化を図り、運用・保守コストを削減できます。

EMQXクラスターの負荷リバランスについては、以下のドキュメントを参照してください:Rebalancing

負荷リバランスの使い方

EMQX Operatorにおけるクラスターリバランスの対応CRDはRebalanceであり、その例は以下の通りです:

yaml
apiVersion: apps.emqx.io/v2beta1
kind: Rebalance
metadata:
   name: rebalance-sample
spec:
   instanceName: emqx-ee
   rebalanceStrategy:
     connEvictRate: 10
     sessEvictRate: 10
     waitTakeover: 10
     waitHealthCheck: 10
     absConnThreshold: 100
     absSessThreshold: 100
     relConnThreshold: "1.1"
     relSessThreshold: "1.1"

Rebalanceの設定については、以下のドキュメントを参照してください:Rebalance reference

負荷リバランスのテスト

リバランス前のクラスター負荷分布

リバランス前に、意図的に接続数が偏ったEMQXクラスターを作成し、GrafanaとPrometheusでクラスター負荷を監視しました:

グラフの通り、クラスターは4つのEMQXノードで構成されており、3つのノードはそれぞれ10,000接続を処理していますが、1つのノードは0接続となっています。

以下の例では、4つのノードすべてに負荷を均等に分散させるためのリバランス操作を実演します。

リバランスタスクの送信

リバランス処理を開始するために、Rebalanceリソースを作成します:

yaml
apiVersion: apps.emqx.io/v1beta4
kind: Rebalance
metadata:
   name: rebalance-sample
spec:
   instanceName: emqx-ee
   instanceKind: EmqxEnterprise
   rebalanceStrategy:
     connEvictRate: 10
     sessEvictRate: 10
     waitTakeover: 10
     waitHealthCheck: 10
     absConnThreshold: 100
     absSessThreshold: 100
     relConnThreshold: "1.1"
     relSessThreshold: "1.1"

ファイル名をrebalance.yamlとして保存し、以下のコマンドを実行してRebalanceタスクを送信します:

bash
$ kubectl apply -f rebalance.yaml
rebalance.apps.emqx.io/rebalance-sample created

リバランス進行状況の確認

EMQXクラスターのリバランス状況を確認するには、以下のコマンドを実行します:

bash
$ kubectl get rebalances rebalance-sample -o json | jq '.status.rebalanceStates'
{
     "state": "wait_health_check",
     "session_eviction_rate": 10,
     "recipients":[
         "emqx-ee@emqx-ee-3.emqx-ee-headless.default.svc.cluster.local",
     ],
     "node": "emqx-ee@emqx-ee-0.emqx-ee-headless.default.svc.cluster.local",
     "donors":[
         "emqx-ee@emqx-ee-0.emqx-ee-headless.default.svc.cluster.local",
         "emqx-ee@emqx-ee-1.emqx-ee-headless.default.svc.cluster.local",
         "emqx-ee@emqx-ee-2.emqx-ee-headless.default.svc.cluster.local"
     ],
     "coordinator_node": "emqx-ee@emqx-ee-0.emqx-ee-headless.default.svc.cluster.local",
     "connection_eviction_rate": 10
}

rebalanceStatesフィールドの詳細な説明は、以下のドキュメントを参照してください:rebalanceStates reference

完了まで待機

タスクの状態がCompletedになるまで監視します:

bash
$ kubectl get rebalances rebalance-sample
NAME               STATUS      AGE
rebalance-sample   Completed   62s

STATUSフィールドはRebalanceタスクのライフサイクル状態を示します:

状態意味
Processingリバランス処理が進行中です。
Completedリバランス処理が正常に完了しました。
Failedリバランス処理でエラーが発生し停止しました。

リバランス後のクラスター負荷分布

上図はリバランス完了後のクラスター負荷を示しています。クライアント接続の移行は全体を通じてスムーズかつ安定しており、クラスター全体の接続数はリバランス前と同じく10,000のままです。

リバランス前は1つのノードが0接続、3つのノードがそれぞれ10,000接続を処理していましたが、リバランス後は4つのノードすべてに均等に接続が再分配されました。各ノードの負荷は約2,500接続で安定し、一貫しています。

クラスターがバランス状態に達したかどうかは、EMQX Operatorが以下の条件を評価して判断します:

avg(ソースノードの接続数) < avg(ターゲットノードの接続数) + abs_conn_threshold
または
avg(ソースノードの接続数) < avg(ターゲットノードの接続数) * rel_conn_threshold

設定済みのRebalance閾値と実際の接続数を用いると:

  • ソースノード平均:avg(2553 + 2553 + 2554) ≈ 2553
  • ターゲットノード平均:2340
  • 条件判定:2553 < 2340 * 1.1

条件を満たすため、Operatorはクラスターがバランス状態に達したと判断し、リバランスタスクは正常に完了したと結論付けます。