はじめに
学習用に作った AWS 環境を terraform destroy でまとめて片付けようとしたら、RDS の削除でこのエラーが出て止まりました。
Error: deleting RDS DB Instance (aws-study-rds): ...
DBSnapshotAlreadyExists: Cannot create the snapshot because a snapshot
with the identifier aws-study-final-snapshot already exists.
「削除しようとしているのに、スナップショットが“すでに存在する”で止まる?」と、最初は状況が飲み込めませんでした。
先に結論:RDS を削除するとき、設定によっては最終スナップショットを作ろうとします。そのスナップショット名が固定で、しかも同じ名前のスナップショットが前回の名残で残っていたため、「同名は作れない」で削除そのものが止まっていました。
環境
- Terraform(AWS プロバイダ)
- Amazon RDS(
aws_db_instance) - リージョン: ap-northeast-1(東京)
起きたこと
片付けは terraform destroy 一発のつもりでした。ところが RDS のところで先ほどのエラー。DBSnapshotAlreadyExists という名前のとおり、「aws-study-final-snapshot という識別子のスナップショットがもうあるから、これ以上作れない」という内容でした。
原因:最終スナップショット名が固定で、前回の名残と衝突
私の構成では、RDS の削除時にこういう設定が入っていました(抜粋)。
skip_final_snapshot = var.skip_final_snapshot
final_snapshot_identifier = var.skip_final_snapshot ? null : "${var.project}-final-snapshot"
つまり、最終スナップショットを取る場合(skip_final_snapshot = false)の名前は aws-study-final-snapshot という固定の文字列になります。
RDS は、同じ識別子のスナップショットを2つ作れません。以前にもこの環境を作って壊しており、そのとき作られた aws-study-final-snapshot がスナップショットとして残ったままでした。そこへ再び destroy が「同じ名前で最終スナップショットを作ろう」としたため、名前が衝突して DBSnapshotAlreadyExists で止まった、というわけです。
補足:固定名のスナップショットは「どれが最終版か分かりやすい」利点がある一方、作り直し→壊すを繰り返すと同名衝突しやすいという弱点があるんだな、と今回学びました。
対処:残ったスナップショットを消してから再 destroy
やったことはシンプルで、衝突している古いスナップショットを先に削除してから、もう一度 destroy しました(削除できるのは、対象スナップショットが available 状態のときです)。
# 衝突しているスナップショットを削除
aws rds delete-db-snapshot \
--db-snapshot-identifier aws-study-final-snapshot \
--region ap-northeast-1
# 改めて片付け
terraform destroy
これで RDS も含めて削除が通りました。
destroy の後、スナップショットは残る
もう1つハマったのが、aws_db_instance を destroy しても、スナップショットは消えないという点です。具体的には、
- RDS 削除時に作られた最終スナップショットは、手動スナップショットとして残る
-
Terraform 管理外で作った手動スナップショットも、
aws_db_instanceの destroy では消えない - 一方、
aws_db_snapshotとして Terraform の state で管理しているスナップショットは、state に含まれていれば destroy 対象になり得る
私の場合は前者2つに当たり、destroy 後に確認すると手動スナップショットが残っていました。
aws rds describe-db-snapshots \
--snapshot-type manual \
--query "DBSnapshots[].DBSnapshotIdentifier" \
--output table --region ap-northeast-1
# → aws-study-db-snapshot / aws-study-final-snapshot などが残っている
スナップショットは保管している間ストレージ料金がかかるので、本当に不要なら手で消しました。
aws rds delete-db-snapshot --db-snapshot-identifier aws-study-db-snapshot --region ap-northeast-1
aws rds delete-db-snapshot --db-snapshot-identifier aws-study-final-snapshot --region ap-northeast-1
(消す前に「本当に復元の必要がないか」は必ず確認してください。スナップショットを消すと、その時点のデータには戻せなくなります。)
そして RDS だけ見て安心せず、EBS・Elastic IP・NAT Gateway・CloudWatch Logs・S3 など、ほかに残っている課金要因がないかもあわせて確認しました。「destroy 成功=もう何も課金されない」とは限らないからです。
学び
- RDS の削除は、設定次第で最終スナップショットの作成を伴う。その名前が固定だと、前回の名残と衝突して
DBSnapshotAlreadyExistsで止まることがある。 - 衝突したら、古いスナップショットを
delete-db-snapshotで消してから再 destroy(対象はavailable状態であること)。 -
aws_db_instanceを destroy しても、最終スナップショットや管理外の手動スナップショットは残る。describe-db-snapshotsで確認する(state 管理下のaws_db_snapshotは別)。 - スナップショットは保管中も料金がかかる。不要なら掃除し、RDS 以外の残存リソースも確認して想定外の課金がないか見る。
おわりに
「削除のコマンドが“すでに存在する”で止まる」のは最初すごく混乱しましたが、RDS は消したあともスナップショットという形でデータが残る、という当たり前を実感した一件でした😅 片付けたつもりで料金が残っていないか、最後に一度確認する習慣がつきました🙌
参考
- AWS公式: DB インスタンスの削除(最終スナップショット /
SkipFinalSnapshot/FinalDBSnapshotIdentifierの関係)
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_DeleteInstance.html - Terraform 公式:
aws_db_instance(skip_final_snapshot/final_snapshot_identifier)
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance - AWS公式: DB スナップショットの削除(
delete-db-snapshot)
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_DeleteSnapshot.html - AWS公式: RDS の料金(バックアップ・スナップショットのストレージ)
https://aws.amazon.com/rds/pricing/