S3 Batch Operations で S3 に保存された数万件の画像を一括でリサイズしてみた
2019-06-24S3 Batch Operations を使って S3 に保存された数万件の画像を一括でリサイズしてみた話です。
目次
TL;DR
S3 Batch Operations めちゃくちゃ便利。ただし料金には注意。
やりたかったこと
- S3 のとあるバケットに保存されている画像を一括でリサイズする
- リサイズの処理は Python 3.7 で実装する
やったこと
リサイズ処理用の Lambda 関数を実装する
「バッチオペレーション リサイズ」などでぐぐると、だいたい Node.js での実装例が出てきます。現時点で Node.js が書けないという言い訳をしながら、今回は Python でリサイズ処理を実装しました。ソースは GitHub に置いています。
リサイズに関しては 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 の利用もほぼ初でしたが、なんとか無事にリサイズ処理実行までたどり着けました。
S3 インベントリレポートを作成する
まずは S3 Batch Operations の対象となる S3 オブジェクトの一覧を準備します。おそらく手作業でも作成できますが、今回は対象が数万件にも及ぶため S3 のインベントリレポート機能を使います。
対象となるバケットの 管理 タブで インベントリ を選択します。
- インベントリ名
任意の名前を入力します - フィルター
バケット内の特定のパスのみを対象にしたい場合にはここでプレフィックスを指定します。今回はバケット直下のblog_images
というフォルダ内にあるオブジェクトを対象としたかったので、blog_images
と入力しました。/
は不要です。 - 送信先バケット
インベントリレポートとして出力されるオブジェクトの保存場所です。任意の S3 バケットを指定します。 - 送信先プレフィックス
インベントリレポートとして出力されるオブジェクトのプレフィックスです。入力しない場合は、
s3://送信先バケット/インベントリ名/
以下にインベントリレポートのオブジェクトが生成されます。 - 頻度
どれくらいの頻度でレポートを生成するか選択します。今回はとりあえず 1 回生成できれば良いので日別
としておいて、レポートが作成されたのちにインベントリの設定を削除しました。
インベントの設定をしてから最初のレポートが作成されるまでには 最大 48 時間 かかります。これ以上経っても作成されない場合は何かしら設定が間違っている可能性があります。私の場合はフィルターの指定で末尾に /
を付けていたため生成されませんでした…。
S3 Batch Operations のジョブを作成する
S3 Batch Operations は S3 コンソールの左にある バッチオペレーション から設定します。ジョブは 新規作成 または 以前に実行したジョブを クローン する形で作成します。クローンした場合は諸々の入力欄をクローン元のジョブから引き継ぎます。
リージョン は、今回は アジアパシフィック(東京) を選択します。
マニフェスト とは、 Batch Operations の対象となるオブジェクトを指定するものです。ここで、事前に作成したインベントリレポートに含まれるオブジェクトをマニフェストとして指定します。
マニフェストの指定方法としては、インベントリレポートとして生成される manifest.json
または、 CSV を使用します。CSV については、インベントリレポートが生成されたバケット内に data/{ランダムな英数字}.csv.gz
という名前で保存されているので、これを解凍して使用できます。今回は manifest.json
を使用するので、 マニフェストオブジェクトへのパス で manifest.json
へのパスを指定します。
オペレーション としては画像ファイルのリサイズなので、 AWS Lambda を選択して、実行する関数、バージョンを指定します。実行する関数は、上で書いた関数です。
追加オプション に関しては、オプションなので適宜設定内容を変更してください。
完了レポート として出力されるのは、対象となる各オブジェクトに対して処理が成功したかどうかなどが含まれます。
アクセス許可 については、この Batch Operations に付与するアクセス権のことです。具体的には、対象となるオブジェクトが保存されているバケットに対する Get*
の権限と、完了レポートを送信するバケットへの Put*
の権限です。また、 IAM ロールの信頼関係として、 batchoperations.s3.amazonaws.com
を指定します。
これらの設定ついては、 IAM ロールのポリシーテンプレートと IAM 信頼ポリシーを表示 をクリックするとポリシー設定用の json が表示されるので、それをそのまま使用して IAM ポリシー、 IAM ロールを作成します。
内容を確認してジョブを作成します。
S3 Batch Operations のジョブを実行する
ジョブを作成した時点では、まずは対象となるオブジェクトの合計が計算されます。
合計が計算されると、ステータスが 確認待ち
となります。確認待ちになったら、ジョブ ID をクリックしてジョブの詳細を表示します。
そして、画面上部に表示されている 確認して実行 ボタンを押します。ここで初めてジョブが実行されます。画面上にも表示されていますが、確認待ち の状態で一定期間放置すると、ジョブは失敗扱いとなります。
確認して実行 ボタンを押すと、すぐにジョブが始まります。ステータスとしては アクティブ
→ 完了中
→ 完了
と遷移します。
今回の対象は 57,568 件でしたが、実行ボタンを押してから完了になるまでにかかった時間は、 3 分程度でした。
料金には注意
こんな便利な S3 Batch Operations ですが、 1 回の実行につき 0.25 USD の料金が発生します。対象オブジェクトの個数に関係無くです。
短時間で処理が終わるからと言ってなんども実行するのはやめましょう。
まとめ
- S3 Batch Operations を初めて使ってみた。
- 数万件のオブジェクトに対する処理が短時間で完了する。すごい。
- 料金には注意。
- Lambda のデプロイパッケージには OS 依存に注意する。
comments powered by Disqus