Skip to content

EMQX クラスターのローリングアップデートを実行する ​

EMQX Operator 3.0 を使用して、EMQX クラスターのグレースフルなローリングアップデートを実行します。

はじめに ​

  • EMQX Operator 3.0 をインストールし、kubectl を設定して Kubernetes クラスターにアクセスできるようにします。
  • Kubernetes 環境が LoadBalancer サービス用の外部アドレスをプロビジョニングできることを確認してください。
  • 同時接続数が少なくとも3,000をサポートする有効な EMQX Enterprise ライセンスを用意してください。この例のライセンスプレースホルダーをライセンスキーに置き換えます。詳細は ライセンス管理 を参照してください。
  • ノードの避難状況を確認するために jq をインストールしてください。
  • テスト接続を生成するために MQTTX CLI をインストールしてください。
  • Core-Replicant クラスターの場合、Core レプリカを最低2つ設定してください。EMQX Operator は Core レプリカが2未満の Core-Replicant 構成を拒否します。

ローリングアップデートの仕組み ​

EMQX Operator は、EMQX カスタムリソースの Pod テンプレート(イメージ、イメージプルポリシー、リソース要求、Core および Replicant テンプレートなど)に変更があった場合にローリングアップデートを実行します。ロールアウトは以下の段階で進行します。

  1. Core ノードの更新: Operator は同じ StatefulSet 内の Core Pod を1つずつ更新します。各 Pod を新しいテンプレートで再作成し、Pod が準備完了になるまで待機します。少なくとも1つの更新済み Core ノードが準備完了になった後に Replicant のロールアウトが開始されます。
  2. Replicant ノードの更新: Operator は Deployment スタイルのロールアウトを行い、maxSurge までの更新済み Replicant Pod を作成し、maxUnavailable までの旧 Replicant Pod を避難させます。これらの制限はロールアウト速度と可用性を制御します。Operator は、Replicant Pod の移行が完了するまで前のリビジョンの Core ノードを少なくとも1つ維持し、各リビジョンの移行中に Core ノードが利用可能であることを保証します。
  3. ロールアウトの完了: Replicant の移行後、Operator は Core ノードの更新を完了します。すべての希望する Pod が準備完了となり、旧 Replicant Pod がなくなるとロールアウトは完了します。

デフォルトでは、Operator は Pod を削除する前に設定されたレートで MQTT 接続とセッションを避難させます。ノードの避難を無効にするには、.spec.updateStrategy.evacuationStrategy.type を Disabled に設定してください。

以下の手順は、EMQX をアップグレードせずに Pod テンプレートのアノテーションを変更してこのメカニズムを示します。EMQX をアップグレードする場合は .spec.image を更新してください。同じローリングアップデートの仕組みが適用されます。

アップデート戦略の設定 ​

  1. apps.emqx.io/v3beta1 の EMQX CR を作成し、アップデート戦略を設定します。
yaml
apiVersion: apps.emqx.io/v3beta1
kind: EMQX
metadata:
  name: emqx
spec:
  image: emqx/emqx:6.3.2
  config:
    roots:
      license:
        key: "..."
  updateStrategy:
    type: RollingUpdate
    evacuationStrategy:
      # MQTT クライアント避難レート(秒あたりの接続数):
      connectionEvictionRate: 1000
      # MQTT セッション避難レート(秒あたりのセッション数):
      sessionEvictionRate: 1000
      # Pod 削除前の待機時間(秒):
      waitTakeover: 10
    replicants:
      maxUnavailable: 1
      maxSurge: 1
  coreTemplate:
    spec:
      replicas: 2
  replicantTemplate:
    spec:
      replicas: 3
  listenersServiceTemplate:
    spec:
      type: LoadBalancer

WARNING

maxUnavailable と maxSurge は両方とも 0 にできません。maxUnavailable が 100% の場合、maxSurge は 0 より大きくなければなりません。フィールド定義、デフォルト値、検証ルールについては ReplicantsUpdateStrategy を参照してください。

  1. 上記内容を emqx-update.yaml として保存し、kubectl apply でデプロイします。
bash
$ kubectl apply -f emqx-update.yaml
emqx.apps.emqx.io/emqx created
  1. EMQX クラスターの状態を確認します。

STATUS が Ready であることを確認してください。完了までに時間がかかる場合があります。

bash
$ kubectl get emqx
NAME      STATUS   AGE
emqx      Ready    8m33s

テスト接続の確立 ​

