パラメータストアでリソース(コンストラクト)間 参照

スタック間の前にコンストラクト間試した

コード全体

cdk.ts

import { App } from "aws-cdk-lib";
import { CdkStack } from '../lib/cdk-stack';

const app = new App();
new CdkStack(app, 'Cdk', {
});

cdk-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { VpcStack } from './resource/vpc-stack';

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

    const vpcStack = new VpcStack(this, 'VpcStack', {
      env: {
        account: '123456789012',
        region: 'ap-northeast-1',
      },
    });

    this.addDependency(vpcStack);
  }
}

vpc-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { SubnetType, Vpc } from 'aws-cdk-lib/aws-ec2';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as ssm from 'aws-cdk-lib/aws-ssm';

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

    const vpc = new Vpc(this, 'Vpc', {
      ipAddresses: ec2.IpAddresses.cidr('192.168.0.0/16'),
      maxAzs: 2,
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'public',
          subnetType: SubnetType.PUBLIC,
        },
      ],
    });

    const securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
      vpc,
      allowAllOutbound: true,
    });

    securityGroup.addIngressRule(
      ec2.Peer.ipv4('54.x.x.x/32'),
      ec2.Port.tcp(22)
    )

    securityGroup.addIngressRule(
      ec2.Peer.ipv4('52.x.x.x/16'),
      ec2.Port.tcp(22)
    )

    const ami = new ec2.AmazonLinuxImage({
      generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
      cpuType: ec2.AmazonLinuxCpuType.ARM_64
    });

    const instanceRole = new iam.Role(this, 'InstanceRole', {
      assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName(
          'AmazonSSMManagedInstanceCore',
        ),
      ],
    });

    new ssm.StringParameter(this, 'VPCID', {
      parameterName: '/cdk/vpcid',
      stringValue: vpc.vpcId,
    });

    const ec2instance = new ec2.Instance(this, 'Instance', {
        vpc: ec2.Vpc.fromLookup(this, 'VPC', {
          vpcId: ssm.StringParameter.valueFromLookup(this, '/cdk/vpcid'),
        }),
        keyName: 'RESEARCH',
        instanceType: ec2.InstanceType.of(
          ec2.InstanceClass.T4G,
          ec2.InstanceSize.NANO),
          machineImage: ami,
          securityGroup: securityGroup,
          role: instanceRole,
          blockDevices: [
            {
              deviceName: `/dev/xvda`,
              volume: ec2.BlockDeviceVolume.ebs(8, {
                volumeType: ec2.EbsDeviceVolumeType.GP3,
              })
            },
          ],
        });
        ec2instance.node.addDependency(vpc);
      }
}

  • CdkStackからVpcStackをコールするときにenvを渡す。envを渡さないとVpcStack内でEC2コンストラクトを作成するところのssm.StringParameter.valueFromLookupが動作しない
    const vpcStack = new VpcStack(this, 'VpcStack', {
      env: {
        account: '123456789012',
        region: 'ap-northeast-1',
      },
  • VPCIDをSSMパラメータストアに出す
    new ssm.StringParameter(this, 'VPCID', {
      parameterName: '/cdk/vpcid',
      stringValue: vpc.vpcId,
    });
  • EC2作成コンストラクトでVPCを指定するときに以下のようにする
    const ec2instance = new ec2.Instance(this, 'Instance', {
        vpc: ec2.Vpc.fromLookup(this, 'VPC', {
          vpcId: ssm.StringParameter.valueFromLookup(this, '/cdk/vpcid'),
        }),
  • EC2作成コンストラクトの直後にVPCコンストラクトへの依存関係をセットする
    const ec2instance = new ec2.Instance(this, 'Instance', { //上記と同じブロック
    ...
    });
    ec2instance.node.addDependency(vpc);

コメント

CDKでクロススタック参照がつらいので(リソース名変えたいなと思うときに依存性解決エラー)、パラメータストア参照を試したがここまでやっときた。

うまくいかなかった理由はec2.InstanceでVPCを渡すときの型が分かってなかったから。

まだまだだけどおぼろげにどういう指定が必要なのか見えてきた。

追記

セキュリティグループもvpcを参照してたのでパラメータストア参照にしてみた

(VPC名変えるときにセキュリティグループも毎度再作成試みられて依存関係エラーでがちだったのでパラメータストア参照にするとよいかもしれない)

    const securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
      vpc: ec2.Vpc.fromLookup(this, 'VPC', {
        vpcId: ssm.StringParameter.valueFromLookup(this, '/cdk/vpcid'),
      }),
      allowAllOutbound: true,
    });

追記2

vpc-stack.tsは以下の方が良い

securityGroupとec2コンストラクトで、都度fromLookupしてた部分を、ssmvpcにまとめることができた

(+ついでにVPCIDをスネークケースにしたVpcId)

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { SubnetType, Vpc } from 'aws-cdk-lib/aws-ec2';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as ssm from 'aws-cdk-lib/aws-ssm';

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

    const vpc = new Vpc(this, 'Vpc', {
      ipAddresses: ec2.IpAddresses.cidr('192.168.0.0/16'),
      maxAzs: 2,
      subnetConfiguration: [
        {
          cidrMask: 24,
          name: 'public',
          subnetType: SubnetType.PUBLIC,
        },
      ],
    });

...

    new ssm.StringParameter(this, 'VpcId', {
      parameterName: '/cdk/vpcid',
      stringValue: vpc.vpcId,
    });

    const ssmvpc = ec2.Vpc.fromLookup(this, 'SsmVpc', {
      vpcId: ssm.StringParameter.valueFromLookup(this, '/cdk/vpcid'),
    });

    const securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
      vpc: ssmvpc,
      allowAllOutbound: true,
    });

...

    const ec2instance = new ec2.Instance(this, 'Instance', {
      vpc: ssmvpc,
      keyName: 'RESEARCH',
      instanceType: ec2.InstanceType.of(
        ec2.InstanceClass.T4G,
        ec2.InstanceSize.NANO),
      machineImage: ami,
      securityGroup: securityGroup,
      role: instanceRole,
      blockDevices: [
        {
          deviceName: `/dev/xvda`,
          volume: ec2.BlockDeviceVolume.ebs(8, {
            volumeType: ec2.EbsDeviceVolumeType.GP3,
          })
        },
      ],
    });
    ec2instance.node.addDependency(vpc);
  }
}