最近ではコンテナーのオーケストレーション・ツールがよく使われるようになってきています。IT ワークロードをパブリック・クラウドとプライベート・クラウドの両方で管理する場合、従来のモデルと比べると、コンテナー・オーケストレーション・ツールにはさまざまな利点があるからです。インテリジェントなスケジューリング、自己修復、自動負荷分散、自動スケーリングは、オーケストレーション・ツールに伴う数多くの利点の数例にすぎません。
このチュートリアルでは、Red Hat® OpenShift® バージョン 3.11 を使用します。OpenShift はフルスタックの自動オペレーションを備えたエンタープライズ対応の Kubernetes コンテナー・プラットフォームとして、ハイブリッド・クラウド・デプロイメントとマルチクラウド・デプロイメントの両方を管理できるようになっています。
OpenShift でのデフォルトの自動スケーリング機能は、メモリー使用量と CPU 使用率に基づいて行われますが、このチュートリアルでは、RabbitMQ 上のキュー・サイズに応じたアプリケーションの自動スケーリングを行います。
このチュートリアルでデプロイするのは基本的に、RabbitMQ クラスターと、RabbitMQクラスター上の特定のキューに対してメッセージを生成するプロデューサー・アプリケーション、このキューからメッセージを取り込むワーカー・アプリケーション、そして RabbitMQ オートスケーラーです。このオートスケーラーがキュー・サイズをチェックして、指定されたいくつかのパラメーターに基づいてワーカー・デプロイメントをスケーリングします。
このソリューションで使用するコンポーネントは次のとおりです。
- マネージド Red Hat OpenShift クラスター
- RabbitMQ テンプレート
- k8s-rabbit-pod-autoscaler (RabbitMQ のキュー・サイズに基づく自動スケーリングを実現するオープンソース・プロジェクト)
前提条件
Red Hat OpenShift の基礎知識。基礎知識を得るためのリソースについては、記事「ヒッチハイカー向け OpenShift ガイド」を参照してください。
OpenShift クラスター (OpenShift の OKD オープンソース・ディストリビューションを使用することもできます)。
所要時間
このチュートリアルの所要時間は約 30 分です。
手順
ステップ 1. RabbitMQ クラスターを OpenShift にデプロイする
まず始めに、OpenShift 内でプロジェクトを作成して、作成したプロジェクトを選択します。
次に、同じプロジェクト上で OpenShift カタログに RabbitMQ テンプレートを追加する必要があります。画面の上部にある「Add to Project (プロジェクトに追加) 」ボタンをクリックし、「Import YAML/JSON (YAML/JSON のインポート) 」を選択します。この RabbitMQ テンプレートの yaml ファイルの内容をコピーして yaml テキスト・ボックスに貼り付けます。
「Create (作成) 」をクリックします。
表示されるフォーム上で「Process the Template (テンプレートの処理) 」を選択してから、「Continue (続行) 」をクリックします。
「Template Configuration (テンプレート構成)」ページで、プロジェクト名とパスワードを指定します (このチュートリアルで指定する必要があるのはこれだけです)。忘れずに、RabbitMQ ユーザー名とパスワードをメモしておいてください。
「Create (作成) 」をクリックします。
ここではロールのバインディングとネットワーク・ポリシーを定義しているため、Red Hat OpenShift では、ここで 2 番目の確認ステップを行う必要があります。詳細については、OpenShift のドキュメントを参照してください。
数分経つと、正常に稼働しているポッドが表示されるはずです。
次は、rabbitmq-cluster-balancer
サービスで使用するルートを作成しましょう。OpenShift 上のサービスにより、ポッドへの内部アクセスが可能になります。これらのサービスを外部トラフィックに公開するには、サービスで使用する「ルート」を作成する必要があります。
rabbitmq-cluster-balancer
サービスを調べると、このサービスには 2 つのポートがあることがわかります。ポート「5672」は、アプリケーションがメッセージを生成するとき、そしてメッセージを取り込むときに使用するポートです。rabbitmq-cluster-balancer
サービスの IP とポート 5672 をメモしてください。この画面に表示されるサービスのホスト名もメモしておく必要があります。最後のステップで、このホスト名を使用するためです。もう一方のポート 15672 は、RabbitMQ 管理ポータルで使用します。このポートから、RabbitMQ 管理ポータルの UI にアクセスします。
RabbitMQ 管理ポータルに外部からアクセスできるようにすることもできます。それには、同じ画面上にある「Create route (ルートを作成) 」ボタンをクリックすればよいだけです。デフォルトでは、これによってポート 15672 のルートが作成されます。デフォルトの設定のまま、「Create (作成) 」ボタンをクリックして外部アクセス用のルートを作成できます。
上記の操作により、同じ rabbitmq-cluster-balancer
サービスのページ上に「15672」ポートのホスト名が表示されるはずです。
RabbitMQ 管理ポータルにアクセスするには、このホスト名にナビゲートして、RabbitMQ クラスターを作成するときに指定した RabbitMQ ユーザー名とパスワードを使用してポータルにサインインします。
ステップ 2. プロデューサー・アプリケーションを OpenShift にデプロイする
次は、プロデューサー・アプリケーションをデプロイします。OpenShift に、私が作成したカスタム Docker イメージを含むデプロイメント yaml ファイルを渡します。この yaml ファイルにより、RabbitMQ クラスター上にキューが作成されて、そのキューを宛先とするメッセージが生成されます。
同じプロジェクト内で、再度「Add to Project (プロジェクトに追加) 」ボタンを使用して「Import YAML/JSON (YAML/JSON のインポート) 」を選択します。producer.yaml
ファイルの内容をコピーして yaml テキスト・ボックスに貼り付けてから、そこに含まれる RabbitMQ 資格情報を必ず自分の資格情報に変更してください。
「Create (作成) 」をクリックします。その後、プロデューサー・ポッドが正常に稼働していることを確認します。
ステップ 3. RabbitMQ に送信するメッセージを生成する
RabbitMQ に送信するメッセージを生成するには、OpenShift 内の左側のメニューから「Applications (アプリケーション) 」、「Pods (ポッド) 」の順に選択します。表示される画面に、前のステップで作成したプロデューサー・ポッドが示されているはずです。このプロデューサー・ポッドの名前をクリックすると、ポッドの詳細が表示されます。その詳細ページの「Terminal (ターミナル) 」タブをクリックして、プロデューサー・ポッドのターミナルを使えるようにします。
ターミナルに「python producer.py
」と入力すると、「test」という名前の RabbitMQ キュー宛てのメッセージが生成されます。このキューは、RabbitMQ 管理コンソール内でも表示できます。
ステップ 4. ワーカー・アプリケーションを OpenShift にデプロイする
ステップ 2 と同じように、yaml ファイルをデプロイしてワーカー・アプリケーションをデプロイします。この場合も「Add to Project (プロジェクトに追加) 」ボタンを使用して「Import YAML/JSON (YAML/JSON のインポート) 」を選択し、worker.yaml
ファイルの内容をコピーして yaml テキスト・ボックスに貼り付けます。
忘れずに自分の RabbitMQ Cluster 資格情報を入力してから、「Create (作成) 」をクリックしてください。
ステップ 5. ワーカー・アプリケーションが RabbitMQ から正常にメッセージを取り込んでいることを確認する
どのような動作が行われているのかを完全に理解するには、このステップが重要となります。ワーカー・アプリケーションは実行中になると同時に、RabbitMQ 上の「test」キューの listen も開始します。RabbitMQ 管理コンソールを調べると、「test」キュー上のメッセージがなくなっていることがわかります。これは、ワーカー・アプリケーションがメッセージを取り込んでいるためです。
時間のかかるワークロードを模倣するために、ワーカー・アプリケーションはキューからメッセージを取り込むたびに 10 秒待機してから、RabbitMQ に対してメッセージを処理したことを確認応答します。この確認応答により RabbitMQ は、メッセージが適切に処理されたので、そのメッセージをメモリー内に維持する必要がなくなったことを知り、ワーカー・アプリケーションによるキュー内の次のメッセージの取り込みを許可します。
OpenShift 内の左側のメニューから「Applications (アプリケーション) 」、「Pods (ポッド) 」の順に選択します。ただし今回は、ワーカー・ポッドを選択してから「Logs (ログ) 」タブを表示します。
このログから、ワーカー・ポッドがメッセージを受信できる状態になっていることがわかります。ワーカー・ポッドはプロデューサー・ポッドで生成された最初のメッセージを受信し、その 10 秒後にメッセージを処理して「[x] Done」というメッセージをログに書き込みます。
ワーカー・ポッドはメッセージを処理し終えたので、別のメッセージを取り込める状態になりました。ステップ 3 を繰り返してアプリケーションをテストし、RabbitMQ 管理コンソール内でメッセージを観察できます。
ステップ 6. RabbitMQ オートスケーラーをデプロイする
重要: RabbitMQ オートスケーラーをデプロイするには、プロジェクトを「kube-system」に切り換えて、このステップ全体を通して「kube-system」プロジェクトを使用する必要があります。
現時点では、1 つのワーカー・ポッドが各メッセージを 10 秒間で処理するようになっています。この場合、10 個のメッセージが生成されたとすると、最後のメッセージを処理するまでに 110 秒かかることになります。この最後のメッセージが処理されるまでにユーザーを待たせる時間を 30 秒以内にするにはどうすればよいでしょうか。
オートスケーラー・アプリケーションは、指定されたいくつかのパラメーターに基づいてワーカーの数をスケールアップすることができます。k8s-rabbit-pod-autoscaler の詳しい説明は、この GitHub リポジトリー内で確認できます。
「kube-system」プロジェクト内で、「Add to Project (プロジェクトに追加) 」ボタンを使用して「Import YAML/JSON (YAML/JSON のインポート) 」を選択します。clusterRole.yaml ファイルの内容をコピーして yaml テキスト・ボックスに貼り付けてから、「Create (作成) 」をクリックします。このファイルで定義している「ClusterRole」を使用すれば、クラスター内のリソースに対するアクセス権を付与できます。
serviceAccount.yaml ファイルについても上記の手順を繰り返します。これによって定義されるのは、「ServiceAccount」です。ポッド内で実行されるコンテナーは、この ServiceAccount を使用して Kubernetes クラスターの API サーバーと通信します。
さらに、clusterRoleBinding.yaml ファイルについても同じ手順を繰り返します。これによって定義されるのは「ClusterRoleBinding」です。基本的に、「ClusterRole」を「ServiceAccount」にバインドします。
次は、RabbitMQ オートスケーラーのデプロイメント yaml を定義します。以下の説明からわかるように、デプロイメント yaml 内では「ServiceAccount」を使用します。これにより、「rabbit-pod-autoscaler」ポッドが特定のコマンド (「ClusterRole」を定義する際に指定したコマンド) を特定のリソース (同じ「ClusterRole」を定義する際に指定したリソース) に対して実行できるようになります。
auto-scaler-deployment.yaml ファイルの内容をコピーして、同じ「Import YAML/JSON (YAML/JSON のインポート)」ボタンを使用して貼り付けます。ここでは「kube-system」プロジェクトを使用していることを忘れないでください。
「Create (作成) 」ボタンをクリックする前に、この yaml 内のいくつかのパラメーターを更新する必要があります。もう一度このドキュメントを確認して、これから入力するパラメーターについて理解してください。
必要なパラメーターを指定した後、「Create (作成) 」をクリックします。
例として、ここでは以下のパラメーター値を入力しました。
INTERVAL: 5 秒。この設定により、RabbitMQ オートスケーラーは 5 秒ごとにキューをチェックして、キュー内で待機中のメッセージの数を調べます。
RAABIT_HOST:
rabbitmq-cluster-balancer.tutorial.svc.cluster.local
。これは、クラスター内のrabbitmq-cluster-balancer
サービスのホスト名です。RABBIT_USER および RABBIT_PASS: RabbitMQ クラスターの作成時に指定した資格情報。
AUTOSCALING: “1|5|3|tutorial|worker|test”。この設定は、システムが最小 1 つのポッドにスケールダウンし、最大 5 つのポッドにスケールアップすることを意味します。キュー内で 4 件以上のメッセージが待機中になっている場合、RabbitMQ オートスケーラーが「tutorial」プロジェクトの「worker」デプロイメント内のポッドの数を 2 にスケールアップします。キュー内で 7 件以上のメッセージが待機中になっている場合は、RabbitMQ オートスケーラーがポッドの数を 3 にスケールアップするといった具体に、5 つのワーカー・ポッドになるまでスケールアップ・プロセスが続きます。リソース使用量に上限を設けるために、スケールアップ・プロセスは指定された最大ポッド数の 5 に達すると停止します。スケールダウンでも同じロジックが使用されます。つまり、稼働中のポッドが 1 つだけになるまで、システムはキュー内で待機中のメッセージの数に基づいてスケールダウンします。キュー内にメッセージがなくなったとしても、次のメッセージを処理する場合に備えて 1 つのポッドが稼働し続けます。
別の視点から見ると、この構成では、システムまたはアプリケーションのユーザーのために処理の最大許容時間を 40 秒に抑えています。
ステップ 7. RabbitMQ オートスケーラーをテストする
アプリケーションをテストするには、ブラウザー上の 1 つのタブ内でステップ 3 を好きなだけ繰り返します。このステップでターミナルに python producer.py
を入力するたびに 1 つのメッセージが生成されます。前述のように、各メッセージがキューからワーカー・アプリケーションに取り込まれてから処理が終わるまでには 10 秒かかります。
別のタブで、「kube-system」プロジェクトに含まれる rabbit-pod-autoscaler
ポッドのログを開きます。
キュー上のメッセージ数に関するログと、スケーリングの更新に関するログが表示されます。
チュートリアル・プロジェクトに含まれる「worker」デプロイメントを調べて、スケーリング・プロセスを確認することもできます。
この画面で、ポッドの数が変わっていることを確認できます。つまり、OpenShift がワーカー・アプリケーションのリソースを自動的に増やして入力を所定の期間で処理できるようにし、遅延を防止しているということです。
まとめ
このチュートリアルでは、テンプレートを使用して迅速に RabbitMQ クラスターを OpenShift 上にデプロイする方法を説明しました。また、OpenShift 上にさまざまなアプリケーションを簡単にデプロイする方法も説明しました。最後に、RabbitMQ のキュー・サイズに基づいてアプリケーションの自動スケーリングを行う方法を説明しました。
このチュートリアルではすべての手順を行うために OpenShift 管理コンソールを使用しましたが、ターミナル・ウィンドウから OpenShift クライアント・ツール (OC ツール) を使用することもできます。
OpenShift の詳細に興味がある場合は、「Kubernetes with OpenShift 101: Exercises to get you started with Running Node-RED on OpenShift」に取り組んでください。また、OpenShift ドキュメントで詳細を確認することもできます。