2019/08/23のAWS大規模障害が40秒のAPIエラーで済んだ理由
トリプル・ダブリュー・ジャパン株式会社でソフトウェアアーキテクトをしています西田です。ネット上では主にkbigwheelの名前で活動しています。
この記事では先日のAWS大規模障害がトリプル・ダブリュー・ジャパンのシステムへどのような影響を与えたのか、またそれに絡めて監視・アラートのフローやシステム設計について紹介します。
AWS大規模障害
2019/08/23の午後、AWSの東京リージョンのEC2およびRDSにおいて大規模な障害が発生しました。
Summary of the Amazon EC2 Issues in the Asia Pacific (Tokyo) Region (AP-NORTHEAST-1)
トリプル・ダブリュー・ジャパンではDFreeサービスでAWSを利用しており、影響が懸念されたのですが幸いにも40秒程度APIがエラーを返す程度で済みました。
障害が発生したときに実際に発生したこと
日時 | 発生源 | 発生したこと |
---|---|---|
2019/08/23 12:59:29 | Mackerel | APIサーバが内部エラーにより500 Internal Server Errorを返したことがslackへ通知される |
2019/08/23 13:00:12 | Mackerel | 上記のエラーが解消したことがslackへ通知される |
2019/08/23 13:01:30 | エンジニア(手動) | APIサーバに装備された各DB・ミドルウェア・外部SaaSとの疎通を確認する専用のHealthCheck APIを叩いて正常に動作していることを確認 |
2019/08/23 13:07:52 | エンジニア | AWSコンソールおよびCloudwatch Logsからエラー原因がDBとのコネクションにあること、その後DBがフェイルオーバーしていることを確認 |
たまたま障害発生の瞬間にエンジニア(私)がslackを見ていたため、問題が発生した瞬間から障害対応と問題原因の調査をすることができました。 結果、8分ほどでDBのフェイルオーバーが発生していることを突き止めています。
監視・アラートのフロー
迅速に障害の発生を感知し、原因調査ができたのは監視・アラートのフローがきちんと設定されていたためでした。
DFreeサービスでは監視やアラートについては現在slackの特定チャンネルへ集約するポリシーを取っています。 監視にはmackerelとCloudwatch Alarmを使用しており、Cloudwatch Alarmの発火はchatbotを通じてslackへ集約しています(以前はSQS, Cloudwatch Events, lambdaと非常に手間でした)。 また、クリティカルなアラートとそれ以外のアラートを別々のslackチャンネルへ分けていたため、今回即座に重大な問題だと判断することができました。
なぜ障害発生の時間が40秒で済んだのか
DFreeサービスが利用しているAWSの構成
DFreeサービスは以下のAWSサービスから構成されています。
私達のチームではリージョン内レベルでの冗長化を基本のポリシーとしています。 Kinesis, S3, DynamoDB, Lambda, ALB, SNSについてはマネージドサービスであるため責任共有モデルに従いAWSへ冗長化を任せており、 ECSでは適切にヘルスチェックとクラスタの最低保証台数を設定することでこれもまた復元をAWSへ任せていました。 RDSについてもMultiAZ設定を有効にすることで2つのリージョンで冗長化しています。
このようにサービスのすべての部分で複数のAvailability Zoneにまたがる冗長化を行っていました。 冒頭のAWSのレポートにも書かれていますが、今回の大規模障害は東京リージョンの2つのAZのうち1つのAZでのみ発生する障害であったため、DFreeサービスでは最小限の影響で済んだと言えます。
ポイント
今回の大規模障害とDFreeサービスでの対応からいくつかのポイントを挙げます。
- マルチAZ対応をしていたためAZレベルの障害へ対応できた
- 監視・アラートのフローはなるべくどこかへ一元化すること
- 重大なアラートとそれ以外のアラートは出力先を分けて、前者の場合は即座に気付けるようにすること
- 両者を混同すると重大でないアラートに重大なアラートが紛れて対応が遅れるケースがよくあります
- AWSのサービスはすべてのログがAWSコンソール上で確認できるため、問題原因の調査が非常に迅速にできる
- 今回の場合CloudWatch Logs(ECSコンテナのログ) → RDSの「ログ・イベント」確認 のフローでしたが、DBのフェイルオーバーが起こっていることを確信するまで8分程度でした
- 今回は特定AZレベルの障害だったが、リージョンレベルでの障害には対応できない