4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ALBを2段重ねたらスティッキーセッションが効かなかった

4
Posted at

この記事について

業務で、外部ALB→内部ALBの多段構成でアプリを2台にしたところ、セッションが途切れる事象に遭遇しました。ALBのCookie設定を変更して解決したものの、なぜ直ったのかを自分の言葉で説明できるほど理解できていなかったので、検証環境を作って確かめました:writing_hand:


こんな方に読んでいただけたらうれしいです◎

・ALBのスティッキーセッションってなに?
・外部ALBと内部ALBを組み合わせた構成を扱っている
・Cookieの中身をブラウザ開発者ツールで見てみたい


先に結論~!

犯人はCookieの名前被りでした:ghost::cookie:


  • 多段ALBの両方で「ロードバランサー生成Cookie(期間ベースの維持、AWSALB)」を使うと、どちらもAWSALBという同じ名前でCookieを発行するため、ブラウザ上で片方が上書きされて消える
  • アプリ自身が発行するCookie(例:JSESSIONID)を使うアプリケーションベースの維持に切り替えると、多段構成でもすべての層でスティッキーセッションを有効にできる(公式ドキュメントに明記)

検証環境

画面を見ながら理解したかったので、あえてTerraformは使わずコンソール操作だけで作りました。


インターネット→外部ALB→内部ALB→EC2 2台の検証構成図

EC2には、アクセスされたインスタンスIDとPHPで発行したセッションIDを表示するだけのシンプルなページを置いています。

※PHPの標準のセッションCookie名はPHPSESSIDですが、実際の案件でよく使われるJavaアプリ(Tomcatなど)に合わせて、session_name(JSESSIONID)で変更しています。

※外部ALBのターゲットには、検証用に内部ALBのIPアドレスを直接登録しています。(本番向けの構成ではありません)


まずは基本のおさらい!

ALBが1段の場合、スティッキーセッションなしではリクエストごとに振り分け先が変わり、期間ベースの維持(AWSALB)を有効にすると同じインスタンスに固定されます。

スティッキーセッションなし
PS> curl.exe http://<ALBのDNS名>
Instance: i-aaaaaaaa...  ← 1台目
Instance: i-bbbbbbbb...  ← 2台目(振り分け先が変わる)

スティッキーセッションあり(Cookieを保持して送信)
PS> curl.exe -c cookies.txt -b cookies.txt http://<ALBのDNS名>
Instance: i-aaaaaaaa...
Instance: i-aaaaaaaa...  ← 固定
Instance: i-aaaaaaaa...

本題:ALBを2段重ねてみる

外部ALBと内部ALBの両方に、期間ベースの維持(AWSALB)を設定しました。


ブラウザの「Application > Cookie」を見ると、AWSALBは1つだけでした。一見、普通に動いているように見えます。

開発者ツールのCookie一覧。AWSALBは1つだけ表示されている


ところが、Networkタブでレスポンスヘッダーの生データを見ると、AWSALBという同じ名前で2つの違う値が返っていました。証拠はCookie一覧ではなく、レスポンスヘッダーにありました:dizzy_face:

レスポンスヘッダーで、同じ名前のAWSALBが異なる値で2つ返っている様子


ブラウザは名前・ドメイン・パスが同じCookieを1つしか保持できないため、最終的にはどちらか一方の値だけが残ります。(画像内のAWSALBCORSも同じ理由で衝突しています)業務で遭遇した事象も、これが原因だったと考えています。EC2が1台のときは問題になりませんが、2台構成にしたことでセッション維持の問題が表面化しました。


JSESSIONIDに揃えるとどうなるか

外部・内部の両方を、アプリケーションベースの維持(Cookie名:JSESSIONID)に変更しました。

ターゲットグループの維持設定で、アプリケーションベースのCookieとCookie名JSESSIONIDを指定した画面


レスポンスヘッダーを見ると、JSESSIONIDと、ALBが生成するAWSALBAPP-0がそれぞれ1つずつ届いており、AWSALBのときのように同じ名前で異なる値が2つ返ってくることはありませんでした。

レスポンスヘッダーで、JSESSIONIDとAWSALBAPP-0がそれぞれ1つずつ返っている様子


なぜ多段でも衝突しないのか?
ALB内部の詳しい動作は公開されていませんが、2つの方式には次の違いがあります。

  • 期間ベース:各層のALBが、AWSALBという同じ名前で別々の値を発行する
  • アプリケーションベース:ALBが生成するCookieは、アプリケーションベースの維持を有効にした各ターゲットグループの持続性情報を保持する

今回の検証でもAWSALBAPP-0は1つしか届いておらず、期間ベースのような同名の衝突は起きていませんでした。

なお、AWSALBAPP-0の-0は、Cookieの分割番号(フラグメント番号)です。ALBの層番号やサーバ番号ではありません。


AWS公式ドキュメントにも、次のように明記されています。

Application Load Balancers の複数のレイヤーを使用している場合、アプリケーションベースの Cookie を使用して、すべてのレイヤーでスティッキーセッションを有効にできます。ただし、期間ベースの Cookie の場合、AWSALB が使用可能な唯一の名前であるため、1 つのレイヤーでのみスティッキーセッションを有効にできます。(強調は筆者)

出典: Application Load Balancer のターゲットグループ属性を編集する - AWS公式ドキュメント


最初にこの文を読んだときはピンときていませんでしたが、実際に上書きされて消えるのを見た後だと、一気に腹落ちしました_(┐「ε:)_


おわりに

何となく設定して終わりにせず、実際に手を動かしてブラウザの中身を見られたのは大きな収穫でした。同じような多段ALB構成で悩んでいる方の参考になりましたら幸いです。


参考



BIPROGYグループへ技術の取り組み

採用募集中!

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?