はじめに
CD パイプラインを通して terraform apply を回したら、VPC や ALB は問題なく作られたのに、Secrets Manager の secret 作成だけがエラーで止まりました。メッセージは「同じ名前の secret が、すでに削除予約されている」。
前回ちゃんと terraform destroy したはずなのに、なぜ「すでにある」と言われるのか。最初は意味が分かりませんでした。
先に結論:Secrets Manager は secret を削除しても、既定では一定期間“復旧待ち”の状態が残ります。その間は同じ名前で新しい secret を作れません。これが新規 apply を弾いていました。
環境
- Terraform(AWS プロバイダ)
- AWS Secrets Manager(
aws_secretsmanager_secret) - 実行は GitHub Actions の CD(terraform apply)
- リージョン: ap-northeast-1(東京)
症状
apply の途中、こんなエラーで停止しました。
Error: creating Secrets Manager Secret (aws-study-db-credentials): operation error
Secrets Manager: CreateSecret, https response error StatusCode: 400,
InvalidRequestException: You can't create this secret because a secret with this
name is already scheduled for deletion.
scheduled for deletion——「削除予約済み」です。
切り分け:どこで止まったか
まず CI の失敗箇所を特定しました。
gh run view --log-failed
これで「VPC・ALB の作成までは成功し、secret の作成で止まっている」と分かりました。ネットワークやロールを疑う前に、エラー文が CreateSecret を名指ししていたので、設計ではなく secret の名前まわりだと当たりがつきました。
原因:削除しても、しばらくは同名で作れない
Secrets Manager は、secret を削除するとき**すぐには消さず、既定で復旧猶予期間(30日。7〜30日で設定可)**を設けます。これは「うっかり消しても戻せる」ための安全機能で、その間 secret は「削除予約(復旧待ち)」状態になります。
そして復旧待ち状態の secret が残っている間は、同じ名前で新しい secret を作成できません。前回の terraform destroy で消したつもりの aws-study-db-credentials が復旧待ちのまま残っていて、今回の apply が「同名は作れない」で弾かれた、というわけでした。「destroy したから同名はもう作れる」という思い込みが原因です。
解決:いまの予約を解放し、再発を防ぐ
1. 復旧待ちの secret を完全削除する(手動)
まず、復旧待ちの secret を復旧猶予なしで完全削除して、名前を解放しました(削除系の操作なので、CI ではなく手元のターミナルで実行)。
aws secretsmanager delete-secret \
--secret-id aws-study-db-credentials \
--force-delete-without-recovery \
--region ap-northeast-1
削除されたかの確認には注意が要ります。list-secrets は削除予約中の secret を既定では一覧に出しません。状態を見たいときは --include-planned-deletion を付けます。
aws secretsmanager list-secrets \
--include-planned-deletion \
--region ap-northeast-1 \
--query "SecretList[?Name=='aws-study-db-credentials']"
# 一覧から消えていれば削除処理は進んでいる
注意点が2つ。
--force-delete-without-recoveryは文字どおり復旧できない完全削除なので、本番の secret では使わないこと。そして即時削除も非同期で進むため、削除直後に同名で作り直すと、まだ消えきっておらず弾かれることがあります。その場合は少し待つ/リトライが必要です。
2. 再発させない(Terraform)
使い捨ての検証環境では、destroy のたびに復旧待ちが残ると毎回ここで詰まります。そこで、destroy 時に復旧猶予を設けない設定にしました。
resource "aws_secretsmanager_secret" "db" {
name = "${var.project}-db-credentials"
recovery_window_in_days = 0 # 0 = 復旧待ちを設けずに削除(学習・使い捨て環境向き)
}
recovery_window_in_days = 0 にすると、復旧待ち期間なしで削除されます。ただし実際の完全削除は非同期なので、「destroy 直後に必ず同名で作れる」とは限りません。直後の再作成では短い待機やリトライを見込んでおくと安全でした。
教訓
- Secrets Manager は 削除しても、しばらく同名で作り直せない(既定で復旧猶予が残る)。
scheduled for deletionはこのサイン。 - 復旧待ちは
delete-secret --force-delete-without-recoveryで解放できる(復旧不可なので本番では慎重に)。状態確認はlist-secrets --include-planned-deletion。[]だけでは判断しない。 - 即時削除も非同期。直後の再作成は待機/リトライを見込む。
- 作り直し前提の学習・使い捨て環境は
recovery_window_in_days = 0。本番は、誤削除の復旧要件・運用手順・secret の重要度を踏まえて復旧ウィンドウを決める。 - CI で止まったら、まず
gh run view --log-failedで「どのリソースで落ちたか」を見ると当たりが早い。
おわりに
「消したのに、まだ同名で作れない」というのは、安全機能だと分かれば納得でしたが、最初はかなり戸惑いました😅 便利さ(復旧できる)と使い勝手(すぐ作り直せる)はトレードオフなんだな、と実感した一件です。同じところで詰まった人の参考になれば嬉しいです🙌
参考
- AWS公式: Secret の削除と復元(復旧ウィンドウ・削除予約)
https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_delete-restore-secret.html - AWS公式:
delete-secret(--force-delete-without-recoveryと再作成時の注意)
https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/delete-secret.html - Terraform 公式:
aws_secretsmanager_secret(recovery_window_in_days)
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret