Lambda上でAWSCLIを動かしてS3 Syncする

AWS運用自動化サービス「Cloud Automator」
こんにちは、技術一課の加藤です。
 
AWS CLIのS3 Sync、便利ですよね。
コピー元とコピー先の付き合わせやバージョンの比較など、Sync処理において面倒だな、と思うことを全部端折ってくれるS3 Syncは、まさにバケット間データ移動の最適解といえるでしょう。
 
しかしこれを定期実行したい、となるとやや面倒です。実はAWS SDKにはS3 Syncと同様の機能がないため、Lambdaでいい感じに実装しようと思うと考慮すべきことが色々出てきてしまいます。
 
S3バケットのSyncがしたい! でもAWS SDKで実装するのも面倒くさい!
 
そうしてやってみたのが「Lambda上でAWS CLIを動かす」というアクロバティック実装です。

実装方法

極力AWS CLIをLambda内で使うために必要な手順に絞って解説を行うため、

  • S3バケット同士のSync
  • 2つのS3バケットおよびLambdaは同一アカウント上に存在
という前提でご説明をします。
クロスアカウントで実装したい場合(そのパターンが圧倒的に多いと思いますが)この辺の記事を参照しつつLambdaからS3へのアクセス許可を設定してみてください。
 
また以下のリソースはご自身で用意しておいてください。
  • 送信元/先のS3バケット(計2つ)
  • 作ったバケットに対するアクセス権限を持つLambda
なおS3 Syncの仕様上、Lambdaの実行権限には最低でも
  • s3:ListBucket
  • s3:GetObject
  • s3:PutObject
が必要となります。もし権限を絞るのが面倒であれば、S3へのフルアクセスを与えておいてください。
ちなみに対象リソースは「バケット自体」と「バケット以下のオブジェクト全て」を指定する必要があります。
バケット名が「src-bucket」であれば、「arn:aws:s3:::src-bucket」および「arn:aws:s3:::src-bucket/*」へのアクセス権限を与えてください。
 

関数の作成

まずディレクトリを作成しAWS CLIをローカルインストールします
以降のコマンド・コードはPython 3.7.2環境にて動作確認済みになります。他のバージョンで実行する際にはご注意ください。)

次に、AWS CLIをPythonスクリプトから呼ぶためのラッパースクリプトを作成します。
 
AWS CLIは文字通りCLIから呼び出すことを想定して作られているため、ローカルインストールしたAWS CLIを普通にプログラムにimportして使おうと思うと引数の与え方などがやや面倒です。このため、コマンド的に利用できるようにラッパースクリプトを挟んでやる必要があります。

awsファイルには以下を書き込んでください。
awsファイルが正しく動作するか確認してください。helpが表示されればOKです。
最後にlambda_functionファイルを作成します

以下のコードを書き込んでください。subprocessを用いて実際にawsコマンドを呼び出すスクリプトになります。
 
以上が完了したら、コードをzip化しLambdaにデプロイします。
今回は特に渡すパラメータもないので、送信元バケットにファイルをおき、Lambdaのテスト実行を行うと動作が確認できます。
 
処理に意外と時間がかかるので、1ファイルのSyncであってもタイムアウトを10秒程度まで伸ばしておくことをお勧めします。
 

おわりに

LambdaでAWS CLIを動かしたい場合、カスタムランタイムを使うという方法もあります。こちらも後日試しに実装してみる予定なので、また記事にしますね。
とはいえやっぱりアクロバティック感は否めないので、ご利用は自己責任でお願いしますね。
 
AWS運用自動化サービス「Cloud Automator」