TL;DR

S3 Batch Operations めちゃくちゃ便利。ただし料金には注意。

やりたかったこと

  • S3 のあるバケットに保存されている画像を一括でリサイズする
  • リサイズの処理は Python 3.7 で実装する (Lambda のランタイム Python 3.7)

やったこと

リサイズ処理用の Lambda 関数を実装する

「バッチオペレーション リサイズ」などでぐぐると、だいたい Node.js での実装例が出てきます。現時点で Node.js が書けないという言い訳をしながら、今回は Python でリサイズ処理を実装しました。ソースは GitHub に置いています。

michimani/resize-s3-image: This function resizes the image in Amazon S3. This function is supposed to be called by Amazon S3 Batch Operations.

リサイズに関しては Python の画像処理ライブラリ Pillow を使ったので特に難しくはなかったです。が、一つ前の記事でも書いた通り、 Pillow には OS に依存する部分があるため、デプロイパッケージとして Lambda にアップロードする際に工夫が必要でした。
ローカルの PC (今回は macOS) でインストールした Pillow をそのままアップロードしたところ、[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': cannot import name '_imaging' from 'PIL' (/var/task/PIL/__init__.py) が発生し、実行できませんでした。

Lambda は Amazon Linux 上で実行されるため、Amazon Linux 上でインストールした Pillow が必要になります。
ということで今回は Amazon Linux のコンテナイメージを使って Pillow ライブラリ群を準備しました。Docker の利用もほぼ初でしたが、なんとか無事にリサイズ処理実行までたどり着けました。

AWS Lambda で Pillow を使おうとしたらハマった - michimani.net

S3 インベントリレポートを作成する

まずは S3 Batch Operations の対象となる S3 オブジェクトの一覧を準備します。おそらく手作業でも作成できますが、今回は対象が数万件にも及ぶため S3 のインベントリレポート機能を使います。
対象となるバケットの 管理 タブで インベントリ を選択します。

create S3 inventory report setting
  • インベントリ名
    任意の名前を入力します
  • フィルター
    バケット内の特定のパスのみを対象にしたい場合にはここでプレフィックスを指定します。今回はバケット直下の blog_images というフォルダ内にあるオブジェクトを対象としたかったので、 blog_images と入力しました。/ は不要です。
  • 送信先バケット
    インベントリレポートとして出力されるオブジェクトの保存場所です。任意の S3 バケットを指定します。
  • 送信先プレフィックス インベントリレポートとして出力されるオブジェクトのプレフィックスです。入力しない場合は、 s3://送信先バケット/インベントリ名/ 以下にインベントリレポートのオブジェクトが生成されます。
  • 頻度
    どれくらいの頻度でレポートを生成するか選択します。今回はとりあえず 1 回生成できれば良いので 日別 としておいて、レポートが作成されたのちにインベントリの設定を削除しました。

インベントの設定をしてから最初のレポートが作成されるまでには 最大 48 時間 かかります。これ以上経っても作成されない場合は何かしら設定が間違っている可能性があります。私の場合はフィルターの指定で末尾に / を付けていたため生成されませんでした…。

S3 Batch Operations のジョブを作成する

S3 Batch Operations は S3 コンソールの左にある バッチオペレーション から設定します。
ジョブは 新規作成 または 以前に実行したジョブを クローン する形で作成します。クローンした場合は諸々の入力欄をクローン元のジョブから引き継ぎます。

create batch operations job 1

リージョン は、今回は アジアパシフィック(東京) を選択します。
マニフェスト とは、 Batch Operations の対象となるオブジェクトを指定するものです。ここで、事前に作成したインベントリレポートに含まれるオブジェクトをマニフェストとして指定します。
マニフェストの指定方法としては、インベントリレポートとして生成される manifest.json または、 CSV を使用します。CSV については、インベントリレポートが生成されたバケット内に data/{ランダムな英数字}.csv.gz という名前で保存されているので、これを解凍して使用できます。
今回は manifest.json を使用するので、 マニフェストオブジェクトへのパスmanifest.json へのパスを指定します。

create batch operations job 2

オペレーション としては画像ファイルのリサイズなので、 AWS Lambda を選択して、実行する関数、バージョンを指定します。
実行する関数は、上で書いた関数です。

create batch operations job 3

追加オプション に関しては、オプションなので適宜設定内容を変更してください。完了レポート として出力されるのは、対象となる各オブジェクトに対して処理が成功したかどうかなどが含まれます。

アクセス許可 については、この Batch Operations に付与するアクセス権のことです。具体的には、対象となるオブジェクトが保存されているバケットに対する Get* の権限と、完了レポートを送信するバケットへの Put* の権限です。また、 IAM ロールの信頼関係として、 batchoperations.s3.amazonaws.com を指定します。

これらの設定ついては、 IAM ロールのポリシーテンプレートと IAM 信頼ポリシーを表示 をクリックするとポリシー設定用の json が表示されるので、それをそのまま使用して IAM ポリシー、 IAM ロールを作成します。

create batch operations job 4

内容を確認してジョブを作成します。

S3 Batch Operations のジョブを実行する

ジョブを作成した時点では、まずは対象となるオブジェクトの合計が計算されます。

run batch operations job 1

合計が計算されると、ステータスが 確認待ち となります。確認待ちになったら、ジョブ ID をクリックしてジョブの詳細を表示します。

run batch operations job 2

そして、画面上部に表示されている 確認して実行 ボタンを押します。ここで初めてジョブが実行されます。画面上にも表示されていますが、確認待ち の状態で一定期間放置すると、ジョブは失敗扱いとなります。

確認して実行 ボタンを押すと、すぐにジョブが始まります。ステータスとしては アクティブ完了中完了 と遷移します。

run batch operations job 3

今回の対象は 57,568 件でしたが、実行ボタンを押してから完了になるまでにかかった時間は、 3 分程度でした。

料金には注意

こんな便利な S3 Batch Operations ですが、 1 回の実行につき 0.25 USD の料金が発生します。対象オブジェクトの個数に関係無くです。
短時間で処理が終わるからと言ってなんども実行するのはやめましょう。

まとめ

  • S3 Batch Operations を初めて使ってみた。
  • 数万件のオブジェクトに対する処理が短時間で完了する。すごい。
  • 料金には注意。
  • Lambda のデプロイパッケージには OS 依存に注意する。

以上、よっしー (michimani) でした。

Share to ...

Follow on Feedly

comments powered by Disqus