RabbitMQ は Erlang で書かれたメッセージ ブローカーで、複数のノードにわたる完全なデータ レプリケーションを備えたフェールオーバー クラスターを編成でき、各ノードが読み取りおよび書き込みリクエストを処理できます。 多くの Kubernetes クラスターが運用運用されているため、多数の RabbitMQ インストールをサポートしており、ダウンタイムなしでクラスター間でデータを移行する必要性に直面していました。
この操作は少なくとも XNUMX つの場合に必要でした。
- Kubernetes にない RabbitMQ クラスターから、すでに「kubernet化」された (つまり、K8s ポッドで動作している) 新しいクラスターにデータを転送します。
- Kubernetes 内の RabbitMQ をある名前空間から別の名前空間に移行する (たとえば、回線が名前空間で区切られている場合、インフラストラクチャをある回線から別の回線に移行するため)。
この記事で提案されているレシピは、古い RabbitMQ クラスター (たとえば、3 ノード) がすでに K8s またはいくつかの古いサーバーに存在する状況 (ただし、これらに限定されるものではありません) に焦点を当てています。 Kubernetes 上でホストされているアプリケーション (すでに存在している、または将来存在する) は、Kubernetes と連携して動作します。
...そして、それを Kubernetes の新しいプロダクションに移行するという課題に直面しています。
まず、移行自体に対する一般的なアプローチについて説明し、その後、その実装の技術的な詳細について説明します。
移行アルゴリズム
アクションの前の最初の準備段階では、古い RabbitMQ インストールで高可用性モードが有効になっていることを確認します (ha-mode: all
:
次のステップは、Kubernetes ポッドで新しい RabbitMQ クラスターを作成することです (たとえば、この例では 3 つのノードで構成されていますが、その数は異なる場合があります)。
この後、古い RabbitMQ クラスターと新しい RabbitMQ クラスターをマージし、単一クラスター (6 ノード) を取得します。
新旧の RabbitMQ クラスター間のデータ同期プロセスが開始されます。 クラスター内のすべてのノード間ですべてのデータが同期されたら、新しいクラスターを使用するようにアプリケーションを切り替えることができます。
これらの操作の後は、RabbitMQ クラスターから古いノードを削除するだけで十分であり、移動は完了したと見なされます。
私たちはこのスキームを本番環境で何度も使用してきました。 ただし、私たち自身の利便性を考慮して、標準の RMQ 構成を複数の Kubernetes クラスターに分散する特殊なシステム内に実装しました。 (興味のある方のために:私たちが話しているのは
実際に試してみましょう
必要条件
詳細は非常に簡単です。
- Kubernetes クラスター (minikube も機能します)。
- RabbitMQ クラスター (ベアメタル上にデプロイでき、公式 Helm チャートから Kubernetes の通常のクラスターのように作成できます)。
以下の例では、RMQ を Kubernetes にデプロイして呼び出しました。 rmq-old
.
スタンドの準備
1. Helm チャートをダウンロードして少し編集します。
helm fetch --untar stable/rabbitmq-ha
便宜上、パスワードを設定します。 ErlangCookie
そして政治を作る ha-all
そのため、デフォルトでキューは RMQ クラスターのすべてのノード間で同期されます。
rabbitmqPassword: guest
rabbitmqErlangCookie: mae9joopaol7aiVu3eechei2waiGa2we
definitions:
policies: |-
{
"name": "ha-all",
"pattern": ".*",
"vhost": "/",
"definition": {
"ha-mode": "all",
"ha-sync-mode": "automatic",
"ha-sync-batch-size": 81920
}
}
2. チャートをインストールします。
helm install . --name rmq-old --namespace rmq-old
3. RabbitMQ 管理パネルに移動し、新しいキューを作成し、いくつかのメッセージを追加します。 これらは、移行後にすべてのデータが保持され、何も失われていないことを確認するために必要になります。
テストベンチの準備が整いました。転送する必要のあるデータを含む「古い」RabbitMQ があります。
RabbitMQ クラスターの移行
1. まず、新しい RabbitMQ をデプロイしましょう другом 名前空間 同じ ErlangCookie
ユーザーのパスワード。 これを行うには、RMQ をインストールするための最後のコマンドを次のように変更して、上記の操作を実行します。
helm install . --name rmq-new --namespace rmq-new
2. ここで、新しいクラスターを古いクラスターとマージする必要があります。 これを行うには、各ポッドに移動します 新しいです RabbitMQ を開き、次のコマンドを実行します。
export OLD_RMQ=rabbit@rmq-old-rabbitmq-ha-0.rmq-old-rabbitmq-ha-discovery.rmq-old.svc.cluster.local &&
rabbitmqctl stop_app &&
rabbitmqctl join_cluster $OLD_RMQ &&
rabbitmqctl start_app
変数内 OLD_RMQ
いずれかのノードのアドレスが見つかりました 古い RMQ クラスター。
これらのコマンドは現在のノードを停止します 新しいです RMQ クラスターを古いクラスターに接続し、再度起動します。
3. 6 ノードの RMQ クラスターの準備が整いました。
すべてのノード間でメッセージが同期されるまで待つ必要があります。 メッセージの同期時間が、クラスターがデプロイされているハードウェアの容量とメッセージの数に依存することを推測するのは難しくありません。 説明したシナリオでは、メッセージが 10 個しかないため、データは即座に同期されましたが、メッセージの数が十分に多い場合、同期は数時間続く可能性があります。
したがって、同期ステータスは次のようになります。
それは +5
メッセージがすでに入っていることを意味します もっと 5 つのノード上 (フィールドに示されているものを除く) Node
)。 したがって、同期は成功しました。
4. 残っているのは、アプリケーションの RMQ アドレスを新しいクラスターに切り替えることだけです (ここでの具体的なアクションは、使用しているテクノロジー スタックやその他のアプリケーションの仕様によって異なります)。その後、古いクラスターに別れを告げることができます。
最後の操作の場合(つまり、すでに 後の アプリケーションを新しいクラスターに切り替える) 各ノードに移動します 古い クラスターを作成し、コマンドを実行します。
rabbitmqctl stop_app
rabbitmqctl reset
クラスターは古いノードを「忘れ」ました。古い RMQ を削除できます。その時点で移動は完了します。
注意注: RMQ を証明書とともに使用する場合、基本的には何も変わりません。移動プロセスはまったく同じように実行されます。
所見
説明したスキームは、RabbitMQ を移行するか、単に新しいクラスターに移動する必要がある場合のほとんどすべてのケースに適しています。
私たちの場合、RMQ がさまざまな場所からアクセスされたときに問題が発生したのは XNUMX 回だけで、どこでも RMQ アドレスを新しいアドレスに変更する機会はありませんでした。 次に、既存のサービスと Ingress に分類されるように、同じラベルを持つ同じ名前空間で新しい RMQ を起動しました。ポッドを起動するときにラベルを手動で操作し、リクエストがそのラベルに分類されないように最初にラベルを削除しました。空の RMQ を作成し、メッセージが同期された後に追加し直します。
RabbitMQ を構成を変更して新しいバージョンに更新するときにも同じ戦略を使用しました。すべてが時計のように機能しました。
PS
この資料の論理的な継続として、MongoDB (ハードウェア サーバーから Kubernetes への移行) と MySQL (Kubernetes 内でこの DBMS を準備する方法) に関する記事を準備しています。 それらは今後数か月以内に公開される予定です。
PPS
私たちのブログもお読みください:
出所: habr.com