【ACM/ALB】504 Gateway Time-out と向き合って見つけた解消法

## 概要

AWSのApplication Load Balancer(ALB)を使ってHTTPS化する際に
ロードバランサーの作成など各種設定を終えてドメインでアクセスしてみると
「504 Gateway Time-out」が発生し苦戦したため、こちらにアウトプットしていきます。

恐らく、これはおっちょこちょいなケースではあると思いますが、
調べたことも含めて共有していけたらと思います。

尚、ご指摘箇所がございましたら
ご教授いただけますと幸いです。

## 結論

序盤の序盤ですが、先に私のケースの場合の結論だけお話しすると

**ロードバランサーのリスナーのデフォルト転送先(ターゲットグループ)をEC2インスタンスのインバウンドルールが許可しているポートに合わせる**

ということです。
つまりは、ちゃんとインバウンドルール、アウトバウンドルールが適切に許可されているか確認をしようね、ということです。
文字だけではよくわからんですよね。以下で説明していきます。

## ELB,ALBとは

ELBとは、公式で以下のように述べています。

>Elastic Load Balancing は、受信したトラフィックを複数のアベイラビリティーゾーンの複数のターゲット (EC2 インスタンス、コンテナ、IP アドレスなど) に自動的に分散させます。登録されているターゲットの状態をモニタリングし、正常なターゲットにのみトラフィックをルーティングします。Elastic Load Balancing は、受信トラフィックの時間的な変化に応じて、ロードバランサーをスケーリングします。また、大半のワークロードに合わせて自動的にスケーリングできます。
>[Elastic Load Balancing とは?](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/userguide/what-is-load-balancing.html)

ALBはELBのひとつでアプリケーションレイヤで機能するものですね。

そもそも通信の流れとしてはどういう流れなのでしょうか。
とても雑に図示すると以下のようになります。（私の場合）

![クライアントからEC2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459618/0fab86c0-713c-3b8d-be50-5cfd5856cb4d.png)

ここからどこでおかしくなっているのか切り分ける必要がありますね。

## 解決法は？

まずは、ターゲットグループのヘルスチェックを見てみましょう。
EC2 > ロードバランシング にターゲットグループとあると思うのでそこをクリックします。
設定したターゲットグループのチェックボックスにチェックをつけると詳細が出ます。
「Targets」のタブがあると思うので、押すと「Health status」と「Health status details」のカラムがあると思います。そこに現在の状態がわかります。
ちなみに私は以下の通り、異常であるとわかります。

![ターゲットグループステータス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459618/1a427944-3d2c-790a-9c87-e21f485df69b.png)

ここでどのターゲットグループが異常なのか、またそれはどんなエラーなのかを教えてくれます。
そして公式ではこの解決手順を教えてくれています。
一部抜粋します。

>- ヘルスチェック用によりシンプルなターゲットページを選択する。
>- ヘルスチェックの設定を調整する。
>- ターゲットに関連付けられたセキュリティグループが、ヘルスチェックポートとヘルスチェックプロトコルを使用してロードバランサーからのトラフィックを許可していることを確認します。ロードバランサーセキュリティグループのすべてのトラフィックを許可するために、ルールをセキュリティグループに追加できます。また、ロードバランサーのセキュリティグループでは、ターゲットへのトラフィックを許可する必要があります。
>[公式AWS](https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-fix-failing-health-checks-alb/)

私の場合、一番目のものは最初からシンプルに設定されていました。(恐らくデフォルトはシンプルなターゲットページだと思います多分)

通常、NginxなどのKeepAlive Timeout値は、ELBのアイドルタイムアウト値より大きくないといけません。
これについては[こちらの記事](https://qiita.com/hareku/items/7880eeac1e96c2f897e1)に詳しく書かれていますので参照してください。

私の場合は、 Nginx => 65, ELB => 60 であったため、問題ないと判断しました。

続いては、
実は、最初から私はどこかのトラフィック許可がダメなんだろうとは思っていました。(えっ？)
ただ、確認をしてもどれも良さそうな感じで特定できていませんでした。

### ここからは私の解決手順になります。

まず、ロードバランサーに設定されているリスナーを確認すると私の場合、ポート80のものとポート443のものを追加していました。（恐らくみなさんと同じかと思います）
リスナーは設定したプロトコルとポートを使用して接続リクエストをチェックするプロセスです。
先ほどの「Health status」の状況からポート「443」を指定したターゲットグループがおかしいはずなので、ここの転送先を確認しました。

転送先はEC2インスタンスのはずなので、こちらのセキュリティグループで設定しているインバウンドルールを確認します。
すると、当然ですが80番ポートと22番ポートしか許可していません。
はい、そうです。443番ポートを受け付けていないんですね。そりゃ「504」出るわですね。

なので、ターゲットグループのポートを変更するかEC2のポートを変更するかは先ほどの図で見た通りEC2は「HTTP」でしかやり取りしないので、ターゲットグループのポート、つまりデフォルトの転送先を変更するべきですね。

EC2 > ロードバランシング のロードバランサーに入って、該当のものにチェックをつけたら
「リスナー」タブがあると思うので押したら、エラーが起きてるリスナーIDの「ルール」カラムにある「ルールの表示/編集」を押します。(赤枠のところ)
![ターゲットグループリスナー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459618/2af794ab-214b-62af-8418-c5daa4d30037.png)

そして、画面上部タブに鉛筆アイコンがあるのでそれを押したら
「デフォルトアクション」左側にも鉛筆アイコンがあるので、押します。
すると以下のような画面が出てくると思うので、「THEN」カラム内右上のゴミ箱アイコンを押して一旦削除後に「アクション追加」を選択して「転送先」を選択したらEC2インスタンスで許可しているポートを指定したターゲットグループを選択して更新すれば完了です！
![ターゲットグループリスナー編集.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459618/dc7f1aeb-2e50-4be2-6b78-17b7b5624633.png)

更新ができたら、再度EC2 > ロードバランシング のロードバランサーに入ってリスナーの転送先が更新されているか確認をしましょう。

お疲れ様でした。
最後までお読みいただきありがとうございます。

## 参考

- [Application Load Balancer をトラブルシューティングし、ヘルスチェックの失敗を修正するにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-fix-failing-health-checks-alb/)
- [ELB使ってる人はすぐにKeepAlive Timeoutの値を確認しよう](https://qiita.com/hareku/items/7880eeac1e96c2f897e1)
- [Application Load Balancer のトラブルシューティング](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html#http-504-issues)
- [ELB（Elastic Load Balancing）を調べて使ってみた。](https://dev.classmethod.jp/articles/elb-explanation-try/)