【awslabs探訪】AWS Cloud Development Kit (AWS CDK)を使ってみた
はじめに
中山(順)です
AWS Cloud Development Kit (AWS CDK)なるツールが存在するとtwitterで発見しました。
なんか、JavaScript, java, typescriptでCloudFormationのテンプレートを生成できるみたいです。 ちょっとよくわかんないのでさわってみたいと思います。
AWS Cloud Development Kit (AWS CDK) User Guide
やってみた
とりあえず、Getting Startedの通りにやってみたいと思います。
検証環境
特に理由はありませんがAmazon Linux 2で動作確認しました。
動作要件
前提となるツールは以下の通りです。
- Node.js (>= 8.11.x)
- AWS CLI
- git
Node.jsのインストール手順は以下の通りです。
1 2 3 | curl --silent --location https: //rpm .nodesource.com /setup_8 .x | bash - sudo yum -y install nodejs |
インストール
まずはAWS-CDKのコマンドラインツールをインストールします。
1 | sudo npm i -g aws-cdk |
正常にインストールできたことの確認を兼ねてバージョンを確認します。
1 | cdk --version |
1 | 0.8.0 (build bb95676) |
プロジェクトの初期化
プロジェクトを作成します。現時点ではJavaScript、Java、TypeScriptが選べるようです。 今回はTypeScriptを使ってみます。
1 2 3 | mkdir hello-cdk cd hello-cdk cdk init app --language=typescript |
生成されたファイルを確認します。
1 | ls -l |
1 2 3 4 5 6 7 8 | total 104 drwxrwxr-x 2 ec2-user ec2-user 26 Aug 7 12:17 bin -rw-rw-r-- 1 ec2-user ec2-user 39 Aug 7 12:17 cdk.json drwxrwxr-x 191 ec2-user ec2-user 8192 Aug 7 12:18 node_modules -rw-rw-r-- 1 ec2-user ec2-user 530 Aug 7 12:17 package.json -rw-rw-r-- 1 ec2-user ec2-user 74509 Aug 7 12:18 package-lock.json -rw-r--r-- 1 ec2-user ec2-user 320 Aug 7 12:17 README.md -rw-r--r-- 1 ec2-user ec2-user 631 Aug 7 12:17 tsconfig.json |
tsconfig.jsonおよびpackage.jsonの内容を確認します。
1 | cat tsconfig.json |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | { "compilerOptions" : { "target" : "ES2018" , "module" : "commonjs" , "lib" : [ "es2016" , "es2017.object" , "es2017.string" ], "declaration" : true , "strict" : true , "noImplicitAny" : true , "strictNullChecks" : true , "noImplicitThis" : true , "alwaysStrict" : true , "noUnusedLocals" : true , "noUnusedParameters" : true , "noImplicitReturns" : true , "noFallthroughCasesInSwitch" : false , "inlineSourceMap" : true , "inlineSources" : true , "experimentalDecorators" : true , "strictPropertyInitialization" : false } } |
1 | cat package.json |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | { "name" : "hello-cdk" , "version" : "0.1.0" , "main" : "bin/index.js" , "types" : "bin/index.d.ts" , "bin" : { "hello-cdk" : "bin/hello-cdk.js" }, "scripts" : { "build" : "tsc" , "watch" : "tsc -w" , "cdk" : "cdk" }, "devDependencies" : { "@types/node" : "^8.9.4" , "typescript" : "^2.8.3" , "aws-cdk" : "^0.8.0" }, "dependencies" : { "@aws-cdk/aws-sns" : "^0.8.0" , "@aws-cdk/aws-sqs" : "^0.8.0" , "@aws-cdk/cdk" : "^0.8.0" } } |
今回はこれらのファイルに修正を加える必要はありません。
コアライブラリのインストール
AWS CDKを利用するうえで必須となるコアライブラリをインストールします。
1 | sudo npm install @aws-cdk /cdk @types /node |
アプリケーションの作成
まずは、リソースを何も作らない空っぽのアプリケーションを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | FILE_NAME= "index.ts" cat << EOF > ${FILE_NAME} import cdk = require( '@aws-cdk/cdk' ); class MyApp extends cdk.App { constructor(argv: string[]) { super(argv); } } process.stdout.write(new MyApp(process.argv).run()); EOF cat ${FILE_NAME} |
1 2 3 4 5 6 7 8 9 | import cdk = require ( '@aws-cdk/cdk' ) ; class MyApp extends cdk . App { constructor ( argv : string [ ] ) { super ( argv ) ; } } process . stdout . write ( new MyApp ( process . argv ) . run ( ) ) ; |
ファイルができたらコンパイルします。
1 | npm run build |
認証情報の設定
AWS CLIの認証情報を設定します。 アクセスキーを環境変数に設定したり、"~/.aws"配下のファイルに認証情報を設定しましょう。
最後に設定できていることを確認してください。 結果はインスタンスプロファイルを利用している場合の例です。
1 | aws configure list |
1 2 3 4 5 6 | Name Value Type Location ---- ----- ---- -------- profile <not set> None None access_key ****************JQ46 iam-role secret_key ****************9jQi iam-role region <not set> None None |
アプリケーションの指定
コンパイルした結果生成される.jsファイルをプロジェクトのディレクトリ直下にある"cdk.json"へ設定します。
1 2 3 | { "app" : "node index.js" } |
スタックの一覧表示
現時点で存在するスタックの一覧を表示します。 もちろん一つもありません。
1 | cdk ls -l |
1 |
スタックの定義
先ほど作成したコード内にスタックを作成するクラスを定義してます。 また、エントリーポイント(?)となるクラスにおいて定義したクラスのインスタンスを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import cdk = require ( '@aws-cdk/cdk' ) ; class MyStack extends cdk . Stack { constructor ( parent : cdk . App , id : string , props? : cdk . StackProps ) { super ( parent , id , props ) ; } } class MyApp extends cdk . App { constructor ( argv : string [ ] ) { super ( argv ) ; new MyStack ( this , 'hello-cdk' ) ; } } process . stdout . write ( new MyApp ( process . argv ) . run ( ) ) ; |
追記したらコンパイルします。
1 | npm run build |
スタックの一覧を確認します。 AWS CDK的にはこの時点でスタックが作成されるようですが、AWSアカウントにCFnスタックが実際に作成されるわけではありません。
1 | cdk ls -l |
1 2 3 4 5 6 | - name: hello-cdk environment: name: xxxxxxxxxxxx/ap-northeast-1 account: 'xxxxxxxxxxxx' region: ap-northeast-1 |
S3バケットを作ってみる
次は実際に何かリソースを作ってみましょう。 今回はS3バケットを作ります。
まずは必要なライブラリをインストールします。
1 | sudo npm install @aws-cdk /aws-s3 |
次に、ライブラリをインポートしてリソースを作成する処理を追加します。 バケットに対してバージョニングの有効化を行っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import cdk = require ( '@aws-cdk/cdk' ) ; import s3 = require ( '@aws-cdk/aws-s3' ) ; class MyStack extends cdk . Stack { constructor ( parent : cdk . App , id : string , props? : cdk . StackProps ) { super ( parent , id , props ) ; new s3 . Bucket ( this , 'myfirstbucketxxxxxxxxxxxx' , { versioned : true } ) ; } } class MyApp extends cdk . App { constructor ( argv : string [ ] ) { super ( argv ) ; new MyStack ( this , 'hello-cdk' ) ; } } process . stdout . write ( new MyApp ( process . argv ) . run ( ) ) ; |
追記したらコンパイルします。
1 | npm run build |
CloudFormationテンプレートの確認
アプリケーションをデプロイする際に利用されることになるテンプレートを確認します。
1 | cdk synth hello-cdk |
1 2 3 4 5 6 7 8 9 10 | Resources: myfirstbucketxxxxxxxxxxxxF02C9402: Type: 'AWS::S3::Bucket' Properties: VersioningConfiguration: Status: Enabled CDKMetadata: Type: 'AWS::CDK::Metadata' Properties: Modules: '@aws-cdk/aws-kms=0.8.0,@aws-cdk/aws-s3=0.8.0,@aws-cdk/cdk=0.8.0,@aws-cdk/cx-api=0.8.0,hello-cdk=0.1.0,js-base64=2.4.5' |
デプロイ(1回目)
デプロイします。
1 | cdk deploy |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ? Starting deployment of stack hello-cdk... [0/2] Tue Aug 07 2018 12:41:49 GMT+0000 (UTC) CREATE_IN_PROGRESS [AWS::CloudFormation::WaitConditionHandle] WaitCondition [0/2] Tue Aug 07 2018 12:41:49 GMT+0000 (UTC) CREATE_IN_PROGRESS [AWS::CloudFormation::WaitConditionHandle] WaitCondition Resource creation Initiated [1/2] Tue Aug 07 2018 12:41:49 GMT+0000 (UTC) CREATE_COMPLETE [AWS::CloudFormation::WaitConditionHandle] WaitCondition [2/2] Tue Aug 07 2018 12:41:51 GMT+0000 (UTC) CREATE_COMPLETE [AWS::CloudFormation::Stack] hello-cdk [0/4] Tue Aug 07 2018 12:42:06 GMT+0000 (UTC) CREATE_IN_PROGRESS [AWS::CDK::Metadata] CDKMetadata [0/4] Tue Aug 07 2018 12:42:06 GMT+0000 (UTC) CREATE_IN_PROGRESS [AWS::S3::Bucket] myfirstbucketxxxxxxxxxxxxF02C9402 [0/4] Tue Aug 07 2018 12:42:08 GMT+0000 (UTC) CREATE_IN_PROGRESS [AWS::S3::Bucket] myfirstbucketxxxxxxxxxxxxF02C9402 Resource creation Initiated [0/4] Tue Aug 07 2018 12:42:08 GMT+0000 (UTC) CREATE_IN_PROGRESS [AWS::CDK::Metadata] CDKMetadata Resource creation Initiated [1/4] Tue Aug 07 2018 12:42:09 GMT+0000 (UTC) CREATE_COMPLETE [AWS::CDK::Metadata] CDKMetadata [2/4] Tue Aug 07 2018 12:42:30 GMT+0000 (UTC) CREATE_COMPLETE [AWS::S3::Bucket] myfirstbucketxxxxxxxxxxxxF02C9402 [2/4] Tue Aug 07 2018 12:42:32 GMT+0000 (UTC) UPDATE_COMPLETE_CLEANUP_IN_PROGRESS [AWS::CloudFormation::Stack] hello-cdk [2/4] Tue Aug 07 2018 12:42:34 GMT+0000 (UTC) DELETE_IN_PROGRESS [AWS::CloudFormation::WaitConditionHandle] WaitCondition [3/4] Tue Aug 07 2018 12:42:34 GMT+0000 (UTC) DELETE_COMPLETE [AWS::CloudFormation::WaitConditionHandle] WaitCondition [4/4] Tue Aug 07 2018 12:42:35 GMT+0000 (UTC) UPDATE_COMPLETE [AWS::CloudFormation::Stack] hello-cdk ? Deployment of stack hello-cdk completed successfully, it has ARN arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/hello-cdk/3ec20540-9a3f-11e8-aede-503a369c8836 |
作成されたリソースを確認
作成したリソースを確認します。
まずはCFnスタックを確認します。
1 2 | aws cloudformation describe-stacks \ --stack-name hello-cdk |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | { "Stacks" : [ { "StackId" : "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/hello-cdk/3ec20540-9a3f-11e8-aede-503a369c8836" , "LastUpdatedTime" : "2018-08-07T12:42:01.908Z" , "Tags" : [], "EnableTerminationProtection" : false , "CreationTime" : "2018-08-07T12:41:46.142Z" , "Capabilities" : [ "CAPABILITY_IAM" , "CAPABILITY_NAMED_IAM" ], "StackName" : "hello-cdk" , "NotificationARNs" : [], "StackStatus" : "UPDATE_COMPLETE" , "DisableRollback" : false , "ChangeSetId" : "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:changeSet/CDK-e81ddbf2-3173-4340-a15b-40a584000216/80337bb2-7eac-450b-9397-b16221a78716" , "RollbackConfiguration" : {} } ] } |
S3バケットを確認します。
まず、リソースが存在することの確認を兼ねて、CFnスタックからリソースIDを確認します。
1 2 3 | aws cloudformation describe-stack-resources \ --stack-name hello-cdk \ --query StackResources[?ResourceType==\`AWS::S3::Bucket\`] |
1 2 3 4 5 6 7 8 9 10 11 | [ { "StackId" : "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/hello-cdk/3ec20540-9a3f-11e8-aede-503a369c8836" , "ResourceStatus" : "CREATE_COMPLETE" , "ResourceType" : "AWS::S3::Bucket" , "Timestamp" : "2018-08-07T12:42:30.556Z" , "StackName" : "hello-cdk" , "PhysicalResourceId" : "hello-cdk-myfirstbucketxxxxxxxxxxxxf02c9402-y5xophnhjrw9" , "LogicalResourceId" : "myfirstbucketxxxxxxxxxxxxF02C9402" } ] |
また、S3バケットのバージョニングが有効であることを確認します。
1 2 | aws s3api get-bucket-versioning \ --bucket "hello-cdk-myfirstbucketxxxxxxxxxxxxf02c9402-y5xophnhjrw9" |
1 2 3 | { "Status" : "Enabled" } |
このように、アプリケーション通りにリソースが作成されることが確認できました。
アプリケーションの修正
修正する流れも確認しましょう。 サーバーサイド暗号化を有効化してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import cdk = require ( '@aws-cdk/cdk' ) ; import s3 = require ( '@aws-cdk/aws-s3' ) ; class MyStack extends cdk . Stack { constructor ( parent : cdk . App , id : string , props? : cdk . StackProps ) { super ( parent , id , props ) ; new s3 . Bucket ( this , 'my-first-bucket-xxxxxxxxxxxx' , { versioned : true , encryption : s3 . BucketEncryption . KmsManaged } ) ; } } class MyApp extends cdk . App { constructor ( argv : string [ ] ) { super ( argv ) ; new MyStack ( this , 'hello-cdk' ) ; } } process . stdout . write ( new MyApp ( process . argv ) . run ( ) ) ; |
追記したらコンパイルします。
1 | npm run build |
差分を確認します。 以下のコマンドで、修正に伴いリソースがどのように変更されるかを確認できます。 CloudFormationの変更セットのようなものでしょうか。
1 | cdk diff |
1 2 3 | [~] ? Updating myfirstbucketxxxxxxxxxxxxF02C9402 (type: AWS::S3::Bucket) mq [+] .BucketEncryption: mq New value: {"ServerSideEncryptionConfiguration":[{"ServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms"}}]} |
最後にデプロイします。
1 | cdk deploy |
1 2 3 4 5 6 | ? Starting deployment of stack hello-cdk... [0/2] Tue Aug 07 2018 14:27:13 GMT+0000 (UTC) UPDATE_IN_PROGRESS [AWS::S3::Bucket] myfirstbucketxxxxxxxxxxxxF02C9402 [1/2] Tue Aug 07 2018 14:27:35 GMT+0000 (UTC) UPDATE_COMPLETE [AWS::S3::Bucket] myfirstbucketxxxxxxxxxxxxF02C9402 [1/2] Tue Aug 07 2018 14:27:37 GMT+0000 (UTC) UPDATE_COMPLETE_CLEANUP_IN_PROGRESS [AWS::CloudFormation::Stack] hello-cdk [2/2] Tue Aug 07 2018 14:27:38 GMT+0000 (UTC) UPDATE_COMPLETE [AWS::CloudFormation::Stack] hello-cdk ? Deployment of stack hello-cdk completed successfully, it has ARN arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/hello-cdk/3ec20540-9a3f-11e8-aede-503a369c8836 |
まとめ
CloudFormationのテンプレートでは宣言的な記述しかできませんが、このようにコードで記述できれば反復処理や分岐処理も書けますので、柔軟な運用ができそうです。
プレビュー版ではありますが、サポートしているリソースは多そうですので皆さんもいろいろ試してみてはいかがでしょうか。
現場からは以上です。