[CloudFormation]リソース置換時の挙動をUpdateReplacePolicyで制御する

2019.08.15

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンニチハ、千葉です。

CloudFormationでリソース置換時の挙動を制御するUpdateReplacePolicy について調べてみました。

そもそもを整理すると、CloudFormationではリソース変更の種類が複数あり、それぞれに対応した挙動を設定できます。

  • リソース作成(CreationPolicy):シグナル受信またはタイムアウトするまで作成完了にならない(例えばEC2でアプリインストール後にシグナルを送るなど)
  • スタック削除(DeletionPolicy):スタック削除時に、リソースを削除・保持・スナップショット取得を指定する
  • リソース更新(UpdatePolicy):AutoScalingなど特定リソースに対してローリングアップデートなどを指定する
  • リソース置換(UpdateReplacePolicy):リソース置換時に、リソースを削除・保持・スナップショット取得を指定する

挙動を見ると、DeletionPolicyのリソース置換バージョンと見ればよさそうです。

やってみた

実際にCloudFormationでリソース置換時の挙動として、DeleteRetainSnapshotをそれぞれ指定して動きを確認してみました。(何も指定しない場合デフォルト動作としてはDeleteの動作になります)

今回サンプルのテンプレートとして、EC2を作るCloudFormationスタックで試してみます。3種類のUpdateReplacePolicyを指定した3台のEC2を起動します。(CFnのコードは後術)

スタックを作ると、EC2がそれぞれ作成されました。

置換するために, ap-northeast-1aap-northeast-1c に変更しスタックの更新を行います。変更セットのプレビューを見ると置換がTrueとなってます。

更新した結果、想定した挙動になりました!確認してみましょう。

  • UpdateReplacePolicy: DeleteはEC2が削除
  • UpdateReplacePolicy: SnapshotはEC2が削除
  • UpdateReplacePolicy: RetainはEC2が残る

UpdateReplacePolicyにスナップショットが残っているか見ましたが、残ってませんでした

スナップショットをサポートしていないリソースに対して UpdateReplacePolicy の snapshot オプションを指定すると、CloudFormation はデフォルトオプション (Delete) の動作になります とのことです。

スナップショットをサポートするリソースは以下のとおりです。

  • AWS::EC2::Volume
  • AWS::ElastiCache::CacheCluster
  • AWS::ElastiCache::ReplicationGroup
  • AWS::Neptune::DBCluster
  • AWS::RDS::DBCluster
  • AWS::RDS::DBInstance
  • AWS::Redshift::Cluster

最後に

UpdateReplacePolicyの挙動を実際に確認してみました。特にUpdateReplacePolicyにスナップショットを指定しておくと、間違って置換してしまっても復旧できるので、センシティブなデータについてはスナップショットを指定しておくといいのかなと思いました。また、スナップショットに対応しているリソースは決まっているので注意しましょう。

参考

おまけ

今回試したCloudFormationテンプレートをおいておきます。

AWSTemplateFormatVersion: '2010-09-09'
Description: This CloudFormation template to create EC2 instances.

Mappings:
EC2:
KeyName: { Value: xxxxx }
ImageId: { Value: ami-xxxxx }
InstanceType: { Value: t3a.nano }
Ec2SecurityGroup: { Value: sg-xxxxx }
AZ: { Value: ap-northeast-1a }

Resources:
## UpdateReplacePolicy:Delete
Delete:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [ EC2, ImageId, Value ]
KeyName: !FindInMap [ EC2, KeyName, Value ]
InstanceType: !FindInMap [ EC2, InstanceType, Value ]
SecurityGroupIds:
- !FindInMap [ EC2, Ec2SecurityGroup, Value ]
BlockDeviceMappings:
-
DeviceName: /dev/sda1
Ebs:
VolumeSize: 10
AvailabilityZone: !FindInMap [ EC2, AZ, Value ]
Tags:
- Key: Name
Value: UpdateReplacePolicy:Delete
UpdateReplacePolicy: Delete

## UpdateReplacePolicy:Retain
Retain:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [ EC2, ImageId, Value ]
KeyName: !FindInMap [ EC2, KeyName, Value ]
InstanceType: !FindInMap [ EC2, InstanceType, Value ]
SecurityGroupIds:
- !FindInMap [ EC2, Ec2SecurityGroup, Value ]
BlockDeviceMappings:
-
DeviceName: /dev/sda1
Ebs:
VolumeSize: 10
AvailabilityZone: !FindInMap [ EC2, AZ, Value ]
Tags:
- Key: Name
Value: UpdateReplacePolicy:Retain
UpdateReplacePolicy: Retain

## UpdateReplacePolicy:Snapshot
Snapshot:
Type: AWS::EC2::Volume
Properties:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [ EC2, ImageId, Value ]
KeyName: !FindInMap [ EC2, KeyName, Value ]
InstanceType: !FindInMap [ EC2, InstanceType, Value ]
SecurityGroupIds:
- !FindInMap [ EC2, Ec2SecurityGroup, Value ]
BlockDeviceMappings:
-
DeviceName: /dev/sda1
Ebs:
VolumeSize: 10
AvailabilityZone: !FindInMap [ EC2, AZ, Value ]
Tags:
- Key: Name
Value: UpdateReplacePolicy:Snapshot
UpdateReplacePolicy: Snapshot