指定した時間にS3 syncでファイルを同期する処理をCloudWatch EventsとCodeBuildでやってみた

指定した時間にS3 syncを行うためにCloudWatch EventsとCodeBuildを組み合わせてみました。お手軽に利用できて以外にいいのでは?と思います。
2020.03.18

こんにちは、臼田です。

みなさん、自動化してますか?(挨拶

今回はすごく具体的な要件ですが指定した時間に自動的にS3 syncする方法についてやってみたので紹介します。

S3 syncを指定した時間に行いたい

まず前提の話ですが、S3 syncはawscliで実行できるコマンドで、指定した送信元S3バケットから宛先S3バケットへファイルを同期する処理が可能です。

よく勘違いされやすいのですが、S3 syncはhigh-level S3 commandsと言われるもので、直接syncするAPIがあるわけではなく、get objectやput objectのAPIを駆使してawscliを実行しているコンピューティングリソース上でコピー作業を実施するラッパーコマンドです。

そのため、例えばLambdaで指定した時間にS3 syncと実行すれば終わりではなく、syncしている間ずっとコンピューティングリソースが動作している必要があります。つまりLambdaだと最大15分までしか動作できないので、対象の量によっては現実的はありません。

というわけで、CloudWatch EventsとCodeBuildで実現する方法を考えました。

ちなみに指定した時間にsyncを行いたい要件としては、毎日決まった時間に同期したい、特定の時間にWebの静的コンテンツをデプロイしたい、等があるかと思います。

S3 syncの方法

ちなみに、単純なS3 syncを行うだけならCodeBuildの他にもLambdaやFargateやAWS Batchもコンピューティングリソースとして利用可能な他、直接的にS3 syncではないですがレプリケーション機能やS3イベントをトリガーにしてLambda等で複製する、S3バッチオペレーションを使うなど色んな方法が考えられます。

CodeBuildを採用するのは大きく下記の理由からです。

  • 動作時間の制約がない
    • Lambdaは15分まで
  • コンテナの用意が不要
    • Fargate / AWS Batchは事前にコンテナを用意
  • CloudWatch Eventsをトリガーにできる(指定した時間に動作させられる)
    • レプリケーションなどはすぐに実行される

もしS3のデータを複製することが目的なら他の方法も検討してみてください。

やってみた

CodeBuildでビルドプロジェクト作成

それでは作っていきます。まずCodeBuildのコンソールへアクセスしてプロジェクトの作成を押します。

プロジェクト名は適当に、ソースプロバイダは今回無いので「ソースがありません」を選択します。

環境ではマネージド型イメージを利用します。個別にDockerイメージを用意しなくていいので便利ですね。OSはAmazon Linux 2にしてランタイムやイメージの詳細は適当に選びます。今回はawscliが動けばいいだけなので、何でもいいです。

サービスロールは新しく作成します。ロール名は自動的に入力されていたのでそれを利用します。この場で権限の設定は行いません。後ほど個別に行います。

処理する内容は1行のawscliなので、ビルドコマンドに直接書いてしまいます。今回はaws s3 sync s3://copy-test-a s3://copy-test-bとしています。アーティファクトも必要ないのでなしです。

ログ出力については今回外しましたが、実運用する際には問題があった時に辿れないと困るのでCloudWatchかS3に出しておきましょう。ビルドプロジェクトを作成します。

作成したら、後ほど使うビルドプロジェクトのARNを控えます。作成したビルドプロジェクトの詳細画面から「ビルドの詳細」タブへ行きプロジェクトARNを控えます。

CodeBuildの準備は完了です。

IAM Roleの権限追加

先程作成されたCodeBuild用のサービスロールにS3 syncを行う権限を追加します。まずはIAMのコンソールへ行き、作成したロールの詳細画面に移動します。移動したらアクセス権限タブから「ポリシーをアタッチします」で任意のポリシーをアタッチします。

今回は簡単に行うためマネージドポリシーのS3FullAccessを選択しましたが、対象のS3バケットやAPIを制限したほうがいいです。

この設定が完了すればCodeBuildのビルドプロジェクトを開始してS3 syncを実行できます。CloudWatch Eventsの設定前に一度動作確認してみてもいいかもしれません。

CloudWatch Eventsの設定

最後にイベントを設定していきます。

CloudWatch Eventsのルールを作成します。イベントソースにはスケジュールでCron式を入力します。ここで使うCron式はLinuxで設定するものとちょっと違うので注意。あとGMTなので注意。入力すると次回実行時間が出るのでこれを確認しましょう。

ターゲット側ではCodeBuildプロジェクトを選択して、先程のARNを入力します。CloudWatch Eventsが利用するIAM Roleについては画面に表示されているまま作成すれば、実行権限をうまくつけてくれます。

ルールの名前を適当にいれて作成します。

これで完了です。実行されたらビルド履歴から確認できます。

S3の状態を確認してみてください。

まとめ

コンピューティングリソースを管理せず、コンテナイメージを作らないで指定した時間にS3 syncを実行してみました。

ちょっとひと手間かけましたが特定のコンピューティングリソースに縛られない処理なので便利に利用できると思います。

料金的にもデフォルトのイメージでは東京リージョンで0.005USDで、無料枠もあるので非常に良心的だと思います。

やってみてはいかがでしょうか?