Azure App Serivceの前段にAzure Front Doorを配置した時にARRアフィニティを有効化する

2022.04.15

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

いわさです。

Azure App Serviceにはスケールアウトと負荷分散機能が備わっています。
そして、ステートフルなアプリケーションを分散環境でもホスティング出来るように、スティッキーセッションを実現するARRアフィニティ機能も備わっています。

ARRアフィニティをONにしたApp Serviceの前段にAzure Front Doorを配置したところ、ARRアフィニティによるインスタンスの固定化出来ませんでした。
本日は少し設定を変更しこちらを動作出来るようにしてみました。

App ServiceのARRアフィニティについて

まず、App Serviceでは価格レベルによってスケールアウトの上限が決まっています。 スケールアウトはBasic以上から可能で、Basicで3, Standardで10, Premiumで30, Isolatedで100が上限となっています。
この記事ではBasicプランを使って検証しています。

まずは通常どおりApp Serviceを構築します。
Windowsの.NET 6で作成しました。

ARRアフィニティはデフォルトでONになっています。
手動スケールアウトでインスタンス数を2台に変更します。

ではここで、cURLを使ってリクエストを送信してみます。

$ curl -I https://iwasa-backend.azurewebsites.net
HTTP/1.1 200 OK
:
Set-Cookie: ARRAffinity=3ffd0248067157b38f97fa0844f67aa350611fd520393a050b70e2e283c48d8c;Path=/;HttpOnly;Secure;Domain=iwasa-backend.azurewebsites.net
Set-Cookie: ARRAffinitySameSite=3ffd0248067157b38f97fa0844f67aa350611fd520393a050b70e2e283c48d8c;Path=/;HttpOnly;SameSite=None;Secure;Domain=iwasa-backend.azurewebsites.net
:

$ curl -I https://iwasa-backend.azurewebsites.net
HTTP/1.1 200 OK
:
Set-Cookie: ARRAffinity=013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfc;Path=/;HttpOnly;Secure;Domain=iwasa-backend.azurewebsites.net
Set-Cookie: ARRAffinitySameSite=013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfc;Path=/;HttpOnly;SameSite=None;Secure;Domain=iwasa-backend.azurewebsites.net
:

Set-Cookieレスポンスヘッダーが設定されていますね。
リクエストを受けた際にこのCookieを使ってApp Serviceがインスタンスの振り分け先を決めています。

ちなみに、013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfcはインスタンスIDを指しています。
このように、ARRアフィニティはCookieベースで動作しています。

Azure Front Doorを使うとCookieが拒否される

Azure Front DoorをキャッシュやWAF、L7ロードバランサーとしての用途で前段に配置するパターンがあると思いますが、そのまま配置するとARRアフィニティが使えないことを最近知りました。
試してみましょう。まずはFront DoorのオリジンにApp Serviceを指定します。

Front Doorのエンドポイントへアクセスすると、Set−Cookieヘッダーは設定されていますが、Google Chromeでは警告が発生しています。

This Set-Cookie was blocked because its Domain attribute was invalid with regards to the current host url.

Set-Cookieの内容を確認してみると、Domain=iwasa-backend.azurewebsites.netが指定されています。

$ curl -I https://hoge-arraffinity.tak1wa.com/
HTTP/1.1 200 OK
:
Set-Cookie: ARRAffinity=3ffd0248067157b38f97fa0844f67aa350611fd520393a050b70e2e283c48d8c;Path=/;HttpOnly;Secure;Domain=iwasa-backend.azurewebsites.net
Set-Cookie: ARRAffinitySameSite=3ffd0248067157b38f97fa0844f67aa350611fd520393a050b70e2e283c48d8c;Path=/;HttpOnly;SameSite=None;Secure;Domain=iwasa-backend.azurewebsites.net
:

不正なドメインとして扱われるのでこのCookieは拒否されます。
それによって、再リクエスト時には都度App ServiceによってインスタンスIDが返却されています。

Set-Cookie - HTTP | MDN

対処してみる

このDomainさえどうにかなれば何とかなりそうです。
色々やってみましょう。

App ServiceとFront Doorでカスタムドメインを一致させる。

App ServiceもFront Doorもカスタムドメイン機能があります。
どちらも同じカスタムドメインを使うと不正なドメインとして扱われることは無い気がしますね。

App ServiceとFront Doorへ同じカスタムドメインを設定してみました。

アクセスするとどうなるでしょうか。

ダメですね。
Front DoorからApp Serviceに対してカスタムドメインでアクセスしているわけではないので、オリジンホストで設定されてしまっています。

ホストヘッダーを指定する

Front Doorのオリジングループでは、ホストヘッダーの指定が出来ます。
デフォルトだとホスト名と同じものが指定されますが、ここをフロントと同じホスト名にしてみましょう。

$ curl -I https://hoge-arraffinity.tak1wa.com/
HTTP/2 200 
:
set-cookie: ARRAffinity=013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfc;Path=/;HttpOnly;Secure;Domain=hoge-arraffinity.tak1wa.com
set-cookie: ARRAffinitySameSite=013a31477018208d1d9a6a5265db9b280dcea0fe6b36fa395321a7acf41f0bfc;Path=/;HttpOnly;SameSite=None;Secure;Domain=hoge-arraffinity.tak1wa.com
:

今度はいけましたね。

さいごに、注意点

これで、Azure Front DoorとApp Serviceを組み合わせた構成で、App ServiceのARRアフィニティ動きそうです。
ただ、以下のドキュメントには「ホストヘッダーをバックエンドと一致させる必要がある」との記載がありました。副作用に関する記述を見つけることが出来なかったのですが何か影響があるかもしれないので注意してください。

ほとんどのアプリ バックエンド (Azure Web Apps、Blob Storage、Cloud Services など) では、ホスト ヘッダーがバックエンドのドメインと一致している必要があります。

また、Azure Front DoorもApp ServiceもTLS/SSLを使う場合の無料のマネージド証明書が提供されていますが、それを使うためにはホストへのCNAME登録が必要のようです。(TXTではダメだった)
そうすると、Front DoorとApp Serviceで重複してしまうので、自動更新の際に問題が起きそうです。おとなしくApp Service証明書を使えるならそちらのほうが無難かもしれません。