CloudFrontで502エラーが起きた時に確認したこと

## 何が起こったか
自社プロダクトのURLにアクセスすると502エラーが返ってくると社内のチャットで連絡があり原因を調査することに。
商用環境のため迅速に復旧する必要があったのですが、調査でつまずいてしまい結果的に上司が解決してくれるという情けない結果になってしまったので今後の障害発生時に迅速に原因究明できるよう忘備録として残します。

## 全体の構成
通信経路としては、Route53⇢CloudFront⇢ALB⇢EC2の流れです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492874/572fcfec-1b77-8c22-c063-67a2898d38ad.png)

## 先に結論
結果的にはCloudFrontの証明書の期限が切れていて502エラーとなっていました。
ACMで取得した証明書は自動で更新されるイメージだったのですが、今回CloudFrontにアタッチされていた証明書はEメール検証を使用していたため手動で更新する必要があったようです。
[AWS Certificate Manager E メール検証
](https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/email-validation.html)

## 502エラーとは
一旦今回起こった502エラーについて以下のaws公式ドキュメントを元に確認します。
[HTTP 502 ステータスコード (Bad Gateway)](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/http-502-bad-gateway.html)

1.CloudFrontのドメイン名とオリジンで設定した証明書の値が一致していない
>CloudFront とオリジンの間で HTTPS を必要とするカスタムオリジンを使用すると、ドメイン名が一致しない場合にエラーが発生する可能性があります。オリジンの SSL/TLS 証明書には、CloudFront ディストリビューションに指定した [オリジンドメイン] またはオリジンリクエストの Host ヘッダーのいずれかに一致するドメイン名が含まれている必要があります。
ドメイン名が一致しない場合、SSL/TLS ハンドシェイクは失敗し、CloudFront は HTTP 502 ステータスコード (Bad Gateway) を返し、X-Cache ヘッダーを Error from cloudfront に設定します。

これはCloudFrontに設定したオリジンドメイン名と、オリジン（今回だとALB）に設定した証明書の値が一致していない為に発生するパターンです。

例えばCloudFrontのオリジンドメイン名がhoge.comで、ALBに設定した証明書の値がfuga.comのような場合ですね。

2.CloudFrontの証明書の期限が切れている
> オリジンの SSL/TLS 証明書が期限切れ、無効、自己署名になっている、または間違った順番の証明書チェーンになっている
オリジンサーバーから、CloudFront が TCP 接続を中断する、HTTP ステータスコード 502 (Bad Gateway) を返す、X-Cache ヘッダーを Error from cloudfront に設定するなどのレスポンスがある場合:
証明書が期限切れです
証明書が無効です
証明書が自己署名です
間違った順番の証明書チェーンです

今回の場合はこれです。オリジンとの通信にACMの証明書を使用したHTTPS通信を設定しているのに期限が切れていたためオリジンとの接続が確立されずCloudFrontからエラーが返されていました。

3.CloudFrontで設定したオリジンのポート番号がオリジン側で許可されていない
> CloudFront ディストリビューションでオリジンを作成するときに、HTTP および HTTPS トラフィックのために CloudFront がオリジンへの接続に使用するポートを設定できます。デフォルトでは TCP 80/443です。これらのポートは変更可能です。これらのポートで、オリジンが何らかの理由でトラフィックを拒否している場合やバックエンドサーバーが応答していない場合、CloudFront は接続に失敗します。

これは今回は原因ではなかったですが結構ありそうな気がしました。
例えばALBに設定したSecurityGroupで443開けていないとか。

## 最初に確認すべきこと
今回は以下のようなCloudFrontが返したことが分かるエラー文がでていたので、まずはエラーメッセージをちゃんと読んで、原因箇所の切り分けを素早く済ませるべきでした。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492874/cbbd6216-39d1-6178-1307-08a992e6f002.png)

僕はまずRoute53のレコードから確認していたので、ちょっと時間かかりました。
そうすれば後は該当するCloudFrontのエラーパターンをいくつか調査すれば解決できたと思います。

## 他の調査方法
以下上司が切り分けのために実施したことについて。
今回の構成ではRoute53⇢CloudFront⇢ALBとなっており、障害が発生したドメイン経由でのアクセスではCloudFrontを経由するためエラーが出ます。
しかし原因がCloudFrontだけであるとは限らず、サイトを置いているサーバーやALBに問題がある可能性もあります。
そこで、どこまでは通信が正常なのか確認するために、ローカルPCのhostsファイルを編集し、ALBに通信が直接飛ぶようにしてみます。
イメージとしては以下のような感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492874/ecd0f5b4-a552-def2-df14-b4e9dd13f21b.png)

hostsファイルの一番下に以下のように追記します。
```
127.0.0.1	localhost
127.0.1.1	pc
1.1.1.1 fuga.com
```

上記のようにすることで、fuga.comにアクセスすると、ヘッダーにfuga.comを入れながらALBに直接アクセスでき、ALBのリスナールールの条件に合致したターゲットにルーティングされます。
ここで正常に通信が行えればALBより後ろ側には問題がなく、CloudFront⇔ALB間に問題があることがわかります。
ALBは2つのAZ上冗長化されていて、IPがマネコン上では確認できないのでdigで調べます。
hostsファイルについては以下を参照ください。
[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word16969.html)

## 終わりに
今回はCloudFront構成での障害発生時の確認ポイントについて紹介しました。
そもそも論ではありますが、いざという時に慌てないためにも自社プロダクトのインフラ構成についてしっかりと把握することと、エラーメッセージをちゃんと読む事の大切さを感じました。
この記事が誰かの参考になりましたら幸いです。