AWS Global Acceleratorの勘違いしやすい仕様

## はじめに
本投稿では私がシステム開発中にGlobal Accelerator周りでつまずいたところを紹介しつつ、AWS Global Acceleratorの勘違いしやすい（※個人の感想）仕様について解説していきたいと思います。

ちなみにQiita初投稿です。

## Global Acceleratorとは
Global Accelerator自体の説明は今回の目的ではないため、あまり詳しく書かないですが、ざっくり言うとALB,NLBやEC2などの前段において、アプリケーションのネットワークパフォーマンスと可用性を向上させるサービスです。

今回紹介する私が開発に携わったシステムではGAを主に以下の2つの理由から採用していました。
* IP固定化が可能
* 複数リージョンへのトラフィック操作が可能

## Global Acceleratorの基本設定
さて、私がつまずいた事象を理解するためにGlobal Acceleratorの基本設定や用語について、コンソール画面での作成手順に沿って説明していきます。

### Global Acceleratorの作成手順
#### 1. アクセラレータの作成
アクセラレータはGlobal Acceleratorにおける一番大きなリソースの単位になります。
![スクリーンショット 2025-02-21 14.00.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017059/654a584d-4d00-482e-a96b-072fe752e9c3.png)

#### 2. 名前を入力
アクセラレータ名やアクセラレータのタイプ、IPアドレスタイプを選択できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017059/cbd5e0c8-e4bd-4eb8-b4ff-b6c9a53c25b6.png)

#### 3. リスナーの設定
リスナーに対してはポートとプロトコルを設定します。
複数のポートを定義する事もでき、下記の画像ではリスナーを2つ定義しています。
このアクセラレータは TCP/443 と TCP/10443 の通信を受けられる様な形となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017059/354d1129-01d0-43d0-8845-b1b15bbda3ba.png)

#### 4.エンドポイントグループの設定
先ほど設定した各リスナーに対してエンドポイントグループ（リージョン）を設定できます。
1つのリスナーに対し、複数のエンドポイントグループを設定でき、各エンドポイントに対してトラフィックダイヤルを設定して振り分けをしたり、ヘルスチェックの設定をしたりすることができます。
下記画像では
* エンドポイントグループ1 : ap-northeast-1 トラフィックダイヤル100%
* エンドポイントグループ2 : ap-northeast-3 トラフィックダイヤル0%

と設定しており、TCP/443 に来たトラフィックは**基本的に**全てap-northeast-1に流れます。
※**基本的に**というのが今回の記事の肝になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017059/0dfba5c8-fadd-4a16-a166-05cf7070d879.png)

#### 5. エンドポイントの設定
先ほど設定したエンドポイントグループに対してエンドポイントを設定できます。
エンドポイントのタイプにはALB, NLB, EC2, Elastic IPが選択でき、エンドポイントでは対応する実際のリソースを選択します。
ここでも1つのエンドポイントグループに対して複数のエンドポイントを設定することができ、それらのトラフィック振り分けの割合を「重み」にて設定できます。
以下では各エンドポイントグループに対しては1つのALBを設定し、重みは255（ap-northeast-3は0）としておきます。（対象が1つなので重みに意味はあまりないです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017059/059d7ebe-e785-4af8-8b1a-fede92bc1eeb.png)

これにてGlobal Acceleratorの作成は終了です。
今回作成したアクセラレータの設定と用語を簡単に図示すると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017059/d9646843-3c10-4df1-a667-4d1d1f9f1449.png)


## 発生した事象
では、今回私がつまずいた事象を紹介します。
### 構成
システム構成を簡略化したものが以下になります。
Global Accelerator → ALB → ECSのシンプルな構成です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4017059/731d77dd-86c9-414a-9a2a-64a16fe68617.png)


Act:東京/ Sby:大阪の構成をとっておりGlobal Acceleratorの設定としては、
東京：トラフィックダイヤル100%、重み255
大阪：トラフィックダイヤル0%、重み0
です。

ALBのターゲットグループとしては複数サービス（sorry/メンテナンス用サービス含む）を対象としています。
sorry/メンテナンスへの切り替えはALBのリスナールールの優先度で制御しており、普段稼働していない大阪ではALBの向き先がsorry/メンテナンス サービスになるよう設定しています。
（リージョン切り替え時に一時的にsorry/メンテナンス応答を返すため）

### 発生事象
以上システムにて、ブラウザからある1つのサービスへのアクセスを試したところ、、、

**sorry画面が表示されました**
**ん？？どういうこと？？？**

ALBの設定に間違いはありませんでした。
調査してみると、大阪側sorry用ECSタスクにアクセスしていることがわかりました。

### 発生原因
原因を見つけるのにも苦労したのですが、結論から言うと

東京側のSorry用サービスの一部ターゲットグループ（1つのポートのみ）のヘルスチェックが設定ミスにより失敗していました。

