[AWS Glue] S3バケットにある大量のファイルを圧縮して別のS3バケットに保存してみた

AWS Glueでは大変お手軽にPython Scriptを実行できるのでお勧めです

こんにちは、AWS事業本部の荒平(@0Air)です。

最近、S3バケットにある大量のファイルをなんとかしてZip化したいとの要望がありました。
大多数の方はLambdaを採用して済むケースが多いと思われますが、Lambdaを使わない方法を考えてみました。

概要

簡単な構成図はこちらです。
ファイル数・容量に振れ幅のあるログファイルなどを想定しているため、別バケットに保存することとしました。

Lambdaを採用しなかった背景

同じ構成はLambdaでも作ることができます。が、以下の理由から採用を見送りました。

料金

今回の構成により、AWS Glue側で発生する料金は以下の通りです。 ※S3ストレージ料金等は別途かかります

課金項目 料金
AWS Glue Jobrun Python Shell ジョブごとに、DPU 時間あたり 0.44USD が 1 秒単位で課金され、最小 1 分
AWS Glue Request 最初の 100 万回のリクエストは毎月無料。月に 100 万回を超えると、100 万回のリクエストあたり 1.00USD
AWS Glue Storage 最初の 100 万個のオブジェクトの保存は無料。月に 100 万個を超えると、10 万個のオブジェクトの保存あたり 1.00USD

なお、変更される場合がありますので最新の料金はこちらをご確認ください。

やってみる

作成したスクリプト

今回Glueにて使用するスクリプトは以下です。

import boto3
import os
import zipfile
from datetime import datetime

# バケット名を設定
source_bucket_name = 's3-bucket-name-A' # ファイルが格納されているバケット名
destination_bucket_name = 's3-bucket-name-B'  # 保存先のバケット名

# boto3のS3クライアントを初期化
s3 = boto3.client('s3')

# バケット内の全てのオブジェクトをリストアップ
objects = s3.list_objects_v2(Bucket=source_bucket_name)
files_to_zip = [obj['Key'] for obj in objects['Contents']]

# 現在の日時を取得してファイル名を作成
now = datetime.now()
zip_file_name = f"archive-{now.strftime('%Y%m%d-%H%M')}.zip"

# ZIPファイルを作成
with zipfile.ZipFile(zip_file_name, 'w') as archive:
    for file_name in files_to_zip:
        # ファイルを一時的にダウンロード
        s3.download_file(source_bucket_name, file_name, file_name)

        # ZIPにファイルを追加
        archive.write(file_name)

        # ローカルのファイルを削除
        os.remove(file_name)

# ZIPファイルを保存先のS3バケットにアップロード
with open(zip_file_name, 'rb') as data:
    s3.upload_fileobj(data, destination_bucket_name, zip_file_name)

# ローカルのZIPファイルを削除
os.remove(zip_file_name)

実行手順

(1) [AWS Glue] - [Data Integration and ETL] - [Jobs]より、[Python Shell script editor]をクリックし、画面右上にある[Create]ボタンをクリックします。

(2) [Script]タブの画面にて、先述のPythonコードを貼り付け、ジョブ名を変更します。
なお、S3バケット名はお手元の環境に合わせて変更してお使いください。

(3) [Job details]タブにて、IAM Roleを設定します。(無い場合は新規作成)

IAMロールには以下の権限が含まれていることを確認します。

  • AmazonS3FullAccess または、使用するバケットの読み書き権限
  • AWSGlueServiceRole
  • AWSGlueConsoleFullAccess

(4) 設定が終わったら、画面右上[Save] および [Run]をクリックします。

(5) [Runs]タブに実行中のジョブが表示されます。
"Succeeded"と表示されていれば、正常にジョブが終了しています。

確認

今回の検証では、ソースバケットに100KBの擬似ログファイルを30個格納しました。

格納先バケットには、正常にジョブの実行時間でZipファイルが格納されていました。
圧縮はほぼ効いてなさそうですが・・・

念の為ダウンロードして解凍しましたが、問題ありません!

おわりに

Lambdaを使わずに、S3バケットにあるファイルをZip化する方法を紹介しました。

今回、検証までは行いませんでしたが、Glueの「Schedule job run」か、Amazon EventBridge Schedulerを利用することで、定期的に今回作成したジョブを実行することができます。

▼ Schedule job run

▼ Amazon EventBridge Scheduler

このエントリが誰かの助けになれば幸いです。 それでは、AWS事業本部 コンサルティング部の荒平(@0Air)がお送りしました!

参考