はじめに
※この記事はAWS CDK Advent Calendar 2025 12日目の記事です。
https://qiita.com/advent-calendar/2025/aws-cdk
AWS CDKを使っていてどのリソースがスタックによって作成された?やこのリソースは手動で作ったのかスタックでCDKによるスタックで作られたのかがわからなくなることがありました!
そんな中いくつか、リソース名がわかりやすくなるような方法を見つけたので記事にしたいと思います。
AWS CDKで出てくるID
まず、AWS CDKを使っていて3つのIDに遭遇しましたので、その紹介から。
物理ID
こちらはマネコンでよく見るリソース名に当たります。手動でリソースを作成する際に我々の方で名前を付けたりします。CLIでリソースを調べる際にも利用したりしますね。
※VPCやセキュリティグループでは⚪︎⚪︎IDとして表現されます。
以下がCDKを使って表現したもの(S3バケットを作って表現)
import { Bucket } from 'aws-cdk-lib/aws-s3';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class TestStarterStack extends cdk.Stack {
private stackSuffix: string;
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// S3バケットの生成
new Bucket(this, 'Test-Bucket', {
// ↓物理IDとして登録される
bucketName: `test-bucket-20251212`
});
}
}
論理ID
こちらはCloudFormation側でテンプレート内で定義されたリソースを判別するものとなります。
テンプレート内で参照する際に利用されます。
以下がCloudFormationtテンプレートでVPCとサブネットを表現しています。
AWSTemplateFormatVersion: 2010-09-09
Resources:
MyVPC2:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.8.0/21
EnableDnsSupport: true
Tags:
- Key: Name
Value: MyVPC2fromCF
subnetName:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: "ap-northeast-1a"
# ↓論理ID「MyVPC2」を参照して物理IDであるVpcIdを取得
VpcId: !Ref MyVPC2
CidrBlock: 10.0.8.0/24
Tags:
- Key: Name
Value: subnet1fronCF
コンストラクトID (CDKを使うにあたっての論理IDも少し)
こちらはCDKを利用する際に作成するものです。コンストラクトからインスタンスが作られる際に第二引数として与えられる識別子となります。実際にCDKでリソースをCloludFormationスタックを介してデプロイされますが、その際は定義したコンストラクトIDの後ろにハッシュ値がついて論理IDが付与されます。こちらはCDKでデプロイした際にCloudFormationの方で自動的に生成されます。
以下がCDKを使って表現したもの(S3バケットとLambdaを作って表現)
import { Bucket } from 'aws-cdk-lib/aws-s3';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
// import * as sqs from 'aws-cdk-lib/aws-sqs';
export class TestStarterStack extends cdk.Stack {
private stackSuffix: string;
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// // thisの次の引数としてコンストラクトIDを指定する
new Bucket(this, 'Test-Bucket', {
bucketName: `test-bucket-20251212`
});
// thisの次の引数としてコンストラクトIDを指定する
const fn = new lambda.Function(this, 'Test-Function', {
runtime: lambda.Runtime.NODEJS_LATEST,
handler: 'index.handler',
code: lambda.Code.fromInline(`
exports.handler = async (event) => {
return "Hello";}`)
});
}
}
以下がCloudFormationテンプレートを生成したものの一部です。
{
"Resources": {
// ↓が論理ID
"TestBucket00913237": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "test-bucket-20251212"
},
"UpdateReplacePolicy": "Retain",
"DeletionPolicy": "Retain",
"Metadata": {
"aws:cdk:path": "TestStarterStack/Test-Bucket/Resource"
}
},
"TestFunctionServiceRoleC3D8AE16": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
]
}
]
},
"Metadata": {
"aws:cdk:path": "TestStarterStack/Test-Function/ServiceRole/Resource"
}
},
// ↓が論理ID
"TestFunctionE87BBA20": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "\n exports.handler = async (event) => {\n return \"Hello\";}"
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"TestFunctionServiceRoleC3D8AE16",
"Arn"
]
},
"Runtime": "nodejs22.x"
},
"DependsOn": [
"TestFunctionServiceRoleC3D8AE16"
],
"Metadata": {
"aws:cdk:path": "TestStarterStack/Test-Function/Resource"
}
},
},
}
CloudFormationの画面から確認するとコンストラクトIDの後ろにハッシュ値が生成されているのがわかりますね。これはCloudFormationが自動で生成してくれます。
※赤い枠線がコンストラクトIDで緑の枠線がCloudFormationスタックで生成する論理IDです。

