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レベルの障害だったが、リージョンレベルでの障害には対応できない
OneLoginとRedashのSAML連携方法
トリプル・ダブリュー・ジャパン株式会社でソフトウェアアーキテクトをしています西田です。ネット上では主にkbigwheelの名前で活動しています。
最近社内ではredashの重要性が増しており、同時にアカウント管理のコストが徐々に増えてきました。 すでに社内ではIDaaSとしてOneLoginが導入されており、redashとのSAML連携ができる環境ができていたのですが一方でSAML連携を一から設定することは難易度が高く、過去複数人が何度か設定に挑戦したものの今まで正しく設定できたことがありませんでした。 今回改めて時間を取って問題解決を図ったところ、どうすれば正しく連携できるかがわかりましたのでこちらで手順を残しておきます。
前提
以下の環境で作業を行いました。
- 2019/06/19時点でのOneLogin
- AMIから作成したredash入りのEC2インスタンス(redash.4.0.1.b4038)
- OneLogin, redash共に管理権限を持っている
連携手順
1. OneLoginでredash用のAppを追加
- OneLoginの管理画面に行く
- 「Apps」を選択
- 「Add Apps」を選択
- キーワード「saml」で検索
- 「SAML Test Connector (Advanced)」を選択して追加
- Display Nameを入力(何でも良いです)
- 「Save」を選択
2. SAML MetadataのURLを取得
- 先程作ったOneLogin上のredash用Appの設定画面を開く
- 「MORE ACTIONS」を選択
- 「SAML METADATA」を 左クリックせず右クリックからリンクをコピー
- コピーしたURLをどこかへ控えておく
3. redashにSAML MetadataのURLを設定
- redash管理画面のSettingsタブを開く ( https://{your_domain}/settings/organization )
- 「SAML enabled」をチェック
- 「SAML Metadata URL」へ先程控えたURLをペースト
- 右下に保存成功と出ることを確認
4. OneLogin上の自分自身のユーザーへOneLoginでredash用のApp実行権限を付与
以下のテストのため、自分自身のユーザーへ①で作成したAppの実行権限を付与します(付与方法は直接/Role経由/Group経由などどれでも良いです)。 付与したあとにoneloginのポータルに表示されていることを確認すると確実です。
4. OneLogin - Redash連携固有の問題を解決
ここまではマニュアル通りの手順でしたが、ここまで行った後にredashのログイン画面から「SAML Login」ボタンを押すとredashサーバ側で500 Internal Server Errorが発生しました。
以下の手順はredashサーバのエラーログから特定した問題の解決法になります。
4.1 redash側から要求されているパラメータrecipientの設定
redash用Appの設定画面のrecipientに次の文字列を設定
http://{your_domain}/saml/callback?org_slug=default
4.2 pyyml2の want_assertions_signed
オプションを無効化
ssh {redashのサーバ} sudo vim /opt/redash/redash.4.0.1.b4038/redash/authentication/saml_auth.py 46行目の 'want_assertions_signed': True, を 'want_assertions_signed': False, に書き換え
4.3 redash側から要求されている属性FirstName/LastNameの設定
RedashでSAML認証できるまで - Cybozu Inside Out | サイボウズエンジニアのブログにも書かれている通りredashは
認証応答メッセージ(Response)のSAMLアサーションの属性ステートメント(AttributeStatement)に、"FirstName"と"LastName"が含まれていることを期待している
です。 OneLoginはこのパラメータへユーザーごとに別の値を設定する仕組みを提供していますが、今回は動作確認のため私のFirstName/LastNameをそのまま固定値で書きました。
5. 動作確認
以上を行い再びredashのトップ画面から「SAML login」ボタンを押したところ、正常にログインすることができました。
6. ユースケースごとに適切な設定を行う
- redashへのアクセスを許可したい人に、OneLogin上のredash用のAppの実行権限を付与
- FirstName/LastNameへ適切な値を設定
RFC7807に沿ったエラーレスポンスの実践について
トリプル・ダブリュー・ジャパン株式会社でソフトウェアアーキテクトをしています西田です。ネット上では主にkbigwheelの名前で活動しています。
今回は最近私達のチームで行ったRFC7807に沿ったエラーレスポンスの実践について紹介します。
RFC7807とは
2016年にIETFから発行された、新しいHTTP APIのエラーレスポンス形式*1です。 日本語の解説記事は非常に少ないですが、こちらのブログで非常にわかりやすく要所を日本語に翻訳しつつ説明されています。
この標準に沿うことで新しい開発メンバーへ仕様を共有することが簡単になります。 また過去にこの仕様を見たことがあれば、新たに勉強することは最小限で済みます。
サーバサイドチームの取り組み
私が所属するサーバサイドチームでは11月にAPIサービスの大幅なバージョンアップを行いました。 しかし、エラーレスポンスの仕様(特にレスポンスボディの仕様)が曖昧なままでアプリチームがハンドリングしたい粒度でエラー原因を返せていませんでした。 そこでエラーケースを再定義するとともにアプリがハンドリングするために必要十分な情報を持たせるよう改修を行うことになったのですが、どうせエラーレスポンス仕様を変更するならより標準的なフォーマットに寄せたいと考えた結果採用したのがRFC7807です。
仕様定義
RFC7807が定義する仕様にはいくつかの選択肢があります。 レスポンスフォーマットをJSONとXMLのどちらにするか、いくつかあるプロパティのうちどれを利用するか、などです。 それらについて私達のサービスではどれを使用するかを決めてgithub wiki上のページへ以下のようにまとめました(実際のエラーコード・URLとは変更しています)。
上に書かれていますが基本的に以下のように仕様を定めました。
ヘッダ
- Content-Type: application/problem+json
プロパティ
- type, titleのみを利用する。 またそれらのプロパティは必須であり、レスポンスによって特定のプロパティが欠けるようなことはない。
サンプル
HTTP/1.1 400 Bad Request Content-Type: application/problem+json { "type": "/api/v5/errors/invalid-device-id", "title": "Invalid deviceId." }
HTTP/1.1 403 Forbidden Content-Type: application/problem+json { "type": "about:blank", "title": "The supplied authentication is not authorized to access this resource" }
また私達のAPIはOpenAPI Specificationで書かれてswagger-uiからいつでも参照できるようになっています。 こちらには各APIごとのエラーレスポンスの仕様が細かく書かれていましたので、こちらも合わせて修正しました。
この仕様決定とドキュメントの作成・更新に比較的時間がかかり、だいたい合計5人日ぐらいかかったイメージです。
実装について
APIサーバはScala言語で書かれておりakka-httpフレームワークで作られています。 今までもRFC7807準拠ではなかったもののJSONフォーマットでエラーレスポンスを返していたので、だいたい実装期間は3人日程度でした。
リリースについて
修正内容に既存のAPI利用を阻害するような破壊的な内容がなかったため、通常通りのリリース手順でリリースしました。
API利用側の反応
2019/02/01現在アプリ側で増強されたエラーレスポンス情報を利用するコードが書かれておらず、まだフィードバックは特段ない状態です。
やってみた感想
エラーレスポンス仕様はまだ大手の公開APIでも完全にバラバラな状態で(参考: WebAPIでエラーをどう表現すべき?15のサービスを調査してみた - Qiita)各種WebフレームワークのRFC7807サポートもほとんどない状態ですが、個人の嗜好や趣味によって行き当たりばったりに決めるよりRFC準拠で実装することは様々なメリットがあります。 毎回APIの仕様を決めるときは数ある選択肢からどういったものにするか非常に悩むのですが、今回RFCという明確な指針に従ったことで非常に楽に仕様を決めることができました。今回決めた仕様は将来もっと良いものに拡張する可能性もありますが、今回はこちらでリリースしています。
各フレームワークも徐々にRFC7807をサポートしつつあるので導入はこれからもっと楽になると思います。
Add Media types for RFC 7807 by bigwheel · Pull Request #2323 · akka/akka-http*2
みなさんもっとRFC7807に従うことで、つまらない詳細の仕様に悩まずより重要なビジネスロジックに集中できるようにしましょう!
AWS re:invent 2018 社内で活用できそうなアップデートまとめ
こんにちは! トリプル・ダブリュー・ジャパン株式会社でサーバサイドリードエンジニアをしています西田です。ネット上では主にkbigwheelの名前で活動しています。
先日、私達の会社でもフル活用しているAWSの新機能・新サービスを発表するre:inventというイベントがありました。
こちらの記事では発表された中から社内で活用できそうなものをリストアップしたいと思います。 アップデートの一覧は以下の公式ブログの記事からいただきました。
- re:Invent 2018 11月26日 アップデートのまとめ | Amazon Web Services ブログ
- re:Invent 2018 / 11月27日 アップデートのまとめ | Amazon Web Services ブログ
- re:Invent 2018 / 11月28日 アップデートのまとめ | Amazon Web Services ブログ
- re:Invent 2018 / 11月29日 アップデートのまとめ | Amazon Web Services ブログ
- re:Invent 2018 / 11月30日 アップデートのまとめ | Amazon Web Services ブログ
目次
すぐに使いたいもの
- New – Amazon CloudWatch Logs Insights – Fast, Interactive Log Analytics | AWS News Blog
- 非常に良いアップデートです。cloudwatch logsは検索機能に癖があることが問題で、そのためにログをS3へ移してathenaで検索などの回避策すら取っていました。これができたことでむしろS3上に作られるELBのログをcloudwatch logsへ載せて検索することがスタンダードになるかもしれません。
- New – Amazon DynamoDB Transactions | AWS News Blog
- これも素晴らしいアップデートですが、一方で乱用すると本来のパフォーマンスを発揮できなくなる気がします。UpdatedItemでアトミックな操作は従来もできていたので、なるべく最低限の利用に留めるのがいい気がします。ここはベストプラクティスの蓄積を待ちたいところ
- The AWS Developer Tools Improve Continuous Delivery Support for AWS Fargate and Amazon ECS
- Fargate / ECS / ECRとCode Pipeline / CodeDeployの統合がより進みました。Code PipelineとECRの結合は実は社内ですでに利用していますが、微妙な問題はありつつも基本的にはデプロイフローが非常にスッキリしていい感じです。
- 新発表 – AWS Toolkits for PyCharm、IntelliJ(プレビュー)、Visual Studio Code(プレビュー) | Amazon Web Services ブログ
- 該当のIDEでlambda開発をしているならすぐに試してみたいところ
- re:Invent 2018 / Andy Jassy Keynote / Amazon Timestream | Amazon Web Services ブログ
- 大きな可能性を感じるプロダクトです。InfluxDBなどと同様に時間に最適化した操作・演算ができます。IoTのセンサーデータなどを入れるのに最適なのですぐにでも検討したいところ
- Amazon DynamoDB On-Demand – 事前のキャパシティプランニングが不要のリクエスト課金が可能になりました。 | Amazon Web Services ブログ
- 負荷を計算せず開始できるため非常に有用ですが、一方で負荷が一定で安定している場合はリザーブドキャパシティのほうが安くなるそうです。
- re:Invent 2018 / Werner Vogels Keynote / Serverless Updates | Amazon Web Services ブログ
詳細によっては使えそうなもの
- AWS のマイクロサービスのための サービスメッシュ - AWS App Mesh のご紹介
- マイクロサービス的な設計をしているシステムでは待望の機能だと思います。うちはコンテナからlambdaへ移行しつつあるので逆に必要性は薄まっているかも
- AWS Cloud Map の紹介
- サービスディスカバリのAWSマネージドサービス。ARNが引けるのが最大のポイントです
- 新機能 – AWS Lambda :あらゆるプログラム言語への対応と一般的なコンポーネントの共有 | Amazon Web Services ブログ
- Arm ベースの新しいAWS Graviton プロセッサによる Amazon EC2 A1 インスタンスのご紹介
- 従来のx86系と比べてコストパフォーマンスが良いそうです。armプロセッサでもよい用途なら活用できそう
- re:Invent 2018 / Andy Jassy Keynote / AWS Control Tower | Amazon Web Services ブログ
覚えておきたいもの
IoT系
- IoT系の機能追加は非常に多かったです。セッション内でもいくつもおおっと思わせる機能があったのですが基礎知識がないこともありすべてを理解することはできませんでした。以下には公式のアップデート記事があるものを載せます。
- AWS IoT Events のプレビューを提供開始
- re:Invent 2018 Midnight Madness/ AWS Transfer for SFTP | Amazon Web Services ブログ
- AWS IoT Greengrass の機能が外部アプリケーションコネクタ、ハードウェアを信頼の起点としたセキュリティ、隔離設定により拡張される
- 新発表 – AWS Well-Architected Tool – クラウドベストプラクティスのレビューツール | Amazon Web Services ブログ
- re:Invent 2018 Midnight Madness/ AWS Transfer for SFTP | Amazon Web Services ブログ
- re:Invent 2018 / Andy Jassy Keynote / Amazon Textract | Amazon Web Services ブログ
- 良さげですがまだ日本語を使えないそうなのでそれ待ちですね
- Amazon S3 Introduces S3 Batch Operations (Preview) for Object Management
- S3上の大量のデータに対して一括処理を書けたいときに有用ですが、そもそもなるべくそういった処理がいらないようなデータのパイプラインを設計したいところ。
- 新発表 – Amazon FSx for Lustre | Amazon Web Services ブログ
*1:毎度お世話になっています
AWS re:Invent 2018 ダイジェスト 特別講演 レポート
こんにちは! トリプル・ダブリュー・ジャパン株式会社でサーバサイドリードエンジニアをしています西田です。ネット上では主にkbigwheelの名前で活動しています。
本日業務の一貫としてこちらのイベントに参加してきました。
その中からおそらくキーノートに相当する午前中の特別講演について非常に簡単にですがレポートしたいと思います。会場のルールとして発表中の撮影が禁止されていたため画像が皆無ですがご了承ください*1。
特別講演 re:Invent 2018 サマリーと新サービス概要
特別講演 re:Invent 2018 サマリーと新サービス概要 〜午後のテクニカルセッションをよりお楽しみいただくために〜 亀田 治伸 アマゾン ウェブ サービス ジャパン株式会社 プロダクトマーケティング エバンジェリスト
話の流れとしては題にある通りre:inventというイベント全体の流れを説明して午後のテクニカルセッションを理解しやすくするためのものでした。 全5日に渡るre:inventについて各曜日に何が行われたか、発表されたサービスなどの概要が説明されます。
以下特に記憶に残っている点を書き出しました。
人工衛星との連携や全世界規模の海底ケーブルプロジェクトへの参入
awsがクラウド分野を開拓してからまだ12年ですが、いよいよ話が大きくなってきたなと思いました。 この人工衛星との連携というのは受信側の話だそうですが、この分だとawsが自ら人工衛星を打ち上げる(そしてそれがサービスになる)のもそう遠くなさそうです。
「開発者」改め「ビルダー」という呼称
一部で物議を醸した開発者の代わりとなるビルダーという呼び方についての説明がありました。 弁明めいて聞こえたのは僕の気のせいかもしれませんが、やはりビルダーという呼称はイマイチしっくり来ないなと感じました。
新機能/サービス公開と顧客数が加速的に増加していることをアピール
去年のre:inventと比べて今年はより多くの新機能を公開しているということでした*2。 また顧客数の増加もより加速しているそうです。でもその測定方法や詳しい値は一切公開されていなかった点は留意しましょう。
DBに関してはOracle社にやり返す
DBに関してはかなり面白い一幕がありました。 Aurora, RDS for MySQL/PostgreSQLで競合しながら同時にRDS for Oracleでは顧客であるAmazonとOracleの関係は、最近Amazonが社内DBをOracleからRedshiftへ変更したことにより一気に冷え込みつつあるそうです。
Amazonプライムデーのサーバ障害、原因は「OracleからAurora DBに乗り換えた」ではない――CTOがCNBCの報道を否定 (1/3) - ITmedia エンタープライズ
今回の発表の中でも「ビルダーはプロダクトに不当に縛られるべきではない、どこの会社とは言わないが」という趣旨の発言がありました。DBについて話している途中出会ったことからもOracle社のことだったのは間違いないでしょう。 前職でOracle Databaseに振り回された身としては個人的には大いに同意するところです。
まとめ
以上になります。短くはありますが軽く雰囲気だけでも掴んで頂ければ幸いです。
この記事は2.5%ルールに従い業務時間を利用して書かれました。