1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

AWS CDKでは、インフラをコードで管理できます。一方で、CloudFormationスタックを削除・更新する際には、AWSリソースや保存データが意図せず削除される可能性があります。

その挙動を制御するのがRemovalPolicyです。

本記事では、Amazon RDS for PostgreSQLを例に、DESTROY、RETAIN、SNAPSHOTの違いを実際に検証します。削除時のデータ消失リスクや、開発環境・本番環境での使い分けについても説明します。

対象読者

  • AWS CDKを使い始めた方
  • RemovalPolicyの違いを整理したい方
  • 開発環境と本番環境での削除ポリシーを検討している方

RemovalPolicyとは

RemovalPolicyは、CDKで管理しているAWSリソースがCloudFormationによって削除される際の挙動を指定する設定です。

removalPolicy: cdk.RemovalPolicy.DESTROY

主な値は次の3つです。

ポリシー 削除時の挙動 データ
DESTROY リソースを削除 原則として消失
RETAIN リソースを削除せず残す 保持される
SNAPSHOT スナップショットを作成して削除 スナップショットから復元可能

ただし、SNAPSHOTはすべてのAWSサービスで利用できるわけではありません。対応状況はリソースごとに異なります。

検証環境

今回は、RemovalPolicyの違いを確認しやすいAmazon RDS for PostgreSQLを使用します。

  • AWS CDK
  • TypeScript
  • Amazon RDS for PostgreSQL
  • Amazon VPC
  • AWS CloudFormation

検証では、データベースにテストデータを登録した後、RemovalPolicyを変更してスタックを削除します。

CDKプロジェクトの作成

mkdir removal-policy-sample
cd removal-policy-sample

cdk init app --language typescript
npm install

VPCとRDSを定義する

lib/removal-policy-sample-stack.tsを次のようにします。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as rds from 'aws-cdk-lib/aws-rds';

export class RemovalPolicySampleStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = new ec2.Vpc(this, 'Vpc', {
      maxAzs: 2,
      natGateways: 0,
    });

    const database = new rds.DatabaseInstance(this, 'Database', {
      engine: rds.DatabaseInstanceEngine.postgres({
        version: rds.PostgresEngineVersion.VER_16,
      }),

      vpc,

      // パブリックサブネットへ配置
      vpcSubnets: {
        subnetType: ec2.SubnetType.PUBLIC,
      },

      instanceType: ec2.InstanceType.of(
        ec2.InstanceClass.T4G,
        ec2.InstanceSize.MICRO,
      ),

      allocatedStorage: 20,
      databaseName: 'sampledb',

      // 認証情報はSecrets Managerに保存
      credentials: rds.Credentials.fromGeneratedSecret('postgres'),

      removalPolicy: cdk.RemovalPolicy.DESTROY,
      deletionProtection: false,

      // パブリックアクセスを有効化
      publiclyAccessible: true,
    });

    // 自分のグローバルIPだけ許可
    database.connections.allowFrom(
      ec2.Peer.ipv4('<自分のグローバルIP>/32'),
      ec2.Port.tcp(5432),
      'Allow PostgreSQL access from local PC',
    );

    new cdk.CfnOutput(this, 'Endpoint', {
      value: database.dbInstanceEndpointAddress,
    });

    new cdk.CfnOutput(this, 'SecretArn', {
      value: database.secret!.secretArn,
    });
  }
}

初期状態では、DESTROYを設定しています。

検証用に指定したグローバルIPから接続を許可しています。
<自分のグローバルIP>部分は自分の環境に合わせて変更してください。
なお、検証後は必ず削除してください。

デプロイする

npm run build
cdk bootstrap
cdk deploy

デプロイ後、データベースのエンドポイントを取得します。

aws cloudformation describe-stacks \
  --stack-name RemovalPolicySampleStack \
  --query "Stacks[0].Outputs"

認証情報はSecrets Managerに保存されています。接続には、次のようにシークレットを取得します。

aws secretsmanager get-secret-value \
  --secret-id <シークレット名>

取得した認証情報を使って、データを登録します。

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name VARCHAR(100) NOT NULL
);

INSERT INTO users (name)
VALUES ('Alice'), ('Bob');

SELECT * FROM users;

登録結果の例です。

 id | name
