0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS CDKでStack間のOutputをImportする方法とベストプラクティス

Posted at

AWS CDK スタック間でのOutput/Import完全ガイド

1. はじめに

AWS CDKを使っていると、あるスタックで作成したリソースを別のスタックから参照したいケースがよくあります。
例えば、VPCを作成するスタックと、そのVPCを利用してEC2やLambdaを作成するスタックを分けたい場合です。

そんなときに役立つのがOutputFn.importValueです。

2. 基本の考え方

AWS CDKは内部的にCloudFormationテンプレートを生成します。
CloudFormationでは、スタック間で値をやり取りするために以下の流れを取ります。

Export/Importの流れ:

  1. Export(スタックAが値を外部公開)
  2. Import(スタックBがその値を参照)

CDKではこれをCfnOutputFn.importValueで表現します。

3. 実装例

3.1 Export側(Stack A)

import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';

export class NetworkStack extends cdk.Stack {
  public readonly vpc: ec2.Vpc;

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    this.vpc = new ec2.Vpc(this, 'MyVpc', { maxAzs: 2 });

    new cdk.CfnOutput(this, 'VpcIdOutput', {
      value: this.vpc.vpcId,
      exportName: 'MyVpcId', // 重要: 一意な名前
    });
  }
}

3.2 Import側(Stack B)

import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';

export class AppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpcId = cdk.Fn.importValue('MyVpcId');

    const vpc = ec2.Vpc.fromLookup(this, 'ImportedVpc', { vpcId });

    new ec2.Instance(this, 'MyInstance', {
      instanceType: new ec2.InstanceType('t3.micro'),
      machineImage: ec2.MachineImage.latestAmazonLinux2(),
      vpc
    });
  }
}

4. アーキテクチャ図解


5. よくあるユースケース

ユースケース Export側 Import側 Export名の例
ネットワーク基盤 VPC ID EC2/Lambda等 myapp-prod-vpc-id
セキュリティグループ Security Group ID ALB/RDS等 myapp-prod-sg-web
データベース RDS Endpoint アプリケーション myapp-prod-db-endpoint
S3バケット Bucket名 Lambda/CodePipeline myapp-prod-artifacts-bucket
KMSキー Key ARN 暗号化サービス myapp-prod-kms-key-arn

6. 注意点とトラブルシューティング

6.1 重要な制約

項目 制約内容 対処法
Export名の一意性 リージョン内で一意である必要 プレフィックスを使用(例:myapp-env-
デプロイ順序 Export側を先にデプロイ cdk deploy NetworkStack AppStack
削除制約 Import中はExportを削除不可 Import側を先に削除
リージョン制約 同一リージョン内のみ クロスリージョンの場合はSSM Parameter Store等を使用

6.2 エラーパターンと対処法

7. ベストプラクティス

7.1 命名規則

レベル 推奨パターン
基本 {project}-{resource} myapp-vpc-id
環境別 {project}-{env}-{resource} myapp-prod-vpc-id
詳細 {project}-{env}-{service}-{resource} myapp-prod-web-sg-id

7.2 使い分けガイド

7.3 推奨する実装パターン

Props渡しパターン(同一アプリ内):

// main.ts
const networkStack = new NetworkStack(app, 'NetworkStack');
const appStack = new AppStack(app, 'AppStack', {
  vpc: networkStack.vpc  // 直接渡す
});

Output/Importパターン(別アプリ・クロスアカウント):

// 環境別Export名
const exportName = `${props.projectName}-${props.env}-vpc-id`;

new cdk.CfnOutput(this, 'VpcIdOutput', {
  value: this.vpc.vpcId,
  exportName: exportName,
  description: `VPC ID for ${props.projectName} ${props.env} environment`
});

8. 高度な活用例

8.1 複数値のExport

// 複数のサブネットIDをExport
this.vpc.privateSubnets.forEach((subnet, index) => {
  new cdk.CfnOutput(this, `PrivateSubnet${index}Output`, {
    value: subnet.subnetId,
    exportName: `myapp-prod-private-subnet-${index}`
  });
});

8.2 条件付きExport

// 本番環境のみExport
if (props.env === 'prod') {
  new cdk.CfnOutput(this, 'DatabaseEndpointOutput', {
    value: this.database.instanceEndpoint.hostname,
    exportName: 'myapp-prod-db-endpoint'
  });
}

まとめ

Output/Importは、スタック間の疎結合を実現する便利な仕組みです。
ただし、以下の点を意識して使用しましょう:

  • 同一CDKアプリ内ではpropsで依存注入を優先
  • Export名は環境・プロジェクト名を含めて一意に
  • デプロイ順序と削除順序に注意
  • クロスアカウント・別アプリ間では積極的に活用

適切に使い分けることで、保守性の高いインフラコードが書けるようになります!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?