AWS CDK で aws_s3_deployment モジュールを使うとローカルにある ZIP ファイル・ディレクトリなどを Amazon S3 にアップロードできる❗️使いどころとしては,静的ファイル・設定ファイル・データセットなどのアップロードも AWS CDK のワークフローに含めて IaC 化したいときなどにハマると思う💡さっそく試す \( 'ω')/
1. ZIP ファイルをアップロードする
まずはローカルにある ZIP ファイルを Amazon S3 にアップロードする.ZIP ファイルはサンプルとして MySQL のサンプルデータセット「sakila database」の sakila-db.zip を使う.AWS CDK の実装としては aws_s3_deployment.BucketDeployment
の sources
に ZIP ファイルを指定して destinationBucket
に Amazon S3 バケットを指定するだけ👌 簡単〜
import { Stack, StackProps, aws_s3, aws_s3_deployment, } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class SandboxCdkS3DeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const bucket = new aws_s3.Bucket(this, 'SandboxCdkS3DeploymentBucket', { bucketName: 'sandbox-cdk-s3-deployment-bucket', }); new aws_s3_deployment.BucketDeployment(this, 'SandboxCdkS3Deployment', { sources: [aws_s3_deployment.Source.asset('./datasets/sakila-db.zip')], destinationBucket: bucket, }); } }
cdk deploy
コマンドを実行すると,ZIP ファイルが自動的に展開されてアップロードされていた❗️
2. ZIP ファイルのままアップロードする
デフォルトでは ZIP ファイルは展開されるけど extract: false
オプションを付けると ZIP のままアップロードできる.しかしファイル名が異なる点には注意する👀
import { Stack, StackProps, aws_s3, aws_s3_deployment, } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class SandboxCdkS3DeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const bucket = new aws_s3.Bucket(this, 'SandboxCdkS3DeploymentBucket', { bucketName: 'sandbox-cdk-s3-deployment-bucket', }); new aws_s3_deployment.BucketDeployment(this, 'SandboxCdkS3Deployment', { sources: [aws_s3_deployment.Source.asset('./datasets/sakila-db.zip')], destinationBucket: bucket, extract: false, }); } }
cdk deploy
コマンドを実行すると,e64c076b781d54f6210a9d9f8bfb08e40e8176ecf6f7542a5465d7b9be376574.zip
という名前で ZIP ファイルのままアップロードされていた❗️
3. ディレクトリをアップロードする
ZIP ファイルではなくローカルにあるディレクトリをアップロードすることもできる.使いどころを考えると一番使うのはディレクトリのアップロードかもしれない.さらに include / exclude でフィルタもあって,不要なファイルをアップロードしないように制御できるのは助かる👌
import { Stack, StackProps, aws_s3, aws_s3_deployment, } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class SandboxCdkS3DeploymentStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const bucket = new aws_s3.Bucket(this, 'SandboxCdkS3DeploymentBucket', { bucketName: 'sandbox-cdk-s3-deployment-bucket', }); new aws_s3_deployment.BucketDeployment(this, 'SandboxCdkS3Deployment', { sources: [aws_s3_deployment.Source.asset('./bin', { exclude: ['*.js'] })], destinationBucket: bucket, }); } }
単純に除外するなら sources
に指定する AssetOptions
に exclude
を指定すればアップロード対象をまとめるときに除外できる.また BucketDeployment
自体に include
と exclude
を指定することもできて,Amazon S3 へのアップロード前に考慮される.ちなみに include
と exclude
の構文に関しては AWS CLI の aws s3 sync
コマンドと同じ💡
今回はサンプルとして AWS CDK プロジェクトの bin
ディレクトリの3ファイルを対象にしつつ *.js
を除外する.
$ tree bin bin ├── sandbox-cdk-aws.d.ts ├── sandbox-cdk-aws.js └── sandbox-cdk-aws.ts
cdk deploy
コマンドを実行すると,sandbox-cdk-aws.d.ts
と sandbox-cdk-aws.ts
のみアップロードされていた❗️
仕組み
ドキュメントにも書いてあるけど,aws_s3_deployment モジュールは内部的に AWS Lambda 関数を作って,AWS Lambda 関数の中から AWS CLI の aws s3 sync
コマンドを実行して Amazon S3 にファイルをアップロードしている.AWS Lambda 関数のコード index.py
は以下にある.
よって,AWS CloudFormation のリソース一覧を見るとカスタムリソース Custom::CDKBucketDeployment
の中に AWS Lambda 関数が含まれていて,実際に以下のような AWS Lambda 関数が作られていた.あくまで個人的にだけどカスタムリソースなどによって勝手にリソースが作られることに少し抵抗はあって,今回だと Amazon S3 にファイルをアップロードするために AWS Lambda 関数が作られるのか〜という気持ちになったりはする💨