OpenShift Ingress Controllerの負荷分散について
目次
はじめに
OpenShift Advent Calendar 2023 の記事です。
OpenShift や Kubernetes を利用して Web サービスを構築する場合、デプロイした Pod は OpenShift Cluster の外部からアクセスできるようにする必要があります。Cluster の外部からアクセスできるようにする方法は Node Port などいくつか用意されていますが、HTTP や HTTPS、WebSocket を利用してアクセス可能な Web サービスをデプロイする場合、OpenShift では Ingress Controller が候補として上がりやすいのではないでしょうか。また、Web サービスを提供する Pod は 1 台ではなく、可用性や性能要件を考慮して 2 台以上で構成されることが一般的です。
このとき、 Ingress Controller では複数の Pod に対して用意されたいくつかの分散方式に従ってリクエストを分散します。本記事では、OpenShift Ingerss Controller のデフォルトの負荷分散の方式について振る舞いについてみていきます。
OpenShift Ingress Controllerとは
OpenShift Container Platformクラスタを作成する際、Cluster 上で実行される Pod および Service はそれぞれ独自のIPアドレスが割り当てられます。これらのIPアドレスは、OpenShift Cluster 上で実行されている他の Pod や Service からアクセス可能ですが、Cluster 外部のクライアントからはアクセスできません。Ingress OperatorはIngressController APIを実装し、OpenShift Container Platform Cluster の Service への外部アクセスを可能にする責任を担うコンポーネントです。
Ingress Operatorは、外部クライアントが Service にアクセスできるようにし、ルーティングを処理する1つまたは複数の HAProxy ベースの Ingress Controller をデプロイおよび管理することを実現します。 Ingress Operatorを使用して、OpenShift Container Platformの Route および Kubernetes の Ingress リソースを指定してトラフィックをルーティングできます。 Ingress Controller 内の設定、たとえば endpointPublishingStrategy タイプの定義や内部負荷分散の可能性など、Ingress Controller エンドポイントを公開する方法が提供されます。
デフォルトの負荷分散
ここで本題です。OpenShift では定義する Route 毎に荷分散の方式を Annotation haproxy.router.openshift.io/balance
で指定することができます。デフォルトは random
*1 です。バックエンドの Pod の状況をみて負荷分散をしたいと考えるケースでは、このランダムというデフォルトは少し微妙に感じるかもしれません。
少し古い記事ですが、HAProxy の random のアルゴリズムについて HAproxy のブログ記事として掲載されています。
この記事では HAProxy の random のアルゴリズムはバックエンドのサーバーからランダムに選んだ2つのバックエンドのうち、コネクション数が最小のものを選択するという振る舞いをすると記載しています。これはどういうことでしょうか。記事の要約を次に記載していきます。
The Power of Two Choices in Load Balancing の要約
ブログ記事では HAProxy で利用可能な Power of Two Random Choices (以下、Power of Two) というアルゴリズムについて記載しています。Power of Two は 2つのランダムなサーバーを選び、最もアクティブな接続が少ないサーバーを選択することで、各リクエストにどのサーバーが応答するかを決定する方法を採用しています。このアルゴリズムの特徴を示すため、HAProxy で利用可能な負荷分散アルゴリズムと比較しどのような結果がもたらされるかを示しす検証結果を掲載しています。
対象となっているのは以下の4つのアルゴリズムです。 - Round Robin - Least Connections - Random - Power of Two
検証をするにあたり、コンディションを以下のように変更しています。
- 外部からの負荷がなく、CPUも専有して利用できる状態
- アプリケーションが CPU を共有できる状態
- アプリケーションが CPU を共有できる状態でかつ、他からもCPUが奪われるような状態
結論として、今回の測定状況では、Round Robin は芳しくない成績となり、一方で Least Connections がベストで次に Power of Two が状況に左右されず良い結果をもたらしてます。Random は結果が安定せず測定毎に大きく結果にばらつきが出ています。 しかしながら、複数の Load Balancer が存在する場合、Least Connections は分散先のサーバーへの負荷に他のLoad Balancer で負荷分散されようとしているアクセスは考慮されないため、期待しない結果となるケースが存在するとまとめています。
負荷分散のベストプラクティス
OpenShift に話を戻すと、デフォルトの構成において、Ingress Controller は 2 つの Pod から構成されます。また、Ingress Controller の前段にはロードバランサーが存在します。すべてのケースについてではありませんが、HAProxy のブログの検証結果を考慮すると、Power of Two (HAProxy でいう random) が良い結果をもたらす可能性が高いと言えるのではないでしょうか。
まとめ
OpenShift では Route を定義すると Ingress Controller (HAProxy) の負荷分散アルゴリズムとして Random がデフォルトで設定されます。HAProxy の Random はランダムに選んだ2つの Pod から最もアクティブな接続が少ない方を選択する方式でした。これによる検証結果は状況に左右されにくいことと、HAProxy が複数台になる場合つまり、Ingress Controller の Pod が 2 台以上の場合に期待した結果が得られそうであることがわかりました。
そのため、OpenShift Ingress Controller のデフォルトの負荷分散アルゴリズム Random は微妙な選択肢ではなく、適切な負荷分散を実現できる選択であることがわかりました。
参考文献
docs.openshift.com docs.openshift.com www.haproxy.com
*1:OpenShift 4.14 現在