CloudFormationで同一スタックで作成したリソースを後から別スタックに移動したかったので実現した手順を説明します。(プロジェクトにおいて何でもかんでも単一のyamlファイルにリソースを書いてしまってサイズ制限にかかったり、保守性が悪かったりで後からスタックの構成を変えたいことは往々にしてあると思います。)
今回実現することを以下に図で書いてみました。

はじめに 注意点と作業の流れ
すべてのリソースが移動できるわけではなさそうだったので、事前に移動したいリソースのタイプを確認しておいてください。移動(正確にはimport)できるリソースの一覧はこちら。DynamoDBやRDS、LambdaやEC2などほとんどのリソースは対象となっています。
今回参考にした公式ドキュメントはこちらです。
作業の流れを以下ざっと書きます。
- 移動対象のリソースに 削除ポリシー:保持 を設定
- 移動対象のリソースをスタックから削除(削除ポリシーにより、リソースは削除されない。スタックの管理下ではなくなるだけ)
- 移動対象のリソースを移動先のスタックにインポートする
今回はStack1にあるLambda関数をStack2に移動するという流れで説明します。
それでは具体的な作業手順を次章から説明します。
STEP1:移動対象のリソースに 削除ポリシー:保持 を設定
移動対象のリソース、今回であればLambda関数に削除ポリシー:保持を設定します。DeletionPolicy: Retain と書くだけです。既存のスタックであればyamlを修正したのちにスタックを更新しておきます。
# AWS CloudFormation スタックを作成のリージョンで作成されます。対象リージョンでスタックを展開してください。
#===============================================================================
# CloudFormation Template
#===============================================================================
AWSTemplateFormatVersion: 2010-09-09
Description: DynamoDB Template
#===============================================================================
# Resources
#===============================================================================
Resources:
#============================================================
# DynamoDB TABLE1作成
#============================================================
table1:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: "TABLE1"
AttributeDefinitions:
- AttributeName: ID
AttributeType: S
KeySchema:
- AttributeName: ID
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: "1"
WriteCapacityUnits: "1"
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: false
#============================================================
# S3バケット 作成
#============================================================
buket1:
Type: AWS::S3::Bucket
Properties:
BucketName: test-bucket0293821908
AccessControl: "Private"
#============================================================
# Lambda 作成(移動対象)
#============================================================
Lambda1:
Type: AWS::Lambda::Function
DeletionPolicy: Retain
Properties:
FunctionName: Lambda1
Handler: lambda_function.handler
Runtime: python3.9
Timeout: 60
Role: arn:aws:iam::123456789012:role/admin
Code:
S3Bucket: awsda-kaneko
S3Key: lambda_function.zip

問題なくUPDATEは完了するかと思います。
STEP2:移動対象のリソースをスタックから削除
削除ポリシー:保持を設定した、移動したいリソースをyamlから削除してスタックから削除します。
削除ポリシー:保持を設定しているのでスタックからリソースを削除したとしても、リソース事態は削除されません。どのスタックにも属していない野良のリソースになります。
#AWS CloudFormation スタックを作成のリージョンで作成されます。対象リージョンでスタックを展開してください。
#===============================================================================
# CloudFormation Template
#===============================================================================
AWSTemplateFormatVersion: 2010-09-09
Description: DynamoDB Template
#===============================================================================
# Resources
#===============================================================================
Resources:
#============================================================
# DynamoDB TABLE1作成
#============================================================
table1:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: "TABLE1"
AttributeDefinitions:
- AttributeName: ID
AttributeType: S
KeySchema:
- AttributeName: ID
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: "1"
WriteCapacityUnits: "1"
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: false
#============================================================
# S3バケット 作成
#============================================================
buket1:
Type: AWS::S3::Bucket
Properties:
BucketName: test-bucket02938219089
AccessControl: "Private"
yamlを用意したらスタックを更新します。

既存テンプレートを置き換えるを選択して更新したyamlテンプレートをアップロードします。

あとは次へを選択していくと変更セットの確認と送信ボタンが出現します。
繰り返しになりますが、変更セットにはRemoveと出ますがスタックの管理からなくなるだけで、リソースは残ります。

