Session affinityを構成したい

「WebアプリをホストするVMへのアクセスを固定したいのだが、うまくいかない場合がある」という問い合わせがあった。この事象が解決したので、その原因と解決策をまとめておく。

環境および配置

問い合わせの事象が発生していた環境は以下の通り。問い合わせ主によると、この環境はオンプレミスからLift & Shiftで移行したもので、事象はGo live後しばらくして発生しはじめた、とのこと。マルチリージョン対応はしていない。

  • Azure Load Balancer(以下、ALB)
  • ネットワーク仮想アプライアンス(以下、NVA)
    • L7 Load Balancer(以下、L7 LB)
    • Reverse Proxy
  • 仮想マシン(以下、VM)
    • Web App
    • データベース

問い合わせ主からのリクエストは、

cookieを使ってアクセス対象のWeb App(をホストするVM)を固定したい。追加開発にあまり費用を出せないので、低コストでsession affinityを実現したい。

というもの。平たく言うとcookieベースのsession affinityを構成したい、ということ。

Web AppはJava EEアプリケーションサーバでホストされているため、ふつうに考えるとアプリケーションサーバのクラスタリングやIn-memory data gridでセッション共有すればよいのだが、コスト低減のためクラスタリング構成できないEditionを使っていた。また、ALBにはsession affinity機能がないことは知っていたため、ALBの後段にL7 LBを配置してsession affinityを実現しようとしていた、ということだった。

この例での原因

おそらく、上図を見ただけで仮説が立つ人も多いはず。具体的には、以下のあたり。

  • Public Load Balancer(以下、Public LB)へのトラフィックのsource IPが変化したのでは?具体的には、アクセス元でローカルIPからGlobal IPへNATした際にglobal IPが変化していないか?
  • ALBではsession affinityを実現する機能はないから、もしsource IPが変わってしまったら宛先のWeb App(をホストするVM)が変わるはず。
  • Reverse Proxyが何か悪さをしたのでは?
  • session affinityを目的としてALBの後段に配置したL7 LBが期待した動作をしているか?例えば、Active-Active構成を取っているが、session情報はL7 LB両系で共有されていない、とか。

今回の事象は、以下が複合して発生していた。

  • アクセス元(プロキシ&Firewallの背後でローカルIPを使っている環境)のlocal IPからのNAT後のglobal IPが以前のアクセスと変わっており、結果としてpublic LBへのトラフィックのsource IP(この場合、NAT後のglobal IP)が変化していた。
  • ALBにはsession affinityの機能はなく、最も細かくてもsource IPとprotocolでしか判断できない。source IPが異なった(変わった)結果、異なるクライアントからのアクセスと判断し、前回とは異なるL7 LBにルーティングしていた。
  • session affinityを目的としてALBの後段に配置されているActive-Active構成のL7 LBは、両系でsession情報が共有されておらず、一方のL7 LBを通過した情報は他方のL7 LBに共有されていなかった。別のL7 LBにトラフィックがルーティングされた場合、sessionの継続性を判断できず、異なるクライアントからのアクセスと判断していた。

なお、ALBの負荷分散規則は以下のドキュメントに記載がある。

Azure Load Balancer の分散モードを構成する
https://docs.microsoft.com/ja-jp/azure/load-balancer/load-balancer-distribution-mode
Configure the distribution mode for Azure Load Balancer
https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-distribution-mode

具体的には以下のような流れで、結果として所望の動作をしないケースが発生した。

構成
要素
発生しうる事象
Public LB実際には同一クライアントからのアクセスにも関わらず、異なるglobal IPにNATされる場合がある。その場合、Public LBは異なるアクセス元からのアクセスと判断し、任意のL7 LBにトラフィックをルーティングする
結果として、前回のトラフィックルーティング先のL7 LBにトラフィックがルーティングされない可能性がある
L7 LBActive-Active構成
異なるL7 LBにルーティングされた場合、以前のトラフィック情報が共有されていないため、任意のReverse Proxyにトラフィックをルーティングする
結果として、前回のルーティング先のReverse Proxyにトラフィックがルーティングされない可能性がある
Internal LB通過したReverse Proxyが以前と異なる場合、source IPが違うために異なるアクセス元からのトラフィックと判断し、任意のinternal L7 LBにトラフィックをルーティングする
結果として、前回のルーティング先のInternal L7 LBにトラフィックがルーティングされない可能性がある
Internal L7 LBActive-Active構成
これも先ほどのL7 LBと同様、異なるL7 LBにルーティングされた場合、以前のトラフィック情報を共有されていないため、任意のWeb App(をホストするVM)にトラフィックをルーティングする
結果として、前回のルーティング先のWeb App(をホストするVM)にトラフィックがルーティングされない可能性がある
Web Appこれまでのトラフィックルーティングの結果、偶然前回と同じVMへトラフィックがルーティングされる可能性もあれば、異なるVMへルーティングされる可能性もある

対策

以下の置き換えを実施し、所望の動作をするようになった。

  • Azure Application Gateway(以下、App GW)でALBとL7 LB、Reverse Proxyを置き換えた
  • 以下のドキュメントに従い、App GWでcookieベースのsession affinityを有効にした

アプリケーション ゲートウェイで Cookie ベースのアフィニティを有効にする
https://docs.microsoft.com/ja-jp/azure/application-gateway/ingress-controller-cookie-affinity
Enable Cookie based affinity with an Application Gateway
https://docs.microsoft.com/en-us/azure/application-gateway/ingress-controller-cookie-affinity

構成変更後のトポロジーは以下の通り。

この構成により、cookieベースのsession affinityが機能するだけでなく、以下のようなメリットを享受できるようになった。

  • L7 LBやReverse ProxyのNVAを使う必要がなくなったため、メンテナンス対象が減り、かつコストを減らすことができた
  • メンテナンス対象が減ったため、オペレーションコストも低減した

その他

Public L7 LBとしてAzure Front Doorを使わなかった理由は、この問い合わせ主のシステムがマルチリージョン対応しておらず、グローバルサービスを使う理由がなかったから。

Azure Front Door Service とは
https://docs.microsoft.com/ja-jp/azure/frontdoor/front-door-overview
What is Azure Front Door Service?
https://docs.microsoft.com/en-us/azure/frontdoor/front-door-overview

今回はApp GWの機能でReverse Proxyに対する要件を賄うことができたが、Reverse Proxyに対する要件がApp GWの機能で賄いきれないものである場合、以下のような配置になる可能性もある。具体的には、認証のためのGatewayとしてのReverse Proxyが必要、とか。

まとめ

類似の事象では異なる解決策が適切な場合があるため、全てのケースにこの解決策があてはまるわけでない。ただ、クラウド移行にあたっては利用するサービスの機能を十分に理解し、機能を使い尽くして利用コンポーネント点数を減らす方向、つまりシンプルにするトポロジーを考えることが重要。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中