Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AWS CDKのConstruct IDはどのように命名するべきか?

ShuyaKinjo
November 01, 2024

AWS CDKのConstruct IDはどのように命名するべきか?

クラスメソッドのCDK事情大公開スペシャル #1の登壇資料です。

・概要
AWS CDKのConstruct IDを適切に命名することで、可読性の高い自動生成のリソース名や、名前の衝突を避けることができます。
Construct ID→CloudFormationの論理ID→リソース名の関係を説明し、実践的な命名規則のTipsをお話しします。

ShuyaKinjo

November 01, 2024
Tweet

More Decks by ShuyaKinjo

Other Decks in Technology

Transcript

  1. こんな経験ありませんか? 😕 スタックを宣言 StackのConstruct IDはクラス名 と同じ コンストラクトを宣言 🤔。 。(Construct IDは親を引き継

    いで動的にし、衝突を避けよう) new MySpecialServiceStack(app, "MySpecialServiceStack", {}); export class MySpecialServiceStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); new S3Construct(this, `${id}-S3Construct`); } } 4
  2. こんな経験ありませんか? 😕 スタックを宣言 StackのConstruct IDはクラス名 と同じ コンストラクトを宣言 🤔。 。(Construct IDは親を引き継

    いで動的にし、衝突を避けよう) new MySpecialServiceStack(app, "MySpecialServiceStack", {}); new S3Construct(this, `${id}-S3Construct`); export class MySpecialServiceStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); } } 4
  3. こんな経験ありませんか? 😕 S3 Constructの中も同じくIDを引 き継いでおこう export class S3Construct extends Construct

    { constructor(scope: Construct, id: string) { super(scope, id); new s3.Bucket(this, `${id}-Bucket1`, { versioned: true, removalPolicy: RemovalPolicy.DESTROY, autoDeleteObjects: true, }); new s3.Bucket(this, `${id}-Bucket2`, { encryption: s3.BucketEncryption.KMS_MANAGED, removalPolicy: RemovalPolicy.DESTROY, autoDeleteObjects: true, }); } } 5
  4. こんな経験ありませんか? 😕 S3 Constructの中も同じくIDを引 き継いでおこう new s3.Bucket(this, `${id}-Bucket1`, { new

    s3.Bucket(this, `${id}-Bucket2`, { export class S3Construct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); versioned: true, removalPolicy: RemovalPolicy.DESTROY, autoDeleteObjects: true, }); encryption: s3.BucketEncryption.KMS_MANAGED, removalPolicy: RemovalPolicy.DESTROY, autoDeleteObjects: true, }); } } 5
  5. cdk deploy ✨ % cdk deploy 'MySpecialServiceStack' ... Do you

    wish to deploy these changes (y/n)? y MySpecialServiceStack: deploying... [1/1] MySpecialServiceStack: creating CloudFormation changeset... ✅ MySpecialServiceStack ✨ Deployment time: 53.89s Stack ARN: arn:aws:cloudformation:ap-northeast-1:012345678910:stack/MySpecialServiceStack/1625a640-9787-11ef-9f35-0e80c9521165 ✨ Total time: 61.44s 6
  6. 結論 Construct ID は scope の中で一意にする Construct ID は PascalCase

    で記述する Construct ID に Construct 、 Stack とつけない 親 コンストラクト で表している情報を繰り返さない Default と Resource を活用し Construct ID を短縮する 12
  7. Construct ID とは Construct ID とは、CDK で コンストラクト を インスタンス化

    する際 に、第 2 引数に渡す文字列のことです。 CDK では コンストラクト を利用して Stack 内のリソースを構造化でき ます。指定する Construct ID は コンストラクト のスコープ内で一意で ある必要があります。 例) new sqs.Queue(this, "MyQueue"); // MyQueue が Construct ID 14
  8. 論理 ID とは 論理 IDは CloudFormation テンプレートの Resources セクションでリ ソースを一意に示す

    ID です。論理 ID の変更はリソースの置換を意味し ます。 例) Resources: MyEC2Instance: # 論理ID Type: AWS::EC2::Instance Properties: ImageId: ami-0ff8a91507f77f867 15
  9. 論理 ID とは 論理 IDは CloudFormation テンプレートの Resources セクションでリ ソースを一意に示す

    ID です。論理 ID の変更はリソースの置換を意味し ます。 例) MyEC2Instance: # 論理ID Resources: Type: AWS::EC2::Instance Properties: ImageId: ami-0ff8a91507f77f867 15
  10. Construct ID と論理 ID の関係性 Construct ID は CDK から

    CloudFormation テンプレートを合成する 際、CloudFormation の論理 ID を決めるために使用されます。 リソースに明示的に名前を指定しない場合、CloudFormation は論理 ID をもとにリソース名を生成します。図にすると以下の関係性です。 AWS CloudFormation AWS CDK cdk synth deploy 自動生成のリソース名 論理ID Construct ID 16
  11. 論理 IDは切り捨てられる CloudFormation の論理 ID は 255 文字まで指定可能です。 しかし自動生成されるリソース名は論理 ID

    を一定の桁数で切 り捨てるため、長すぎる論理 ID はリソース名を正しく表せないこ とがあります。 17
  12. 論理 IDは切り捨てられる CloudFormation の論理 ID は 255 文字まで指定可能です。 しかし自動生成されるリソース名は論理 ID

    を一定の桁数で切 り捨てるため、長すぎる論理 ID はリソース名を正しく表せないこ とがあります。 Construct IDを適切につけることで論理IDを短縮し、可読性の高いリ ソース名を生成しましょう 17
  13. Construct ID は PascalCase で記述する 論理 ID 生成時に Construct ID

    に含まれる英数字以外の文字列は除去さ れます。 Construct ID は PascalCase で記述することで、リソース名の 可読性を高め、意図せぬ論理 ID 衝突を防ぐことができます。 ⭕️ Good ❌ Bad new sqs.CfnQueue(this, "MyQueue"); // 上位のConstruct IDと結合されて区切りがわかりづらくなる new sqs.CfnQueue(this, "myQueue"); // 以下は論理IDが衝突する new sqs.CfnQueue(this, "my-queue"); new sqs.CfnQueue(this, "myqueue"); 19
  14. Construct ID に Construct や Stack とつけない Construct ID に

    Construct や Stack を含めると、CDK の世界で止める べき事情が Cfn テンプレート や AWS の世界に漏れてしまいます。 Construct のクラス名と同じ名前を Construct ID につけたくなった場 合、一歩踏みとどまって、論理 ID やリソース名に使われた時にどう見 えるかを考えて命名しましょう。 ⭕️ Good ❌ Bad new ApiConstruct(this, "Api"); new ApiConstruct(this, "ApiConstruct"); 20
  15. 親 コンストラクト で表している情報を繰り返さない 論理 ID は コンストラクト のパスツリーを結合して生成されます。 冗長さをなくしましょう。 ⭕️

    Good // 親コンストラクトでの宣言 new ApiConstruct(this, "Api"); // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); const role = new iam.Role(this, "ExecutionRole"); // 省略 } } ❌ Bad // 親コンストラクトでの宣言 new ApiConstruct(this, "Api"); // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); const role = new iam.Role(this, "ApiExecutionRole"); // 省略 } } 21
  16. 親 コンストラクト で表している情報を繰り返さない 論理 ID は コンストラクト のパスツリーを結合して生成されます。 冗長さをなくしましょう。 ⭕️

    Good new ApiConstruct(this, "Api"); const role = new iam.Role(this, "ExecutionRole"); // 親コンストラクトでの宣言 // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); // 省略 } } ❌ Bad // 親コンストラクトでの宣言 new ApiConstruct(this, "Api"); // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); const role = new iam.Role(this, "ApiExecutionRole"); // 省略 } } 21
  17. 親 コンストラクト で表している情報を繰り返さない 論理 ID は コンストラクト のパスツリーを結合して生成されます。 冗長さをなくしましょう。 ⭕️

    Good new ApiConstruct(this, "Api"); const role = new iam.Role(this, "ExecutionRole"); // 親コンストラクトでの宣言 // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); // 省略 } } ❌ Bad // 親コンストラクトでの宣言 new ApiConstruct(this, "Api"); // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); const role = new iam.Role(this, "ApiExecutionRole"); // 省略 } } 21 論理ID:ApiExecutionRole
  18. 親 コンストラクト で表している情報を繰り返さない 論理 ID は コンストラクト のパスツリーを結合して生成されます。 冗長さをなくしましょう。 ⭕️

    Good new ApiConstruct(this, "Api"); const role = new iam.Role(this, "ExecutionRole"); // 親コンストラクトでの宣言 // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); // 省略 } } ❌ Bad new ApiConstruct(this, "Api"); const role = new iam.Role(this, "ApiExecutionRole"); // 親コンストラクトでの宣言 // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); // 省略 } } 21 論理ID:ApiExecutionRole
  19. 親 コンストラクト で表している情報を繰り返さない 論理 ID は コンストラクト のパスツリーを結合して生成されます。 冗長さをなくしましょう。 ⭕️

    Good new ApiConstruct(this, "Api"); const role = new iam.Role(this, "ExecutionRole"); // 親コンストラクトでの宣言 // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); // 省略 } } ❌ Bad new ApiConstruct(this, "Api"); const role = new iam.Role(this, "ApiExecutionRole"); // 親コンストラクトでの宣言 // ApiGatewayとRoleを定義するカスタムコンストラクト class ApiConstruct extends Construct { constructor(scope: Construct, id: string) { super(scope, id); // 省略 } } 21 論理ID:ApiExecutionRole 論理ID:ApiApiExecutionRole
  20. Construct ID に Default と Resource を活用する DefaultとResourceはコンストラクトIDを短縮するための仕組みです。 共通の設定をあらかじめ入れてお くLambdaのカスタムコンストラ

    クトを例にします。 LambdaConstructは再利用を前 提に作られており、使用時に一意 に命名されることが期待されま す。 export class LambdaConstruct extends Construct { readonly function: nodejs.NodejsFunction; constructor(scope: Construct, id: string, props: LambdaConstructProps) { super(scope, id); this.function = new nodejs.NodejsFunction(this, "Resource", { functionName, handler: "handler", tracing: lambda.Tracing.ACTIVE, runtime: lambda.Runtime.NODEJS_20_X, timeout: Duration.seconds(5), memorySize: 1769, architecture: lambda.Architecture.ARM_64, ...props, }); } } 22
  21. Construct ID に Default と Resource を活用する DefaultとResourceはコンストラクトIDを短縮するための仕組みです。 共通の設定をあらかじめ入れてお くLambdaのカスタムコンストラ

    クトを例にします。 LambdaConstructは再利用を前 提に作られており、使用時に一意 に命名されることが期待されま す。 this.function = new nodejs.NodejsFunction(this, "Resource", { export class LambdaConstruct extends Construct { readonly function: nodejs.NodejsFunction; constructor(scope: Construct, id: string, props: LambdaConstructProps) { super(scope, id); functionName, handler: "handler", tracing: lambda.Tracing.ACTIVE, runtime: lambda.Runtime.NODEJS_20_X, timeout: Duration.seconds(5), memorySize: 1769, architecture: lambda.Architecture.ARM_64, ...props, }); } } 22
  22. Construct ID に Default と Resource を活用する Resource と Default

    は論理IDを生成する際に除去されます。 これにより、論理IDが短くなり可読部が増えます。 両者の違いについて、詳細は後述するブログに書いています。 ほとんどの場合では Resource を使っておけば無難です。 23
  23. 結論(再掲) Construct ID は scope の中で一意にする Construct ID は PascalCase

    で記述する Construct ID に Construct 、 Stack とつけない 親 コンストラクト で表している情報を繰り返さない Default と Resource を活用し Construct ID を短縮する 24
  24. 参考 [AWS CDK] Construct ID はパスカルケースで命名するのが良い CDK Tips: ID=Default の使い方

    AWS CDK がデプロイするリソース名はどうやって決まるのか 26
  25. 27

  26. 28