しばらく待つとUPDATE_COMPLETEになります。
念のため確認しておくと、対象のLambda関数は削除されていませんでした。

また、スタックのリソースからはLambda1が消えていました。

STEP2の作業は完了です。
STEP3:移動対象のリソースを移動先のスタックにインポートする
移動先のスタックでスタックアクション→スタックへのリソースへのインポートを選択します。

次の画面は必要なことの注意事項です。確認して次へを押下します。
インポートするリソースと、もともとスタックに存在するリソースを記述したyamlテンプレートを用意しておくようにという説明です。

さて、yamlテンプレートを準備します。
移行先のStack2にはもともとDynamoDBのtable2が存在していたとします。yamlテンプレートでは以下です。
#AWS CloudFormation スタックを作成のリージョンで作成されます。対象リージョンでスタックを展開してください。
#===============================================================================
# CloudFormation Template
#===============================================================================
AWSTemplateFormatVersion: 2010-09-09
Description: DynamoDB Template
#===============================================================================
# Resources
#===============================================================================
Resources:
#============================================================
# DynamoDB TABLE1作成
#============================================================
table2:
Type: 'AWS::DynamoDB::Table'
Properties:
TableName: "TABLE2"
AttributeDefinitions:
- AttributeName: ID
AttributeType: S
KeySchema:
- AttributeName: ID
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: '1'
WriteCapacityUnits: '1'
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: false
このyamlテンプレートに移動したいリソース(今回であればLambda1)を追記します。
#AWS CloudFormation スタックを作成のリージョンで作成されます。対象リージョンでスタックを展開してください。
#===============================================================================
# CloudFormation Template
#===============================================================================
AWSTemplateFormatVersion: 2010-09-09
Description: DynamoDB Template
#===============================================================================
# Resources
#===============================================================================
Resources:
#============================================================
# DynamoDB TABLE1作成
#============================================================
table2:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: "TABLE2"
AttributeDefinitions:
- AttributeName: ID
AttributeType: S
KeySchema:
- AttributeName: ID
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: "1"
WriteCapacityUnits: "1"
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: false
#============================================================
# Lambda 作成
#============================================================
Lambda1:
Type: AWS::Lambda::Function
DeletionPolicy: Retain
Properties:
FunctionName: Lambda1
Handler: lambda_function.handler
Runtime: python3.9
Timeout: 60
Role: arn:aws:iam::495592951950:role/admin
Code:
S3Bucket: awsda-kaneko
S3Key: lambda_function.zip
そして上記のテンプレートを画面で選択してアップロードします。

続いてインポートするリソースを選択します。今回はLambda1なのでLambda1と入力します。

あとは次へを選択してリソースのインポートを選択します。変更の欄では今回インポートしようとしているリソースが表示されます。

ほどなくするとIMPORT_COMPLETEとなります。リソースタブを確認すると無事Lambda1がstack2にインポートされました。めでたしめでたし。

さいごに 感想
開発初期ではそこまでシステムが肥大化するとは思わずにすべてのリソースを単一スタックに入れてしまって後々公開するパターンがありました。このように後からスタック間でリソースを移動できるのは非常に便利だと感じました。
PR
当ブログはWordPressテーマSWELLを使用しています。非常に使いやすく、簡単にプロのようなデザインを使えるのでお勧めです!!
SWELL – シンプル美と機能性両立を両立させた、圧巻のWordPressテーマ

システムエンジニア
AWSを中心としたクラウド案件に携わっています。
IoTシステムのバックエンド開発、Datadogを用いた監視開発など経験があります。
IT資格マニアでいろいろ取得しています。
AWS認定:SAP, DOP, SAA, DVA, SOA, CLF
Azure認定:AZ-104, AZ-300
ITIL Foundation
Oracle Master Bronze (DBA)
Oracle Master Silver (SQL)
Oracle Java Silver SE
■略歴
理系の大学院を卒業
IT企業に就職
AWSのシステム導入のプロジェクトを担当