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でスタック間依存を解消する方法メモ

Posted at

AWS CDKでスタック間依存を解消する方法メモ

AWS CDKのExport/Importとは?

AWS CDKでは、あるスタックのリソース(例:VPCやEC2インスタンス)を別のスタックから参照することができます。

// NetworkStack.ts
export class NetworkStack extends cdk.Stack {
  readonly vpc: ec2.Vpc;
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    this.vpc = new ec2.Vpc(this, 'AppVpc', { maxAzs: 2 });
  }
}

// AppStack.ts
export class AppStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props: { vpc: ec2.Vpc }) {
    super(scope, id, props);
    new ec2.Instance(this, 'AppServer', {
      vpc: props.vpc, // ← 他スタックのVPCを参照
      instanceType: new ec2.InstanceType('t3.micro'),
      machineImage: ec2.MachineImage.latestAmazonLinux(),
    });
  }
}

一見便利ですが、裏ではCDKが自動的に以下のようなCloudFormation設定を生成しています。

# NetworkStackのOutputs
Outputs:
  VpcId:
    Value: !Ref AppVpc
    Export:
      Name: NetworkStack:ExportsOutputRefAppVpc

# AppStackでの参照
Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      SubnetId: !ImportValue NetworkStack:ExportsOutputRefAppVpc

つまり、CloudFormationのExport/ImportValueが裏で作られ依存関係を持つことになります。

依存関係のデメリット

この仕組みには便利さの裏に大きなデメリットがあります。

  • 削除できない
    Exportを持つスタックを削除しようとすると、Importしているスタックがある限り削除不可。

  • 順序に依存
    Producer(Export側)を更新するたびに、Consumer(Import側)も自動的にデプロイ対象になり、CI/CDが複雑化。

  • 単体再デプロイが難しい
    一部だけ壊れても、依存する全スタックを再構築しなければならない。

→ 結果として、強すぎる結合が運用負担を増やします。

SSM Parameter Storeを使った解決策

CloudFormationのExport/Importを使わずに値を共有するには、
AWS Systems Manager Parameter Store が有効です。

① Producer(値を提供する側)

// ProducerStack.ts
import * as ssm from 'aws-cdk-lib/aws-ssm';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as cdk from 'aws-cdk-lib';

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

    const instance = new ec2.Instance(this, 'AppEc2', {
      vpc: new ec2.Vpc(this, 'AppVpc', { maxAzs: 2 }),
      instanceType: new ec2.InstanceType('t3.micro'),
      machineImage: ec2.MachineImage.latestAmazonLinux(),
    });

    new ssm.StringParameter(this, 'Ec2IdParam', {
      parameterName: '/myapp/ec2-id',
      stringValue: instance.instanceId,
    });
  }
}

② Consumer(値を使う側)

// ConsumerStack.ts
import * as ssm from 'aws-cdk-lib/aws-ssm';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as cdk from 'aws-cdk-lib';

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

    const instanceId = ssm.StringParameter.valueFromLookup(this, '/myapp/ec2-id');

    const imported = ec2.Instance.fromInstanceId(this, 'ImportedEc2', instanceId);

    new ec2.SecurityGroup(this, 'ExampleSG', {
      vpc: imported.instanceVpc,
      description: `SecurityGroup for instance ${instanceId}`,
    });
  }
}

この構成では:

  • CloudFormationのExport/ImportValueは生成されません
  • Producerを単体でdestroy可能
  • ConsumerはSSMを介して最新値を取得できます

cdk.context.jsonについて注意すべきこと

valueFromLookup() を使うと、CDKはSSMの値を合成時に問い合わせてキャッシュします。
このキャッシュは cdk.context.json に保存されます。

基本ルール

操作 コマンド 内容
全クリア cdk context --clear 全てのルックアップ結果を削除(再取得)
部分クリア cdk context --reset <key> 指定キーのみ削除
キー確認 cat cdk.context.json キャッシュされたキー一覧を確認

キャッシュ更新運用例

# SSMパラメータの値だけ再取得したい場合
cdk context --reset "ssm:account=111111111111:region=ap-northeast-1:parameterName=/myapp/ec2-id"

# 全てのルックアップを更新したい場合
cdk context --clear

# 更新後に差分を確認
cdk diff

これで cdk diff に最新SSM値の変更が反映されます。


結論

CDKのExport/Importは便利ですが、強すぎる依存関係を生みます。SSM Parameter Storeを使えば、スタックを疎結合に保ちながら差分検知も可能です。valueFromLookup + cdk context --clear の運用は、再現性と柔軟性を両立するベストプラクティスです。

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?