ただ、「東京側のターゲットグループのヘルスチェックが失敗⇨大阪側にトラフィックが流れる」のロジックがぱっとは理解できませんでした。
色々と調べていくと、Global Acceleratorの地味に難しい仕様が原因でした。

## Global Acceleratorの仕様
### ALBのヘルスチェック
「4.エンドポイントグループの設定」でも軽く触れましたが、Global Acceleratorはエンドポイント（ここでいうALB）に対してヘルスチェックを行っています。
このヘルスチェックの仕様は以下のように説明されています。

> Global Accelerator は、少なくとも 1 つの正常なアベイラビリティーゾーンがある場合、Network Load Balancer または Application Load Balancer の状態を正常と見なします。アベイラビリティーゾーン内のすべてのロードバランサーターゲットグループが正常である場合、アベイラビリティーゾーンは正常です。
引用元：https://docs.aws.amazon.com/ja_jp/global-accelerator/latest/dg/about-endpoint-groups-health-check-options.html

もう少し噛み砕くと、Global Acceleratorはエンドポイントに指定されたALBの**ターゲットグループ全てが正常**かどうかでエンドポイントが正常かを判断しています。
つまり、1つでもターゲットグループが異常であれば、Global Acceleratorはそのエンドポイント（ALB）を異常とみなすというわけです。
今回はターゲットグループ1つだけ異常だったためにGlobal Acceleratorは東京側のエンドポイント（ALB）を異常とみなしたようです。

さて、Global Acceleratorが東京側のエンドポイントを異常とみなしたところまでは分かりました。
ただ、まだトラフィックダイヤルが0%である大阪にトラフィックが流れた理由は分かりませんでした。
原因はGlobal Acceleratorのフェイルオーバーの仕様にありました。

### Global Acceleratorのフェイルオーバー
Global Acceleratorは可用性を高めるためにフェイルオーバー機能を備えています。
フェイルオーバーの仕様は以下のように説明されています。

> エンドポイントグループに重みが 0 より大きい正常なエンドポイントがない場合、Global Accelerator は別のエンドポイントグループの重みが 0 より大きい正常なエンドポイントにフェイルオーバーしようとします。このフェイルオーバーにおいて、Global Accelerator はトラフィックダイヤルの設定を無視することに注意してください。したがって、例えば、エンドポイントグループでトラフィックダイヤルが 0 に設定されている場合、Global Accelerator はフェイルオーバーの試行にそのエンドポイントグループを含めます。
引用元：https://docs.aws.amazon.com/ja_jp/global-accelerator/latest/dg/about-endpoints-endpoint-weights.unhealthy-endpoints.html

しっかりと**このフェイルオーバーにおいて、Global Accelerator はトラフィックダイヤルの設定を無視することに注意してください**と記載されています。勘違いしやすいポイントですね。
つまり、トラフィックダイヤルが0%であってもエンドポイントが正常とみなされる場合はそちら側にトラフィックが流れるようにフェイルオーバーされます。
今回は大阪側のSorry/メンテナンス用サービスは正常に機能していたため、大阪側のエンドポイントは正常とみなされたわけです。
ここまで理解してようやく今回の事象の原因については理解できました。

では、最後に全てのエンドポイントが異常とみなされた場合、Global Acceleratorはどこにトラフィックを流すのでしょうか？
それも先ほどと同じページに次のように説明されています。

> 例えば、2 つのエンドポイントがあり、1 つは正常でもう 1 つは異常で、それぞれの重みを 0 より大きい値に設定していると仮定します。この場合、Global Accelerator は正常なエンドポイントにトラフィックをルーティングします。ただし、唯一の正常なエンドポイントの重みを 0 に設定すると仮定します。次に、Global Accelerator は 3 つの追加のエンドポイントグループを試行して、重みが 0 より大きい正常なエンドポイントを見つけます。見つからない場合、Global Accelerator はクライアントに最も近いエンドポイントグループのランダムエンドポイントにトラフィックをルーティングします。

クライアントに近いエンドポイントが選ばれるようです。
東京にいる場合はこれらの仕様に気付く術がないわけですが、今回は不幸中の幸い？で大阪側エンドポイントは正常だったため気付くことができたわけです。

## 事象への対応
複数サービスがALBのターゲットグループとして指定されているため、このままだと1つのターゲットグループで問題があった際に全てのサービスに対するトラフィックが大阪側のSorry用サービスに流れてしまいます。
結局、大阪側のエンドポイントグループは普段設定せず、どう足掻いても東京側にしかトラフィックを流さないようにしました。
また、リージョンを切り替える際は東京側のエンドポイントグループを削除して、大阪側のエンドポイントグループを追加するという処理を行うようにしました。

## 最後に
今回は自分がつまずいた事象をきっかけに、Global Acceleratorの仕様についてしっかりと調べてみました。
Global Acceleratorのフェイルオーバーの仕様は意外と奥深くて、Act/Act構成のシステムであれば自動フェイルオーバーの実装に使えそうですし、ALBやGlobal Acceleratorをサービスごとに分ければ障害時に自動でSorryに振り分けることができそうですね。