MQTTX CLI を使用して MQTT 接続を確立し、ローリングアップデート中の接続避難を観察します。MQTTX CLI は自動再接続に対応しています。

emqx-listeners サービスの外部アドレスを取得します。以下のコマンドは、IP アドレスまたはホスト名のいずれかを公開するロードバランサーに対応しています。

bash
export EMQX_HOST="$(kubectl get service emqx-listeners -o jsonpath='{.status.loadBalancer.ingress[0].ip}{.status.loadBalancer.ingress[0].hostname}')"

EMQX_HOST にアドレスが設定されたら、MQTTX を使ってデフォルトの TCP リスナー(ポート 1883)に3,000接続を開きます。

bash
mqttx bench conn -h "${EMQX_HOST}" -p 1883 -c 3000
[10:05:21 AM] › ℹ  Start the connect benchmarking, connections: 3000, req interval: 10ms
✔  success   [3000/3000] - Connected
[10:06:13 AM] › ℹ  Done, total time: 31.113s

アップデートのトリガー ​

  1. Core と Replicant の Pod テンプレートのアノテーションを更新してローリングアップデートをトリガーします。コマンドはタイムスタンプとランダムサフィックスを組み合わせて、同じアノテーション値の再利用を減らします。
bash
ROLLOUT_ID="$(date +%s)-${RANDOM}"

kubectl patch emqx emqx --type=merge -p \
  "{\"spec\":{\"coreTemplate\":{\"metadata\":{\"annotations\":{\"docs.emqx.com/rollout-id\":\"${ROLLOUT_ID}\"}}},\"replicantTemplate\":{\"metadata\":{\"annotations\":{\"docs.emqx.com/rollout-id\":\"${ROLLOUT_ID}\"}}}}}"

期待される出力:

text
emqx.apps.emqx.io/emqx patched
  1. アップデートプロセスの状態を確認します。
bash
$ kubectl get emqx emqx -o json | jq ".status.nodeEvacuations"
[
  {
    "nodeName": "emqx@10.244.4.56",
    "initialConnections": 33,
    "initialSessions": 0,
    "connectionEvictionRate": 200,
    "sessionEvictionRate": 200,
    "state": "waiting_takeover",
    "sessionRecipients": [
      "emqx@10.244.4.57",
      "emqx@10.244.4.58"
    ]
  }
]
フィールド名説明
nodeName現在避難中のノード名。
stateノードの避難フェーズ。
sessionRecipientsMQTT セッションの受信先ノード。
sessionEvictionRateこのノードの MQTT セッション避難レート(秒あたりのセッション数)。
connectionEvictionRateこのノードの MQTT 接続避難レート(秒あたりの接続数)。
initialSessionsこのノードの初期セッション数。
initialConnectionsこのノードの初期接続数。

ノードの避難進捗は対応する EMQX ノードステータス の connections と sessions カウンターを確認して推定できます。

  1. アップデート完了まで待ちます。
bash
$ kubectl get emqx
NAME      STATUS   AGE
emqx      Ready    8m33s

STATUS が Ready であることを確認してください。MQTT クライアント数やセッション数によっては、アップデートに時間がかかる場合があります。

アップデート完了後、kubectl get pods で全ての Pod が希望するテンプレートで稼働していることを確認できます。

ローリングアップデートのイラスト ​

以下の図は、3,000接続の Replicant ローリングアップデート中の接続分布の一例を示しています。Grafana の測定データに基づくものではありません。

06001,2001,8002,4003,000Update progressTotal 3,000emqx-replicant-86f864f9-0emqx-replicant-86f864f9-1emqx-replicant-86f864f9-2emqx-replicant-648c45c7-0emqx-replicant-648c45c7-1emqx-replicant-648c45c7-2Illustrative Replicant rolling update, maxSurge = 1, maxUnavailable = 1
ラベル/プレフィックス説明
Total図の最上部の線として示される接続数の合計例。
emqx-replicant-86f864f9旧 Replicant Pod のセットの名前プレフィックス例。
emqx-replicant-648c45c7更新済み Replicant Pod のセットの名前プレフィックス例。

Replicant のロールアウト中、避難された Pod から切断されたクライアントは、更新済み Pod を含む他の稼働中 Pod に再接続する可能性があります。図中の線はこの再分配を示したものであり、測定値ではありません。実際の接続数はノード避難レート、クラスターの利用可能容量、クライアントの再接続動作により変動します。