AWS CDKでクロススタック参照をしてみた
こんにちは、CX事業本部 IoT事業部の若槻です。
AWS CDKは、書き慣れた言語でAWSリソースのIaCを構成できるAWSサービスです。
このAWS CDKでアプリケーションを構築する際に、目的単位やリソース種別単位でCDKスタックを複数使用することがよくあるのですが、その際にスタック間でリソースのパラメーター(リソース名やArnなど)を参照させたい(クロススタック参照)場合があります。
そこで今回は、AWS CDKでクロススタック参照をする方法を確認してみました。
方法
スタックAwsCdkStateMachineStack
で作成したステートマシンのArnを、もう一方のスタックAwsCdkAppStack
で参照したい場合の実装で確認してみます。
参照される側のスタック
クロススタック参照される側のスタックでは、CfnOutput
を使用して参照させたいパラメーターをエクスポートします。
import * as cdk from '@aws-cdk/core'; import * as sfn from '@aws-cdk/aws-stepfunctions'; export class AwsCdkStateMachineStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); //ステートマシン const stateMachine = new sfn.StateMachine(this, 'sampleStateMachine', { stateMachineName: 'sampleStateMachine', definition: new sfn.Pass(this, 'pass', {}), }); //ステートマシンArnのエクスポート new cdk.CfnOutput(this, 'stateMachineArnOutPut', { value: stateMachine.stateMachineArn, exportName: 'stateMachineArn', }); } }
参照する側のスタック
クロススタック参照する側のスタックでは、Fn.importValue
を使用して参照したいパラメーターをインポートします。
import * as cdk from '@aws-cdk/core'; import * as lambda from '@aws-cdk/aws-lambda'; import * as lambdaNodejs from '@aws-cdk/aws-lambda-nodejs'; import * as iam from '@aws-cdk/aws-iam'; export class AwsCdkAppStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); //ステートマシンArnのインポート const stateMachineArn = cdk.Fn.importValue('stateMachineArn'); //Lambda関数 const startStateMachineFunc = new lambdaNodejs.NodejsFunction( this, 'startStateMachineFunc', { functionName: 'startStateMachineFunc', entry: 'src/lambda/startStateMachineHandler.ts', handler: 'handler', runtime: lambda.Runtime.NODEJS_14_X, environment: { STATE_MACHINE_ARN: stateMachineArn, }, } ); //ステートマシン起動権限付与 startStateMachineFunc.addToRolePolicy( new iam.PolicyStatement({ actions: ['states:StartExecution'], resources: [stateMachineArn], }) ); } }
CDKアプリ
CDKアプリでは、addDependency
を使用してクロススタック参照する/される両スタックの依存関係を明示的に定義します。
#!/usr/bin/env node import 'source-map-support/register'; import * as cdk from '@aws-cdk/core'; import { AwsCdkAppStack } from '../lib/aws-cdk-app-stack'; import { AwsCdkStateMachineStack } from '../lib/aws-cdk-state-machine-stack'; const app = new cdk.App(); //参照される側のスタック const awsCdkStateMachineStack = new AwsCdkStateMachineStack( app, 'AwsCdkStateMachineStack', {} ); //参照する側のスタック const awsCdkAppStack = new AwsCdkAppStack(app, 'AwsCdkAppStack', {}); //両スタックの依存関係を明示的に定義 awsCdkAppStack.addDependency(awsCdkStateMachineStack);
動作確認
両スタックをCDKデプロイします。
$ cdk deploy --all
CloudFormationのマネジメントコンソールで参照される側のスタックの出力を確認すると、ちゃんと値がエクスポートされています。
インポートしたステートマシンのArnがLambdaの環境変数にちゃんとセットできています。
addDependencyによる依存関係の指定の必要性について
addDependency
を使用せずスタック間の依存を明示的に指定しない場合でも、適切な順でスタックをスタックを作成すればエラーを回避できます。
例えば、下記のようにcdk deploy
コマンドで参照される側(依存される側)のAwsCdkStateMachineStack
を手前で指定すれば、デプロイは問題なく行われます。
$ cdk deploy AwsCdkStateMachineStack AwsCdkAppStack
しかし下記のように参照する側(依存する側)のAwsCdkAppStack
を手前で指定すると、AwsCdkStateMachineStack
が未作成であればNo export named stateMachineArn found.
というエラーとなります。
$ cdk deploy AwsCdkAppStack AwsCdkStateMachineStack 12:22:56 AM | ROLLBACK_IN_PROGRESS | AWS::CloudFormation::Stack | AwsCdkAppStack No export named stateMachineArn found. Rollback requested by user. 12:22:56 AM | ROLLBACK_IN_PROGRESS | AWS::CloudFormation::Stack | AwsCdkAppStack No export named stateMachineArn found. Rollback requested by user.
またcdk deploy --all
でデプロイした場合でも同様のエラーになる場合があります。よってaddDependency
はcdk deploy
コマンドの組み立て方によっては必須ではないのですが、明示的に指定しておいた方が安全です。
クロスリージョンの場合
クロスリージョンでのクロススタック参照を行いたい場合は下記を参考にしてください。
参考
- AWS Cloud Development Kit(AWS CDK)でカスタムリソース(@aws-cdk/custom-resources)をつかってみた - Qiita
- Import Stack Outputs in AWS CDK for Cross Stack References | bobbyhadz
以上