CloudFormationのスタックをDeleteしてもデータを残す方法

2015.01.10

こんにちは、せーのです。
みなさん、CloudFormation使ってますか?ちょっと待ち時間がありますが出来上がった時のあの爽快感は使った事のある方にしかわからないかもしれません。
今日はこのCloudFormationを扱う時のちょっとしたTipsをご紹介します。

こんな事で困ったことないですか

CloudFormationはAWSの構成管理ツール、という事で基本的には新規構築だけではなく、修正や変更も基本的にはテンプレートを変更してUpdate Stackを行うことが理想です。初期構築時等なるべくクリーンな環境を作りたい場合は今までのStackで環境を作って色々実験し、本番は本番用として別スタックを作成して、今までのStackは削除することもあるかと思います。
ですがDelete Stackすると全てが削除されるわけなので、例えば一つのサーバーだけミドルウェアや新規ユーザーを入れていたとしてもDelete Stackしてしまえば全てまとめてTerminateされてしまいます

DeletionPolicy

CloudFormationには[DeletionPolicy]という項目があります。[DeletionPolicy]はDelete Stackされた時にリソースがどのような動きをするかを定義する項目です。
[DeletionPolicy]は

  • Delete(削除)
  • Retain(保持)
  • Snapshot(スナップショット・対象リソースのみ)

の3種類になります。Deleteはそのままなので残りの2つをサクッとご紹介します。

Retain

例えばS3のバケットをCloudFormationで作成した場合

"myS3Bucket" : {
  "Type" : "AWS::S3::Bucket",
  "DeletionPolicy" : "Retain"
}

とするとDelete Stackをした時にもバケットは保持されてデータは残ります。簡単ですね。

Snapshot

Snapshotを使えるのはリソース的にスナップショットが使えるAWS::EC2::VolumeAWS::RDS::DBInstanceAWS::Redshift::Clusterの3つのリソースに使えます。

"MyDB" : {
  "Type" : "AWS::RDS::DBInstance",
  "Properties" : {
    "DBName" : { "Ref" : "DBName" },
    "AllocatedStorage" : { "Ref" : "DBAllocatedStorage" },
    "DBInstanceClass" : { "Ref" : "DBInstanceClass" },
    "Engine" : "MySQL",
    "EngineVersion" : "5.5",
    "MasterUsername" : { "Ref" : "DBUser" },
    "MasterUserPassword" : { "Ref" : "DBPassword" },
    "Tags" : [ { "Key" : "Name", "Value" : "My SQL Database" } ]
  },
  "DeletionPolicy" : "Snapshot"
}

例えばこのようにRDBにつけるだけでDelete Stack時にスナップショットが取れます。簡単ですね。

やってみた

やってみましょう。S3とRDSを立ててそれぞれにDeletionPolicyをつけてみます。

test.template

{
  "AWSTemplateFormatVersion" : "2010-09-09",
 
  "Description" : "AWS CloudFormation Sample Template RDS_PIOPS: Sample template showing how to create an Amazon RDS Database Instance with provisioned IOPs.**WARNING** This template creates an Amazon Relational Database Service database instance. You will be billed for the AWS resources used if you create a stack from this template.",
 
  "Parameters": {
    "DBUser": {
      "NoEcho": "true",
      "Description" : "The database admin account username",
      "Type": "String",
      "MinLength": "1",
      "MaxLength": "16",
      "AllowedPattern" : "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription" : "must begin with a letter and contain only alphanumeric characters."
    },
 
    "DBPassword": {
      "NoEcho": "true",
      "Description" : "The database admin account password",
      "Type": "String",
      "MinLength": "8",
      "MaxLength": "41",
      "AllowedPattern" : "[a-zA-Z0-9]*",
      "ConstraintDescription" : "must contain only alphanumeric characters."
    }
  },
 
  "Resources" : {
    "testDB" : {
      "Type" : "AWS::RDS::DBInstance",
      "Properties" : {
        "AllocatedStorage" : "100",
        "DBInstanceClass" : "db.m1.small",
        "Engine" : "MySQL",
        "OptionGroupName" : "test",
        "PubliclyAccessible" : "true",
        "StorageType" : "io1",
        "Iops" : "1000",
        "MasterUsername" : { "Ref" : "DBUser" },
        "MasterUserPassword" : { "Ref" : "DBPassword" }
      },
	  "DeletionPolicy" : "Snapshot"
    },
 
	"testS3Bucketcm" : {
	  "Type" : "AWS::S3::Bucket",
	  "DeletionPolicy" : "Retain"
	}
  }
}

これをCloudFormationに流します。

deletionpolicy1

RDSを確認します。RDSのIDはランダムの文字列が振られます。

deletionpolicy2

次にS3です。S3のバケットは一意のものが求められる為、指定がなければリソース名にランダム文字列が自動的に振られます。

deletionpolicy3

ではDelete Stackしてみましょう。

deletionpolicy4

Delete Stackした後のEventを見てみます。

deletionpolicy5

S3に[DELETE_SKIPPED]というステータスがついています。削除をスキップしたっぽいです。RDSは特に変化なく[DELETE_COMPLETE]ですね。S3を見てみます。

deletionpolicy7

しっかり残っていますね。次にRDSのスナップショットを見てみます。

deletionpolicy6

ありました。先ほどのインスタンスIDがついていますね。ちなみにもう一回作ってみましょう。

deletionpolicy8

バケット名の後ろのランダム文字列が変わって別のバケットが出来上がりました。RDSを見てみましょう。

deletionpolicy9

こちらもランダムでついたIDが変わっています。つまりDeletionPolicyをつけたからといって上書きしたりスナップショットから作ったりはしない、ということですね。

まとめ

いかがでしたでしょうか。RDSのスナップショットにも費用がかかりますのでこのオプションは計画性を持って作るのがいいですね。上手く活用してください。

参考サイト