AWS CloudFormationを用いて各リソースを管理していますが、テストで一時的に各サービスを使う際はコンソール上から手動で作成しています。
そうして作成したリソースをCFnスタックに取り込む方法が無いか探していたところ、公式マニュアルがありましたので試してみました。
手順
CloudFormationスタックを作成
まずは取り込む元となるスタックを予め作成しておきます。
コンソール→CloudFormation→スタック→スタックの作成→新しいリソースを使用
デザイナーを利用してS3バケットを作成するテンプレートを作成します。
実際には既に運用しているテンプレートが対象となります。
取り込み元リソースを作成
取り込み対象となるLambda関数とStep Functionsステートマシンとそれらに割り当てるIAMロールを作っておきます。
Lambda関数
入力したイベントをもとに挨拶を返す関数をコンソールで作成します。
名前をcall-greeting
としました。
import json
def lambda_handler(event, context):
name = event.get('name', 'World')
return f"Hello! {name}!"
StepFunctionsステートマシン
入力したイベントをもとにLambda call-greeting関数 を呼び出して結果を返す関数をコンソールで作成します。
名前をcall-greeting-sf
としました。
コンソール→Step Functions→ステートマシン→ステートマシンの作成→ワークフローを視覚的に設定
AWS Lambda Invokeをドラッグ&ドロップして、call-greeting関数を指定します。
IAMロール
Lambda関数とStepFunctionsステートマシンに割り当てるIAMロールをコンソールで作成します。
リソース取り込みで内容を変更したいので、全く意味のない設定にしておきます。
Lambda関数とStepFunctionsステートマシンにはまだ割り当てしていません。
取り込み元リソースをCFnテンプレートに記載
上記で作成したLambda関数とStepFunctionsステートマシンとIAMロールを最初に作成したスタックのテンプレートに追記します。
テンプレートはコンソールから
CloudFormation→スタック→作成したスタック名→テンプレート
から見ることができます。
インポートする各リソースは、テンプレートに DeletionPolicy 属性がある必要があります。
とありますので、取り込むLambda関数とStepFunctionsステートマシンのリソースについてはDeletionPolicyをDelete
として追加しました。
AWSTemplateFormatVersion: 2010-09-09
Metadata:
'AWS::CloudFormation::Designer':
7a1603be-030e-4e77-90c5-f4edc7766eb5:
size:
width: 60
height: 60
position:
x: 350
'y': 250
z: 0
embeds: []
Resources:
S3Bucket:
Type: 'AWS::S3::Bucket'
Properties: {}
Metadata:
'AWS::CloudFormation::Designer':
id: 7a1603be-030e-4e77-90c5-f4edc7766eb5
(Metadataは要らないので消しました)
AWSTemplateFormatVersion: "2010-09-09"
Resources:
CallGreetingRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: greeting-manipulation
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service:
- states.amazonaws.com
- lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns: [arn:aws:iam::aws:policy/AWSStepFunctionsFullAccess, arn:aws:iam::aws:policy/service-role/AWSLambdaRole]
S3Bucket:
Type: "AWS::S3::Bucket"
CallGreeting:
Type: "AWS::Lambda::Function"
DeletionPolicy: Delete
Properties:
FunctionName: call-greeting
Role: !GetAtt CallGreetingRole.Arn
Handler: index.lambda_handler
Runtime: pytyhon3.11
Code:
ZipFile: |
import json
def lambda_handler(event, context):
name = event.get('name', 'World')
return f"Hello! {name}!"
GreetingStateMachine:
Type: "AWS::StepFunctions::StateMachine"
DeletionPolicy: Delete
Properties:
StateMachineName: call-greeting-sf-cfn-ops
StateMachineType: STANDARD
RoleArn: !GetAtt CallGreetingRole.Arn
DefinitionString: |-
{
"Comment": "A description of my state machine",
"StartAt": "Lambda Invoke",
"States": {
"Lambda Invoke": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"OutputPath": "$.Payload",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:ap-northeast-1:account-id:function:call-greeting:$LATEST"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 2,
"MaxAttempts": 6,
"BackoffRate": 2
}
],
"End": true
}
}
}
取り込む
いざ取り込み~ということで
コンソール→CloudFormation→スタック→対象スタックを選択→スタックアクション→スタックのリソースへのインポート
を選択します。
テンプレートの指定で作成したテンプレートファイルをアップロードします。
リソースを識別画面でそれぞれ情報を記入します。
FunctionNameは取り込み元とテンプレートで一致する必要がありました。
レビューまで進み、エラーが無ければ「リソースをインポート」します。
確認
それぞれのリソースがどうなっているか確認してみます。
Lambda関数
call-greeting関数は開くと、
この関数はアプリケーションに属します。管理するにはこちらをクリックしてください。
と表示されます。
CFnを使用するとAWS Lambda アプリケーションで1つのリソースとして管理されますので、CFnスタックに取り込まれたことがわかります。
ですが、template.yml
で割り当てたロールが割り当てられていなかったです。
StepFunctionsステートマシン
コードは変更していないですが、割り当てていなかったIAMロールが割り当てられています。
IAMロール
IAMロールはtemplate.yml
で定義したものが反映されていませんでした。
取り込みは、それぞれ識別子を対応させて取り込むだけなので、詳細設定をテンプレート側に上書きはしてくれなさそうです。
更新
ということで、設定も変更するためにスタックの更新をします。
コンソール→CloudFormation→スタック→スタック名→スタックの更新→既存テンプレートを置き換える→テンプレートファイルのアップロード
作成したtemplate.ymlを選択して更新しようとすると、「変更される点がありません!」と出てきて実行できませんでした。
Lambda関数とIAMロールが適切に更新されていないので、適当に変更点を作ってあげました。
Lambda : Hello! World!
のエクスクラメーションマークを1つ増やす
IAMロール : arn:aws:iam::aws:policy/service-role/AWSLambdaRole
をarn:aws:iam::aws:policy/AWSLambda_FullAccess
に変更
Lambdaは適切にIAMロールが割り当てられて適切に更新されていました。
IAMロールは何故かarn:aws:iam::aws:policy/AWSStepFunctionsFullAccess
がついていませんでしたし、S3FullAccess
が消えていませんでした。
再作成
取り込み時、テンプレートの設定をDeletionPolicy : Delete
としたのでスタックを削除すると取り込んだリソースも消えます。
削除→再作成することで適切な設定に戻します。
削除後、template.yml
を使ってスタックを作成します。
まとめ
無事取り込みができたので良かったです。
ただ紐づけるだけなので、ついでに設定の変更も~等は辞めたほうが良いと思いました。
実際に使う時は慎重にやらなければいけなさそうです。
気づき
- 識別子は取り込み元と取り込み先で合わせる必要がある
- 既存リソースのインポート時は、既存リソースと同じ内容でテンプレートを書いたほうが良い
- テンプレートについでに更新内容を書くとその後の更新でおかしくなる可能性がある為
- どうしても直らなければ最悪スタックを削除して再作成が手っ取り早い
- 既存リソースのインポート時に、紐づかない新しいリソースをテンプレートに書くことはできない
- テンプレートの全ての変更点について、紐づける識別子リストが出現するので、「ついでに新しいリソースも作ろう」はできない