雑多に技術メモと他色々

主に自分用な技術メモが多くなる気がする。他色々が書かれるかどうかは不明。

AWSでマネージドサービスの異常発生をテストしたい時はどうするか

AWS便利なんだけど、基本的にAPI叩くときはエラーが発生することを考慮して設計するのが原則である。
(Design for Failure)
これが原則と言われるものの、いざエラーが発生した状況を再現しようとするとなかなか難儀なのである。
エラー発生時のリカバリ処理を仕込んだはいいけど、発生頻度が低くて正しくリカバリされるかテストしきれず、苦労するようなケースが結構出る。

どうにもスタンダードな方法は確立されてない感じで、こんなやり方があるんじゃないかというものを一覧化。

運用中は発生しないけどとりあえずエラーになればいい系

AWSの認証情報を通らないものに書き換える

Credentialを使っているなら中身を書き換える、IAMRoleで認証されるケースならRoleを変更する、といった手段でサービスに対して認証が外れるようにする。
通常運用でこれが発生したら設定ミスなので、まともに動いてる状態では発生しない理屈。

サービス内で利用する対象の定義を存在しないものに変更

S3ならバケット名、Dynamoテーブル名といったものが容易に設定変更できるように組んでいるなら、その定義を変更することで存在しないリソースへアクセスする系のエラーが起きる。
これもまともに動いてる状態では発生しない系。
※ S3バケット名はグローバルなので、不意に存在するバケットにアクセスすることを避ける目的も含めてやらないほうがいいかも。

サービス利用するEC2などから外部へ通信する口を閉じる

AWSサービス利用は各種サービスエンドポイントへのAPI実行で実現するので、ネットワーク設定で外部通信不可などにすれば失敗するという理屈。
これはあまりやらないと思う。そもそもAWSサービスを利用している部分まで処理が到達するかどうかも不安。

ある程度運用中に発生するエラーを狙う系

API互換のライブラリを使ってエラーを発生させる

一部のAWSサービスは、テスト用やスタンドアロン動作を目的にしたAPI互換のライブラリ(ミドルウェアか?)が存在する。
接続先設定をこちらに切り替えた上で、エラーが発生するように設定するといった対処。
それぞれが意図的なエラー発生に明確に対応しているかどうかは見切れていないが、本物サービスでエラー発生を期待するよりはやりやすいと思う。

AWSサービス スタブサービス
DynamoDB DynamoDB Local
S3 FakeS3
S3 riak_cs Dockerイメージがあるので使うつもりがあればささっと立ち上がるらしい
SQS ElasticMQ

参考:
java - AWS S3 local server for integration testing - Stack Overflow
ローカルにAmazonSQS互換のMQを起動して使ってみる - Qiita

APIエンドポイントをダミー化してエラーを発生させる

AWSは各種サービス+リージョンに対応するAPIのエンドポイントを公開している。
AWS サービスエンドポイント - AWS 全般のリファレンス
/etc/hostsなどにダミーのホスト定義を設定すれば、狙ったサービスのAPIのみを任意の接続先に向けることができる。
APIの互換性保証は怪しいが、タイムアウト系のエラーは容易に再現することができる。
※ ルーティング不可の通信先を指定する、通信先をスタブにして通信受け入れ後にリードタイムアウト以上のスリープを挟むなど。

ひたすら処理を叩き続けてエラー発生を期待する

それなりの負荷で長時間、繰り返しサービス実行する余裕があるならばこれも有り。
実運用で発生しやすいエラー(=重要なところ)から確認して潰していけるというメリットもある。
問題はエラー発生がAWS次第で、狙ったルートを通すことが保証できないことや、リクエストに対する課金系のサービスが結構多いので費用が嵩みそうな点。
不確実性があると、テストの妥当性やシステム納品先の説得が面倒なことになるイメージもある。

サポートに頼んでみる

契約を結んでいるならとりあえず聞いてみるのもありか。
ロットリングやサービス上限抵触を発生しやすくするために、一時的に上限値を下げるくらいの対応はとってくれるかもしれない。
意図的に内部エラーを起こすといったことはたぶん無理だと思う。

異常発生を再現する仕組みをコード上に仕込んで作る

カオスエンジニアリング的な考え方で、ランダムにエラー発生させる仕組みを処理レイヤの境界などに組み込む方法も出てきている。
下記では、SpringBoot上でランダムにRuntimeExceptionを発生させるケースが例示されている。
Chaos Monkey for Spring Bootの使い方 - Qiita
コードの様々な箇所でエラーハンドリング~代替処理が通ることを確認するためにこういったものを使うのも有りだろう。
通常処理と一緒にこういった分岐を自作すると、試験用の処理でコードが汚くなるデメリットが大きいので、必ずライブラリなどを利用してインタセプタ的に実現できる方式を取りたい。

Fault Injection Simulatorを使う(2021/06追記)

障害発生させるための公式サービスも発表された。
対応しているリソースは限られるものの、AWS公式でリソースの障害をシミュレートできる。(有料)
https://docs.aws.amazon.com/fis/index.html
S3やDynamoなどのマネージドサービスだと「ピンポイントに落とす」が難しいが、それらも障害注入のターゲットにして広げていく動きを期待したい。