物理IDをわかりやすくした
これまでいくつかIDを見てきましたが、物理IDを見てどのスタックで生成されたかを判別したいと思ったので、実際に2通りでやってみました。
その1 toLocaleLowerCase()を使う
toLocaleLowerCase()メソッドを使ってデプロイするスタック名を小文字にし、それを物理IDに付与する形です。
そうすることでスタック名と物理IDが紐づくかなと思います。
以下がCDKを使って表現したもの
import { Bucket } from 'aws-cdk-lib/aws-s3';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class TestStarterStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// S3バケットの生成
new Bucket(this, 'Test-Bucket', {
// バケット名の後ろにスタック名を小文字にしたものを適用
bucketName: `test-bucket-20251212-${this.stackName.toLocaleLowerCase()}`
});
// Lambdaの作成
const fn = new lambda.Function(this, 'Test-Function', {
// 関数名の後ろにスタック名を小文字にしたものを適用
functionName: `test-function-20251212-${this.stackName.toLocaleLowerCase()}`,
runtime: lambda.Runtime.NODEJS_LATEST,
handler: 'index.handler',
code: lambda.Code.fromInline(`
exports.handler = async (event) => {
return "Hello";}`)
});
}
}
以下がCloudFormationで確認したもの

※注意点として、付随して作られるリソースに関しては適用されません。例えばLambdaを作成した際に作られる、IAMロールにはつかなかったです。
その2 スタックIDの一部を付与
こちらではCloudFormationスタックのスタックIDの後ろ部分を物理IDの後ろの付けていきます。
今回はスタックIDの後ろの部分を物理IDに付与していきます。

以下がCDKを使って表現したもの
import { Bucket } from 'aws-cdk-lib/aws-s3';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Fn } from 'aws-cdk-lib';
export class TestStarterStack extends cdk.Stack {
// クラスで利用できるように定義
private stackSuffix: string;
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// initializeSuffix()メソッドの呼び出し
this.initializeSuffix();
// S3バケットの生成
new Bucket(this, 'Test-Bucket', {
// CloudFormationのスタックIDの後ろ部分を物理IDの後ろに適用
bucketName: `test-bucket-20251212-${this.stackSuffix}`
});
// Lambdaの作成
const fn = new lambda.Function(this, 'Test-Function', {
// CloudFormationのスタックIDの後ろ部分を物理IDの後ろに適用
functionName: `test-function-20251212-${this.stackSuffix}`,
runtime: lambda.Runtime.NODEJS_LATEST,
handler: 'index.handler',
code: lambda.Code.fromInline(`
exports.handler = async (event) => {
return "Hello";}`)
});
}
// initializeSuffix()メソッドを定義して、CloudFormationのスタックIDの後ろを抜粋
private initializeSuffix(){
const shortStackId = Fn.select(2, Fn.split('/', this.stackId))
this.stackSuffix = Fn.select(4, Fn.split('-', shortStackId))
}
}
以下がCloudFormationで確認したものです。物理IDの後ろにCloudFormationスタックIDの後ろ部分が適用されているのがわかります。

※こちらも付随して作られるリソースに関しては適用されません。例えばLambdaを作成した際に作られる、IAMロールにはつかなかったです。
まとめと感想
今回はCKDを利用してリソースを作成する際にどのスタックで作ったをわかるようにするため、CDKスタック名の付与やCloudFormationスタックIDを付与してみました。
論理IDに関してはあまり意識していなかったですが、今回の検証でCloudFormationやCDKにとってはリソースを参照するのに大事なものだなと感じました。
あと、関連リソースには付与されないので注意ですね(方法はあると思うのですが…)。
参考文献
以下を参考にして学習しました。
ありがとうございます。
AWS CDK公式ドキュメント
AWS CDK コンストラクト
コンテキスト値
Code with AWS and Typescript by creating serverless projects with CDK, CloudFormation, Cognito, Lambda and Amplify!


