ALBのセッションスティッキーの切り替わり時の挙動について

概要
ALBによって、ECSコンテナ1・ECSコンテナ2に負荷分散するシステムで、アプリタイプのセッションスティッキーを使った際の、タイムアウトによるスティッキー切り替え時の挙動がおかしい。
切り替え後に、セッションスティッキーが有効にならずにコンテナ1,コンテナ2に交互にアクセスされ、ブラウザにERR_TOO_MANY_REDIRECTS (リダイレクト回数が多すぎます)と表示された後、予定していた画面に遷移する、ということがあったので調査しました。
ただ、ここに書いてある内容は、実際の動作から推測したものであり、間違っている可能性があります。
環境
ブラウザ | EDGE |
Webアプリ | ASP.NET CORE6 MVC |
ネットワーク | ALB -> コンテナ(Nginx -> Kestrel) |
多重度 | 2(コンテナ1、コンテナ2) |
セッションスティッキー | アプリタイプ(アプリで発行したセッションcookieによりアクセスするコンテナを固定する) |
セッションスティッキーのタイムアウト | 10分(アクセスがない状態が10分続くとスティッキーが無効になる。アクセスがあると再度10分に延長される) |
セッションタイムアウト | 9分 |
セッションCookieを作成するタイミング | 認証時(重要。これが原因) 認証はOpenIdConnectでログイン画面なしでその場で認証(すでに他のシステムで認証済) 認証結果は、Cookie認証としてCookieに保持。 |
セッションスティッキーの挙動の前提
ALBのセッションスティッキーは、アプリのセッションcookieの中身で振り分け先を決定するのではなく、ALBが独自に発行したcookieにより振り分け先を決定します。
ALBは、AWSALBAPP-0~AWSALBAPP-4までのCookieを作成し、見てた範囲では、AWSALBAPP-0に値が設定されているときはスティッキーが有効に働いているときで、値が設定されていないとき(値が_remove_の場合も値が設定されていないとみなす)はスティッキーが働いていないときになります。
最初にAWSALBAPP-0に値が設定されるのは、セッションCookieが作成されたときで、次回のリクエストからAWSALBAPP-0が付与されます。
(今回のタイムアウトの)10分間アクセスがなく、スティッキーが無効になると、現在アクセスしているコンテナ(コンテナ1とする)とは別のコンテナ(コンテナ2とする)にアクセスします。
切り替わり初回のリクエストには、値が設定されたAWSALBAPP-0が付与されます(レスポンスで値なしに変更している?)。
コンテナ2でセッションが作られれば、そこでまたスティッキーが有効になり、コンテナ2へのアクセスが固定化されます。
コンテナ2でセッションが作られなければ、AWSALBAPP-0は値なしになり、スティッキーが無効になります。
ここでポイントなのが、コンテナ2でセッションが作られなかった場合は、コンテナ1で作られたセッションCookieが残った状態になります。
ALBは、セッションCookieの名前しか参照しないという話だったので、コンテナ2でセッションCookieが作られなかった場合に、コンテナ1で作られたセッションCookieをもとにスティッキーを有効にし、コンテナ2へのアクセスを固定化するかと思ったのですが、違うようです。
結論として、どうやらALBのセッションスティッキー切り替え前と切り替え後でセッションCookieの値(または作成日時)に変化がなければ、セッションが開始されていないと判断されるようです。
実際の動作
遷移ページ | セッションCookie | AWSALBAPP-0 | |
初回アクセス | |||
↓ | |||
コンテナ1 | /Home (トップページ) 認証していないため/Loginにリダイレクト | なし | 値なし |
↓ | (スティッキー無効) | ||
コンテナ2 | /Login (認証) 認証後、/Homeにリダイレクト | 作成(AAAA) | 値ありに変更 |
↓ | (スティッキー有効) | ||
コンテナ2 | /Home | 保持(AAAA) | 値あり |
↓ | (タイムアウト発生/スティッキー無効) | ||
コンテナ1 | /Home コンテナ1は認証していないため /Loginにリダイレクト (Cookie認証のCookieはコンテナ間で 互換性がない模様) | 保持(AAAA) | 値なしに変更 |
↓ | (セッションCookieに変化がないため スティッキー無効) | ||
コンテナ2 | /Login 認証後、/Homeにリダイレクト | 再利用(AAAA) | 値なし |
↓ | (もともとコンテナ2で作られた セッションCookieのため再利用で 値の変化なし。スティッキー無効) | ||
コンテナ1 | /Home コンテナ1は未認証 /Loginにリダイレクト | 保持(AAAA) | 値なし |
↓ | (スティッキー無効) | ||
コンテナ2 | /Login 認証後、/Homeにリダイレクト | 再利用(AAAA) | 値なし |
↓ | (以降、コンテナ1とコンテナ2の リダイレクトを繰り返し、ブラウザに ERR_TOO_MANY_REDIRECTS (リダイレクト回数が多すぎます) と表示される。 ブラウザから/Loginが再送される(多分) | 保持(AAAA) | 値なし |
コンテナ1 | /Login 認証後、/Homeにリダイレクト | 新規作成(BBBB) | 値ありに変更 |
↓ | (スティッキー有効) | ||
コンテナ1 | /Home | 保持(BBBB) | 値あり |
まとめ
ALBのセッションスティッキーを動作させる場合、認証時ではなくALBからの初回アクセス(上記の例だと/Homeにアクセス)されたタイミングでセッションを作成する必要があります。