----+-------
  1 | Alice
  2 | Bob

DESTROYを検証する

まず、RemovalPolicy.DESTROYのままスタックを削除します。

cdk destroy

確認プロンプトで削除を実行すると、RDSインスタンス自体が削除されます。

再度AWSコンソールで確認すると、次の状態になります。

  • DBインスタンス:削除済み
  • DBインスタンスに保存されていたデータ:消失
  • 自動バックアップ:保持期間などの設定に依存
  • 手動スナップショット:作成されない

つまり、DESTROYはリソースとデータを削除する設定です。

DESTROYの用途

  • 一時的な検証環境
  • CI/CDで毎回作り直す環境
  • データを残す必要がない開発環境

本番データベースで安易に指定すると、重大なデータ消失につながります。

RETAINを検証する

次に、RemovalPolicyを変更します。

removalPolicy: cdk.RemovalPolicy.RETAIN,

再度デプロイします。

cdk deploy

データベースが作成されたら、先ほどと同じようにテストデータを登録します。

その後、スタックを削除します。

cdk destroy

RETAINでは、CloudFormationスタックは削除されますが、RDSインスタンスは残ります。

RETAINの確認ポイント

  • CloudFormationスタック:削除済み
  • RDSインスタンス:残る
  • データ:保持される
  • CDKスタックとの管理関係:失われる

重要なのは、残ったリソースがCDKスタックから管理されなくなる点です。

不要になったリソースは、別途AWSコンソールやCLIから削除する必要があります。

aws rds delete-db-instance \
  --db-instance-identifier <DB識別子> \
  --skip-final-snapshot

RETAINの用途

  • 本番データベース
  • スタック削除後もデータを保持したい場合
  • 誤削除への対策

ただし、リソースが残り続けることで、利用料金も発生し続けます。

SNAPSHOTを検証する

最後に、次のように変更します。

removalPolicy: cdk.RemovalPolicy.SNAPSHOT,

スタックをデプロイし、テストデータを登録した後で削除します。

cdk deploy
cdk destroy

SNAPSHOTでは、RDSインスタンスの削除前に最終スナップショットが作成されます。

SNAPSHOTの確認ポイント

  • CloudFormationスタック:削除済み
  • DBインスタンス:削除済み
  • 最終スナップショット:作成される
  • データ:スナップショットとして保持される

スナップショット一覧は、次のコマンドで確認できます。

aws rds describe-db-snapshots \
  --snapshot-type manual

スナップショットから復元する場合は、次のようにします。

aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier restored-db \
  --db-snapshot-identifier <スナップショット識別子>

復元後は、エンドポイントを確認して接続します。

aws rds describe-db-instances \
  --db-instance-identifier restored-db \
  --query "DBInstances[0].Endpoint.Address"

SNAPSHOTの用途

  • 削除前にバックアップを残したい場合
  • 検証環境を削除するが、データを復元できるようにしたい場合
  • データベースの移行や再構築を想定している場合

スナップショットは自動的に削除されません。不要になった後は、手動で削除する必要があります。

aws rds delete-db-snapshot \
  --db-snapshot-identifier <スナップショット識別子>

3つのポリシーを比較する

観点 DESTROY RETAIN SNAPSHOT
リソース 削除 残る 削除
データ 消失 保持 スナップショットに保持
復元 困難 残ったリソースを利用 スナップショットから復元
後処理 少ない リソース削除が必要 スナップショット削除が必要
料金リスク 小さい 継続課金に注意 スナップショット料金に注意
主な用途 開発・一時環境 本番データ バックアップを残す環境

データ消失リスクについて

RemovalPolicyは、バックアップ戦略そのものではありません。

例えばSNAPSHOTを指定していても、次のようなリスクがあります。

  • スナップショット作成に失敗する
  • 対象リソースがSNAPSHOTに対応していない
  • スナップショットを誤って削除する
  • 別リージョンの障害には対応できない
  • 復元手順を検証していない
  • データベース以外の関連リソースを削除する

また、RETAINも「安全にバックアップされる」という意味ではありません。単にリソースを削除せず残すだけです。

本番環境では、次の対策も組み合わせる必要があります。

  • 自動バックアップ
  • 手動スナップショット
  • AWS Backup
  • クロスリージョンバックアップ
  • 削除保護
  • 復元手順の定期的な検証
  • IAMによる削除権限の制限

