🐕
AWS CDK と CloudFormation の記述量の違いとメンテナンスコストについて勉強してみた。※ymlに修正しました〜
AWS CDK と CloudFormation の記述量の違いとメンテナンスコスト
はじめに
JAWS-UG CDK支部のイベントのラジオで聞いてCDKについて影響を受けて、CDKの勉強をはじめました。
私はAWSのIaCツールについてAWS CDK と CloudFormation について勉強した中での備忘録です。
※すみませんjsonです。時間あったらymlにします。→ymlに修正しました〜
記述量の違い
今回の実装について※CDKインストール時のsampleを使用
- SQSキューを作成する。
- SNSトピックを作成する。
- そのSNSトピックに、前述のSQSキューをサブスクリプションとして追加する。
AWS CDK (TypeScript)
例: SNS トピックと SQS キューを作成し、その SNS トピックからのメッセージを SQS キューに送る機能
import { Duration, Stack, StackProps } from 'aws-cdk-lib';
import * as sns from 'aws-cdk-lib/aws-sns';
import * as subs from 'aws-cdk-lib/aws-sns-subscriptions';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { Construct } from 'constructs';
export class SampleStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const queue = new sqs.Queue(this, 'SampleQueue', {
visibilityTimeout: Duration.seconds(300),
});
const topic = new sns.Topic(this, 'SampleTopic');
topic.addSubscription(new subs.SqsSubscription(queue));
}
}
CloudFormation (YAML)
※CDKからCloudFormation (YAML)のテンプレートを作成
例: SNS トピックと SQS キューを作成し、その SNS トピックからのメッセージを SQS キューに送る機能
Resources:
SampleQueue49AAAEFF:
Type: "AWS::SQS::Queue"
Properties:
VisibilityTimeout: "300"
UpdateReplacePolicy: "Delete"
DeletionPolicy: "Delete"
Metadata:
aws:cdk:path: "SampleStack/SampleQueue/Resource"
SampleQueuePolicy6B63351F:
Type: "AWS::SQS::QueuePolicy"
Properties:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action: "sqs:SendMessage"
Condition:
ArnEquals:
aws:SourceArn:
Ref: "SampleTopic5FE9B5DC"
Effect: "Allow"
Principal:
Service: "sns.amazonaws.com"
Resource:
Fn::GetAtt:
- "SampleQueue49AAAEFF"
- "Arn"
Queues:
- Ref: "SampleQueue49AAAEFF"
Metadata:
aws:cdk:path: "SampleStack/SampleQueue/Policy/Resource"
SampleQueueSampleStackSampleTopic95768FB97B34B6F6:
Type: "AWS::SNS::Subscription"
Properties:
Endpoint:
Fn::GetAtt:
- "SampleQueue49AAAEFF"
- "Arn"
Protocol: "sqs"
TopicArn:
Ref: "SampleTopic5FE9B5DC"
DependsOn:
- "SampleQueuePolicy6B63351F"
Metadata:
aws:cdk:path: "SampleStack/SampleQueue/SampleStackSampleTopic95768FB9/Resource"
SampleTopic5FE9B5DC:
Type: "AWS::SNS::Topic"
Metadata:
aws:cdk:path: "SampleStack/SampleTopic/Resource"
CDKMetadata:
Type: "AWS::CDK::Metadata"
Properties:
Analytics: "v2:deflate64:H4sIAAAAAAAA/1WNywrCMBBFv6X7ZKzdue4PaOte2iTCtDWpmUSRkH83DxBkYObew4Hp4HSEtpnexIVc+YYzhNFNYmUJ3QI9CcLFK69Yf9c1lH02G4rPD9YaGenkj34mYXF3aHQ2/vrV7CgyLSHGHAdFxltRfvRGS8xmZNpIBQsdXl0LaZqFELn12uFDwVDvFwwGXTbAAAAA"
Metadata:
aws:cdk:path: "SampleStack/CDKMetadata/Default"
Condition: "CDKMetadataAvailable"
Conditions:
CDKMetadataAvailable:
Fn::Or:
- Fn::Or:
- Fn::Equals: [ Ref: "AWS::Region", "af-south-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "ap-east-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "ap-northeast-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "ap-northeast-2" ]
- Fn::Equals: [ Ref: "AWS::Region", "ap-south-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "ap-southeast-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "ap-southeast-2" ]
- Fn::Equals: [ Ref: "AWS::Region", "ca-central-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "cn-north-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "cn-northwest-1" ]
- Fn::Or:
- Fn::Equals: [ Ref: "AWS::Region", "eu-central-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "eu-north-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "eu-south-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "eu-west-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "eu-west-2" ]
- Fn::Equals: [ Ref: "AWS::Region", "eu-west-3" ]
- Fn::Equals: [ Ref: "AWS::Region", "me-south-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "sa-east-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "us-east-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "us-east-2" ]
- Fn::Or:
- Fn::Equals: [ Ref: "AWS::Region", "us-west-1" ]
- Fn::Equals: [ Ref: "AWS::Region", "us-west-2" ]
Parameters:
BootstrapVersion:
Type: "AWS::SSM::Parameter::Value<String>"
Default: "/cdk-bootstrap/hnb659fds/version"
Description: "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
Rules:
CheckBootstrapVersion:
Assertions:
- Assert:
Fn::Not:
- Fn::Contains:
- [ "1", "2", "3", "4", "5" ]
- Ref: "BootstrapVersion"
AssertDescription: "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
もしjsonだったら
{
"Resources": {
"SampleQueue49AAAEFF": {
"Type": "AWS::SQS::Queue",
"Properties": {
"VisibilityTimeout": 300
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete",
"Metadata": {
"aws:cdk:path": "SampleStack/SampleQueue/Resource"
}
},
"SampleQueuePolicy6B63351F": {
"Type": "AWS::SQS::QueuePolicy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "sqs:SendMessage",
"Condition": {
"ArnEquals": {
"aws:SourceArn": {
"Ref": "SampleTopic5FE9B5DC"
}
}
},
"Effect": "Allow",
"Principal": {
"Service": "sns.amazonaws.com"
},
"Resource": {
"Fn::GetAtt": [
"SampleQueue49AAAEFF",
"Arn"
]
}
}
],
"Version": "2012-10-17"
},
"Queues": [
{
"Ref": "SampleQueue49AAAEFF"
}
]
},
"Metadata": {
"aws:cdk:path": "SampleStack/SampleQueue/Policy/Resource"
}
},
"SampleQueueSampleStackSampleTopic95768FB97B34B6F6": {
"Type": "AWS::SNS::Subscription",
"Properties": {
"Endpoint": {
"Fn::GetAtt": [
"SampleQueue49AAAEFF",
"Arn"
]
},
"Protocol": "sqs",
"TopicArn": {
"Ref": "SampleTopic5FE9B5DC"
}
},
"DependsOn": [
"SampleQueuePolicy6B63351F"
],
"Metadata": {
"aws:cdk:path": "SampleStack/SampleQueue/SampleStackSampleTopic95768FB9/Resource"
}
},
"SampleTopic5FE9B5DC": {
"Type": "AWS::SNS::Topic",
"Metadata": {
"aws:cdk:path": "SampleStack/SampleTopic/Resource"
}
},
"CDKMetadata": {
"Type": "AWS::CDK::Metadata",
"Properties": {
"Analytics": "v2:deflate64:H4sIAAAAAAAA/1WNywrCMBBFv6X7ZKzdue4PaOte2iTCtDWpmUSRkH83DxBkYObew4Hp4HSEtpnexIVc+YYzhNFNYmUJ3QI9CcLFK69Yf9c1lH02G4rPD9YaGenkj34mYXF3aHQ2/vrV7CgyLSHGHAdFxltRfvRGS8xmZNpIBQsdXl0LaZqFELn12uFDwVDvFwwGXTbAAAAA"
},
"Metadata": {
"aws:cdk:path": "SampleStack/CDKMetadata/Default"
},
"Condition": "CDKMetadataAvailable"
}
},
"Conditions": {
"CDKMetadataAvailable": {
"Fn::Or": [
{
"Fn::Or": [
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"af-south-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"ap-east-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"ap-northeast-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"ap-northeast-2"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"ap-south-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"ap-southeast-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"ap-southeast-2"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"ca-central-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"cn-north-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"cn-northwest-1"
]
}
]
},
{
"Fn::Or": [
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"eu-central-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"eu-north-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"eu-south-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"eu-west-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"eu-west-2"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"eu-west-3"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"me-south-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"sa-east-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"us-east-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"us-east-2"
]
}
]
},
{
"Fn::Or": [
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"us-west-1"
]
},
{
"Fn::Equals": [
{
"Ref": "AWS::Region"
},
"us-west-2"
]
}
]
}
]
}
},
"Parameters": {
"BootstrapVersion": {
"Type": "AWS::SSM::Parameter::Value<String>",
"Default": "/cdk-bootstrap/hnb659fds/version",
"Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
}
},
"Rules": {
"CheckBootstrapVersion": {
"Assertions": [
{
"Assert": {
"Fn::Not": [
{
"Fn::Contains": [
[
"1",
"2",
"3",
"4",
"5"
],
{
"Ref": "BootstrapVersion"
}
]
}
]
},
"AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
}
]
}
}
}
-
CDK: リソースを増やしていくと、CDKの抽象化と再利用の恩恵により、記述が効率的になります。
-
CloudFormation: 初心者にとっては直感的でシンプルですが、大規模なアーキテクチャや高度な設定を扱う場合、テンプレートが非常に長くなる可能性があります。
メンテナンスに関するメリット・デメリット
AWS CDK
メリット:
- 抽象化: AWSリソースに関連する複雑な設定やブートストラッピングを抽象化することで、記述ミスを減少させることができます。
- 再利用: 複数のスタックやアプリケーションで同じパターンを使用する場合、カスタムコンストラクトを簡単に再利用できます。
- テストの容易性: TypeScript (または他のプログラミング言語) による記述のため、ユニットテストや統合テストを組み込みやすい。
デメリット:
- 隠蔽: 高度な抽象化により、何が「裏で」起こっているのかを理解するのが難しくなる場合がある。
- 依存関係の管理: NPMや他のパッケージマネージャを使用して依存関係を管理する必要があり、これにより追加のメンテナンスの複雑さが生じることがあります。
CloudFormation
メリット:
- 直接性: 何が起こるかがテンプレートに明示的に書かれており、AWSのドキュメントと直接対応しています。
- 成熟度: 多くのツール、プラグイン、コミュニティサポートが存在します。
デメリット:
- 複雑さ: 大規模なプロジェクトや複雑なリソースの関係を管理する場合、テンプレートが非常に長く、複雑になることがあります。
- ロジックの制約: YAMLの表現能力に制約があり、プログラム的なロジックの組み込みが難しい。
参考
実践 AWS CDK - TypeScript でインフラもアプリも! - Silverworks - BOOTH
CloudFormationは、AWS CDKから使うのが正解な気がしてきた - 新しいことにはウェルカム
普段 CloudFormation で書いている人が AWS CDK Workshop をやってみて思うこと | DevelopersIO
Discussion
このツールを使うとJSONからyamlに簡単に変換できますよー!
ありがとうございます。
便利なツールがあるのですね!!助かります。
仕事終わったら、やってみます~!!
ymlに変換できました〜
めっちゃ便利です!!
よかったです〜
yamlに変換した過程で変な記述になってるところもあるので気をつけてください〜
ありがとうございます!
見直してみます〜