【awslabs探訪】AWS Cloud Development Kit (AWS CDK)を使ってみた
はじめに
中山(順)です
AWS Cloud Development Kit (AWS CDK)なるツールが存在するとtwitterで発見しました。
フォフォー / "awslabs/aws-cdk: The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code" https://t.co/mq7qEk0FOW pic.twitter.com/eBMuVBOnmS
— ポジティブな Tori (@toricls) 2018年8月7日
なんか、JavaScript, java, typescriptでCloudFormationのテンプレートを生成できるみたいです。 ちょっとよくわかんないのでさわってみたいと思います。
AWS Cloud Development Kit (AWS CDK) User Guide
やってみた
とりあえず、Getting Startedの通りにやってみたいと思います。
【2019年6月21日 追記】上記のドキュメントはリンク切れになっていました。チュートリアルをやってみたい方は以下のドキュメントをご覧ください。
Getting Started With the AWS CDK
検証環境
特に理由はありませんがAmazon Linux 2で動作確認しました。
動作要件
前提となるツールは以下の通りです。
- Node.js (>= 8.11.x)
- AWS CLI
- git
Node.jsのインストール手順は以下の通りです。
curl --silent --location https://rpm.nodesource.com/setup_8.x | bash - sudo yum -y install nodejs
インストール
まずはAWS-CDKのコマンドラインツールをインストールします。
sudo npm i -g aws-cdk
正常にインストールできたことの確認を兼ねてバージョンを確認します。
cdk --version
0.8.0 (build bb95676)
プロジェクトの初期化
プロジェクトを作成します。現時点ではJavaScript、Java、TypeScriptが選べるようです。 今回はTypeScriptを使ってみます。
mkdir hello-cdk cd hello-cdk cdk init app --language=typescript
生成されたファイルを確認します。
ls -l
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の内容を確認します。
cat tsconfig.json
{ "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 } }
cat package.json
{ "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を利用するうえで必須となるコアライブラリをインストールします。
sudo npm install @aws-cdk/cdk @types/node
アプリケーションの作成
まずは、リソースを何も作らない空っぽのアプリケーションを作成します。
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}
import cdk = require('@aws-cdk/cdk'); class MyApp extends cdk.App { constructor(argv: string[]) { super(argv); } } process.stdout.write(new MyApp(process.argv).run());
ファイルができたらコンパイルします。
npm run build
認証情報の設定
AWS CLIの認証情報を設定します。 アクセスキーを環境変数に設定したり、"~/.aws"配下のファイルに認証情報を設定しましょう。
最後に設定できていることを確認してください。 結果はインスタンスプロファイルを利用している場合の例です。
aws configure list
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"へ設定します。
{ "app": "node index.js" }
スタックの一覧表示
現時点で存在するスタックの一覧を表示します。 もちろん一つもありません。
cdk ls -l
[]
スタックの定義
先ほど作成したコード内にスタックを作成するクラスを定義してます。 また、エントリーポイント(?)となるクラスにおいて定義したクラスのインスタンスを作成します。
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());
追記したらコンパイルします。
npm run build
スタックの一覧を確認します。 AWS CDK的にはこの時点でスタックが作成されるようですが、AWSアカウントにCFnスタックが実際に作成されるわけではありません。
cdk ls -l
- name: hello-cdk environment: name: xxxxxxxxxxxx/ap-northeast-1 account: 'xxxxxxxxxxxx' region: ap-northeast-1
S3バケットを作ってみる
次は実際に何かリソースを作ってみましょう。 今回はS3バケットを作ります。
まずは必要なライブラリをインストールします。
sudo npm install @aws-cdk/aws-s3
次に、ライブラリをインポートしてリソースを作成する処理を追加します。 バケットに対してバージョニングの有効化を行っています。
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());
追記したらコンパイルします。
npm run build
CloudFormationテンプレートの確認
アプリケーションをデプロイする際に利用されることになるテンプレートを確認します。
cdk synth hello-cdk
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回目)
デプロイします。
cdk deploy
? 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スタックを確認します。
aws cloudformation describe-stacks \ --stack-name hello-cdk
{ "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を確認します。
aws cloudformation describe-stack-resources \ --stack-name hello-cdk \ --query StackResources[?ResourceType==\`AWS::S3::Bucket\`]
[ { "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バケットのバージョニングが有効であることを確認します。
aws s3api get-bucket-versioning \ --bucket "hello-cdk-myfirstbucketxxxxxxxxxxxxf02c9402-y5xophnhjrw9"
{ "Status": "Enabled" }
このように、アプリケーション通りにリソースが作成されることが確認できました。
アプリケーションの修正
修正する流れも確認しましょう。 サーバーサイド暗号化を有効化してみます。
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, 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());
追記したらコンパイルします。
npm run build
差分を確認します。 以下のコマンドで、修正に伴いリソースがどのように変更されるかを確認できます。 CloudFormationの変更セットのようなものでしょうか。
cdk diff
[~] ? Updating myfirstbucketxxxxxxxxxxxxF02C9402 (type: AWS::S3::Bucket) mq [+] .BucketEncryption: mq New value: {"ServerSideEncryptionConfiguration":[{"ServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms"}}]}
最後にデプロイします。
cdk deploy
? 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
削除
最後はdestroyコマンドで削除します。
cdk destroy
Are you sure you want to delete: hello-cdk (y/n)? y ? Starting destruction of stack hello-cdk... ? Stack hello-cdk successfully destroyed.
まとめ
CloudFormationのテンプレートでは宣言的な記述しかできませんが、このようにコードで記述できれば反復処理や分岐処理も書けますので、柔軟な運用ができそうです。 現時点でサポートしているコードは私自身どれも書き慣れていないのですが、いい機会なのでTypeScriptでも勉強してみるのもいいかなーと思いました。
プレビュー版ではありますが、サポートしているリソースは多そうですので気になる方はいろいろ試してみてはいかがでしょうか。
現場からは以上です。