はじめに
この記事は自分の学習用、備忘録として書いてるものです。
もし内容に間違いなどがあればご指摘ください。
記事を書いた経緯
先日、シンプルなWebページをAWSのECS/Fargateにデプロイしようとした時に、CSサービスを作成後、初歩的なミスにぶつかりました。
この記事はそんなAWSの経験があまりない自分に向けて書いた備忘録となります。
今回試したAWS構成図は以下のとおりです。
1.今回のエラー内容
🚨 ECS ECSサービスを作成後、ALB経由でアクセスして動作を確認したら期待結果の {"status":"healthy"}が返ってこなかった
入力値
curl http://<自分のALBのDNS名>/health
⭕️期待していた結果
({"status":"healthy"}
❌実際に返ってきた結果
curl: (28) Failed to connect to note-app-api-alb-1134715016.ap-northeast-1.elb.amazonaws.com port 80 after 150327 ms: Couldn't connect to server
仮説
エラー内容を調べると、ブラウザやcurlからALBの80番ポートにTCP接続できていない状態であることが判明。
HTTPレスポンスが返らないなら分かるが、そもそもALBの80番に接続できないということは HTTP:80を許可されていないでは?と考えた。
一時対応
(前提条件は省きます)
元々、インターネットからのHTTP 80番アクセスは許可される設定だっため、 ALBのセキュリティグループのインバウンドルールに以下の内容を追記した
タイプ: HTTP
プロトコル: TCP
ポート範囲: 80
ソース: 0.0.0.0/0
その後、ターミナルで再度以下のコマンドを入力したが、
期待する結果({"status":"healthy"})は表示されなかった。
しかし、前回と別の内容が返ってきた
入力値
curl http://<自分のALBのDNS名>/health
⭕️期待していた結果
({"status":"healthy"}
❌実際に返ってきた結果
<html>
<head><title>504 Gateway Time-out</title></head>
<body>
<center><h1>504 Gateway Time-out</h1></center>
</body>
</html>
返ってきた内容を見ると、504 Gateway Time-out は、ALBには接続できているがALBがバックエンド(ECSタスク)から応答を受け取れない状態を表しているそうです。
また、ALBのセキュリティグループのインバウンドルールを追加した後にレスポンスが変わったため、ALBが80番で応答できている。
ALBが80番で応答できているということは、ALB自体は到達可能で、ALBの入口側に問題はない
どうやら問題の場所は「ALBの入口」ではなく「ALB → ECSタスク」の経路のようです。
恐らく原因は ECSタスクのセキュリティグループでALBからの通信が許可されていない ことと考えた。
現在:
504 Gateway Time-out( ALBは応答するがバックエンドから応答なし)
→ 自分のPCからALBまでは届いている
→ しかし ALB から ECSタスク / アプリ への通信で失敗している
ALB → ECSタスク間で何が起きているかを順番に確認した。
ECSタスクのセキュリティグループ:タスクのSGのインバウンドルールに「プロトコル: TCP / ポート: アプリのポート(例: 8000)/ ソース: ALBのセキュリティグループID」が入っているか確認。
EC2
→ ロードバランサー
→ note-app-api-alb
→ セキュリティ
→ セキュリティグループ
ここに表示されている sg-xxxxxxxxが、あとで ECSタスク側セキュリティグループのソースに指定されるべきIDなのでメモする

次に、実際に動いているECSタスクに付いているセキュリティーグループを確認
ECS
→ クラスター
→ note-app-cluster
→ サービス
→ note-app-api-service
→ Tasks タブ
→ RUNNING のタスクをクリック
→、下の方にある Networking またはネットワークセクションをかくにん
そこに、Security groupsがある。
ここに表示されている sg-xxxxxxxx が ECSタスク側のセキュリティグループ 。
次に、ECSタスク側のインバウンドルールを確認
EC2
→ セキュリティグループ
→ ECSタスクに付いていた sg-xxxxxxxx を検索
→ インバウンドルール を確認
下の内容が書いているか確認
タイプ: カスタム TCP
プロトコル: TCP
ポート範囲: 8000
ソース: ALBのセキュリティグループID
状況を見る限り、ECSタスク側セキュリティグループのソースに指定しているALBのセキュリティグループが、実際にAPI用ALBについているセキュリティグループと一致していない可能性が高い
重要な点はECSタスク側セキュリティグループのソースには「実際にそのALBに付いているセキュリティグループ」を指定する必要があるということ
API用ALB側で見ていたセキュリティグループ
sg-036fbc39407760f91
ECSタスク側セキュリティグループ
sg-0cbd03a39f7d3f03a(note-app-api-sg)
ECSタスク側セキュリティグループのインバウンドで許可しているソース
sg-08cc9df02c19c0530(note-app-alb-sg)
→つまり、別のALB用セキュリティグループを許可している!
この場合、実際の note-app-api-alb から来る通信は、ECSタスク側セキュリティグループで許可されていないため、ALB → ECSタスクで通信できず、504 Gateway Time-out になる
ECSタスク側セキュリティグループで許可する
許可する内容はこれ
タイプ: カスタム TCP
プロトコル: TCP
ポート範囲: 8000
ソース: sg-036fbc39407760f91
EC2
→ セキュリティグループ
→ 検索欄に ECSタスク側セキュリティグループ(sg-0cbd03a39f7d3f03a)を入力
→ セキュリティグループ詳細画面でインバウンドルールを開く
→ インバウンドのルールを編集
以下のようにルールを追加する
| 項目 | 入力内容 |
|---|---|
| タイプ | カスタム TCP |
| プロトコル | TCP 自動選択 |
| ポート範囲 | 8000 |
| ソース | カスタム |
| ソース欄 | sg-036fbc39407760f91 |
ターゲットグループを確認
EC2
→ ターゲットグループ
→ 対象のターゲットグループ
→ Targets タブ
対象のターゲットグループのヘルスステータスを確認して、「healthy」になっていることを確認
再度curlして、期待結果({"status":"healthy"})が返ってくることを確認
正しく返ってきたので、ALB → ECSタスク → アプリの疎通は成功

今回の流れ
最初:
Couldn't connect to serverが発生
→ インターネットからALBの80番に届いていなかった
→ ALB側セキュリティグループにHTTP:80を許可して解消
次:
504 Gateway Time-outが発生
→ ALBまでは届くが、ALBからECSタスクに届いていなかった
→ ECSタスク側セキュリティグループで、正しいALB SGからのTCP:8000を許可して解消
現在:
ターゲットグループが Healthy
→ ALBからECSタスクの8000番へ到達でき、/health が正常応答している
参考リンク
Application Load Balancer のトラブルシューティング(公式)