deletionProtectionとの違い

RDSにはdeletionProtectionという設定もあります。

deletionProtection: true,

deletionProtectionは、DBインスタンスの削除自体を防止する設定です。

一方、RemovalPolicyは、削除されることになった場合の挙動を指定します。

設定 役割
deletionProtection 削除操作を防ぐ
RemovalPolicy 削除時の動作を決める

本番環境では、例えば次のような組み合わせが考えられます。

removalPolicy: cdk.RemovalPolicy.RETAIN,
deletionProtection: true,

この場合、誤ったcdk destroyだけでなく、削除保護によってDB削除も防ぎやすくなります。

環境ごとに設定を切り替える

開発環境と本番環境でポリシーを切り替える方法もあります。

const isProduction =
  this.node.tryGetContext('environment') === 'prod';

const removalPolicy = isProduction
  ? cdk.RemovalPolicy.RETAIN
  : cdk.RemovalPolicy.DESTROY;

const deletionProtection = isProduction;

cdk.jsonのコンテキストを使ってデプロイします。

cdk deploy -c environment=dev
cdk deploy -c environment=prod

環境別に明示的な設定を持たせることで、誤って本番環境にDESTROYを適用するリスクを下げられます。

CloudFormationテンプレートを確認する

CDKで指定したRemovalPolicyは、最終的にCloudFormationのDeletionPolicyとしてテンプレートへ反映されます。

cdk synth

生成されたテンプレート内で、次のような記述を確認できます。

DeletionPolicy: Retain
UpdateReplacePolicy: Retain

削除時だけでなく、リソースの置換時にもデータを保護したい場合は、UpdateReplacePolicyの挙動も確認することが重要です。

注意点

すべてのリソースがSNAPSHOTに対応しているわけではない

SNAPSHOTは、スナップショット機能を持つリソースでのみ利用できます。

対応していないリソースでは、期待したバックアップが作成されない可能性があります。対象リソースのCDKドキュメントやCloudFormationリファレンスを確認しましょう。

RemovalPolicyの変更は削除を伴う場合がある

既存リソースに対してRemovalPolicyを変更すると、CloudFormationの更新内容によってはリソースの置換や削除が発生することがあります。

変更前に必ず差分を確認します。

cdk diff

RETAINしたリソースは孤立する

スタックを削除した後、RETAINされたリソースはCloudFormationのスタック管理から外れます。

後から不要になったリソースを削除し忘れないよう、棚卸しの仕組みを用意しておくと安全です。

テスト後は必ずリソースを確認する

検証環境では、次のコマンドで不要なリソースが残っていないか確認します。

aws rds describe-db-instances
aws rds describe-db-snapshots --snapshot-type manual

VPCやSecrets Managerのシークレットなど、関連リソースも確認しましょう。

検証後のクリーンアップ

RETAINを使用した場合、RDSインスタンスが残っています。

SNAPSHOTを使用した場合は、手動スナップショットが残っています。

不要なリソースを確認したうえで削除します。

aws rds delete-db-instance \
  --db-instance-identifier <DB識別子> \
  --skip-final-snapshot
aws rds delete-db-snapshot \
  --db-snapshot-identifier <スナップショット識別子>

削除後は、AWSマネジメントコンソールやAWS CLIで、関連リソースが残っていないことを確認してください。

まとめ

今回の検証結果は次のとおりです。

  • DESTROYはリソースとデータを削除する
  • RETAINはリソースとデータを残す
  • SNAPSHOTはスナップショットを作成してからリソースを削除する
  • RETAINやSNAPSHOTでも、料金や削除漏れに注意が必要
  • RemovalPolicyだけでなく、削除保護やバックアップも組み合わせる必要がある

迷った場合の目安は次のとおりです。

環境 推奨例
一時的な開発環境 DESTROY
データを絶対に残したい本番環境 RETAIN
削除後に復元できる状態を残したい環境 SNAPSHOT

特に本番環境では、cdk destroyを実行する前に対象リソースとRemovalPolicyを確認する習慣をつけましょう。

この記事が、誰かのお役に立てば幸いです。

参考サイト

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?