AWS使ってますか??
個人でなり、会社でなり、AWSを使用されている人が最近どんどん増えているのではないでしょうか。たくさんの機能を提供してくれているAWSですが、今回は私の体験談からとてつもなく初歩的なS3の仕様に関して紹介したいと思います。これで皆様が私と同じような体験をしなくて済むように願っています。
この記事はすでに使われておられる方からすれば何を当たり前なことをと思われるかもしれませんが、私はS3にそんな仕様があるとは知らずに無知なまま使ってしまいました。そんなまだ使ったことないけど使ってみようかなって人向けの記事になります。
体験談
本当にあった怖い話
趣味でLambdaを使い、一日一回対象のアカウントのtweetを取得して条件を満たせばretweetするTwitterボットを作成したので、せっかくTwitterのいろいろな情報を取得するならその情報を機械学習とかに使いたいと思い、S3に情報を保存するように改修しました。それに加えてS3に最後に取得したtweetのIDを保存しておいて次はそのID以降のtweetだけを取得させるようにもしようとしました。結果、S3側のLambda連携の設定を作り、Lambdaには以下のような実装をほどこしました。
exports.handler = ()=>{
var bucket = "id"
gets3(bucket) //s3からIDをとってくる処理を記述した関数
doAction() // Tweeterに関する実行関数
puts3(bucket) //s3にあるIDを更新しようとデータを再度登録する関数
}
二日後取れたデータを確認しようとS3を見てみると、そこには目的のデータファイルは存在せず、あるのは大量のログファイルのみ。最初Lambdaの関数のミスを疑ってLambdaを確認してみたのですが、どうもLambdaはうまくいってるっぽい。そこで膨大なS3に残されたログから適当なものの中身を確認してみました。するとなんと一日一回しか実行させないはずのLambdaのgetとputの処理が常時実行されているではありませんか!これはやばいと思って慌ててLambdaを消して請求を確認してももう後の祭り。無意味にgetとpostを繰り返していた結果、最終的に1900ドル強の請求が発生してました......
原因は一体...
今回このような事態を起こしてしまったのは、会社のメールアドレスで登録していて無料枠超えたことに気づかなかったというのもあったのですが、そもそも根本的にS3の仕様を理解していなかったのが原因でした。一体どういうしようかといいますと
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-example.htmlより引用
重要
次のチュートリアルでは、ソース用に 1 つとターゲット用に 1 つの 2 つのバケットを使用していることを前提とします。ソースとターゲットに同じバケットを使用する場合、ソースバケットにアップロードされた各サムネイルは、別のオブジェクト作成イベントをトリガーし、これにより Lambda 関数が再び呼び出されて不要な再帰が行われます。(略)
つまり、あるバケットにデータが登録されるたびにそれに紐づいているS3が実行されてしまうため、一つの関数でそれに紐づけた一つのバケットにデータを登録する実装をしていた関数はS3の仕様に基づき再帰的に登録を繰り返す無限ループに陥ってしまっていたのです。
どうするべきだったの
S3とLambdaを正しく連携させる
先ほどの引用でもあった通り、再帰的に呼ばれないようにバケットを取得用と登録用の二つに分けておくべきでした。それでは目的が達成できないなら、DB関係のサービスとの連携も考えておくべきでした。S3でデータベース的なことができるならそのまま使えばいいじゃんという安易な発想でよく調べもせずに使うものではなかったです。
サービスに関する知識を持って使おう
当たりですが、無料枠があるとはいえ枠を超えれば使用料が発生します。まず使いたいサービスの仕様と料金くらいは初めに押さえておきましょう。私のように押さえたつもりにならないよう、公式のドキュメントを確認しながらどのタイミングで何が実行されるのかしっかり把握してから使われることをお勧めします。
最後に
本当にどうしていいのかわからなくなった状況におちいった場合は、すぐにサポートに連絡しましょう。AWSのコンソールの右上のほうにサポートに相談という項目があるはずです。
私のようなへまをせずに、皆さんは楽しいAWSライフを送ってください!!