メインコンテンツまでスキップ

課金構造の地図と安全な終わり方: コストの全体像とdestroy手順

前章で、Tasukuのインフラはmodules/ + envs/dev,prodという複数環境を扱える構成に育ちました。この最終章では、視点を変えて2つのことをします。1つは、各章に散らばっていたコストの話を1枚の地図に集約すること。もう1つは、この連載を通じて作ってきた学習用インフラを、安全に終わらせる手順を示すことです。最後に、この連載がスコープ外に置いた事項を、次の一歩として整理します。

12.1. 課金構造の地図

この連載は、第1章以来「料金の絶対額は書かず、課金ディメンションと相対比較のみを示し、詳細は公式料金ページを参照する」という方針を貫いてきました。個々のリソースのコストへの注意は各章の:::warningで触れていますが、全体を俯瞰する地図はまだ書いていません。ここで1枚にまとめます。

リソース課金ディメンション既出章
NAT Gateway稼働時間 + 処理データ量第4章
Application Load Balancer稼働時間 + LCU (リクエスト量等に応じた単位)第6章
Route 53ホストゾーン月額固定第7章
ACM証明書なし (ALB等への統合利用は無料)第7章
ECS Fargate (web/api)vCPU・メモリの稼働時間、Auto Scalingでタスク数に応じて変動第8章第10章
RDS (Multi-AZ)インスタンス稼働時間 (Multi-AZは2台分) + ストレージ第9章
S3 (3バケット)ストレージ量 + バージョニングによる旧バージョン保持分第5章
S3 Gatewayエンドポイントなし (VPCエンドポイントとしては無料)第5章
ECRリポジトリ保存イメージのストレージ量第8章
CloudWatch Logsログの取り込み量 + 保持期間分のストレージ第8章
Secrets Managerシークレット数 + API呼び出し回数第9章第10章

Fargate・ECR・CloudWatch Logs・Secrets Managerは、個々の章では設定の説明が中心で、明示的なコスト注意はしていませんでした。ここで初めて課金ディメンションとして言及します。ACM証明書とS3 Gatewayエンドポイントは、対比のために「無料」の行として並べています。無料であることが常に自明とは限らないため、他の有料リソースと並べて確認できるようにする狙いです。

12.2. 削減定石

第11章11.5節のenv差分は、そのままdev環境のコスト削減にもなっています。RDSのmulti_az = falseはインスタンス1台分の課金で済み、Auto Scalingのmin_capacity = 1は常時稼働するタスクを最小限にします。ここでは、それに加えられる削減定石をいくつか示します。

RDSの一時停止です。使わない期間はRDSインスタンスを止められます。停止は最大7日間有効で、7日を過ぎると自動的に再起動します。1 ただし、停止中も止まらない課金がある点に注意してください。プロビジョニングしたストレージ (Provisioned IOPSを含む) と、バックアップストレージの課金は、停止中も継続します。2 完全に無課金になるのはインスタンスの稼働時間分だけです。この機能はAurora MySQL・Aurora PostgreSQL・RDS Customには適用されません。3 Tasukuは通常のPostgreSQL (Auroraでない) のため、この制約には該当せず利用できます。

aws rds stop-db-instance --db-instance-identifier tasuku-dev-db

NAT Gatewayの構成見直しは、削減定石として挙げきれません。第4章4.5節では、単一のNAT Gatewayで複数のアベイラビリティゾーンをカバーする「Regional NAT Gateway」というモードに触れました。そこでは「コードの見た目が1個になることと、実際の課金がAZごとに2個用意する構成より安くなることは別の話で、後者は確認できていない」と留保していました。4 このモードが実在しavailability_mode = "regional"を指定するだけで使え、5 ap-northeast-1でも利用可能であること6は、今回のfact-checkで確認できました。しかし、第4章が留保した核心の疑問、すなわち「実際に課金がAZごとに2個用意する構成より安くなるか」は、依然として確認できていません。Regional NAT Gatewayも実際にはアベイラビリティゾーンごとに帯域を確保する動作をしており、4 見た目の個数がコストに単純に比例するとは限らないためです。この選択肢はここでも採用を推奨せず、コード変更も行いません。

Auto Scalingの最小値は、すでに第11章のenv差分でdev=1に設定済みです。負荷テストなど一時的に高い性能が必要な場面以外は、この値を上げる理由はありません。

これらはすべて、絶対額でなく「何を減らせば何が減るか」という構造の話です。実際の削減額は、公式の料金ページとご自身の利用量に照らして確認してください。

12.3. 安全なdestroy

この節が対象にするのは、第11章で作ったenvs/devenvs/prodです (旧main/の後始末は前章11.8節で扱い済みです)。素朴にterraform destroyを実行すると、いくつかのリソースが削除を拒否します。壊す前に確認すべきことを棚卸しします。

リソース保護設定destroy前に必要な作業
RDSインスタンスdeletion_protection (prod環境はtrue)deletion_protection = falseに変更して再applyしてから destroy する
S3バケット (添付・ALBログ)force_destroy未設定バケットを空にするか、一時的にforce_destroy = trueを設定して再apply
ECRリポジトリforce_delete未設定イメージを削除するか、一時的にforce_delete = trueを設定して再apply
Route 53ホストゾーンデフォルトのSOA・NSレコード以外は削除必須apex・apiのAliasレコード、ACM検証用レコードを削除する (ホストゾーン自体を削除すればSOA・NSは自動的に削除される) 7
ACM証明書リスナーからの参照443番リスナーの依存はTerraformの依存グラフが自動的に解決する (追加作業は不要)

bootstrap/が作るtfstateバケットは、最後にdestroyします。先に消してしまうと、envs/devenvs/prodのbackendが参照するstateの置き場自体が失われます。第5章5.3節の「バケットがないとbackendを設定できない、backendがないとバケットを作るstateを置けない」という鶏と卵の関係が、destroy時には逆向きに現れる形です。このバケットも上表の添付・ALBログバケットと同様にforce_destroyを設定していないため、destroy前にバケットを空にするか、一時的にforce_destroy = trueを設定して再applyする必要があります。

前章11.6節で触れたmovedブロックとの関係も整理しておきます。movedは既存のリソースを壊さずに新しいアドレスへ付け替えるための工夫でした。destroyは逆に、意図してリソースを壊す操作です。目的は正反対ですが、どちらも「今あるリソースの状態を正確に把握したうえで、Terraformの操作を組み立てる」という点は共通しています。

12.4. 次の一歩

この連載でスコープ外に置いた事項のうち、続けて手を付けやすいものを挙げます。

第9章9.4節で、Fargateは第10章のAuto Scalingでタスクの数こそ動的に調整するもののcpu/memoryの値自体は見直されず、RDSのインスタンスクラス (db.t4g.micro) も同様に見直す章がこの連載になかったことに触れました。この問いへの答えは、「インスタンスサイジングの見直しは運用フェーズの課題」というものです。CloudWatchのメトリクス (CPU使用率、空きメモリ、接続数など) を監視し、実際の負荷傾向が見えてから見直すのが実務的な順序です。構築時点で先回りしてサイズを変える理由は、まだありません。

他にも、次のような発展先があります。

  • CI/CDパイプライン化: 第11章11.2節のデプロイ標準手順を、GitHub Actions等で自動化する
  • CloudFront: 第1章でスコープ外とした、ALBの手前にCDNを置く構成
  • マルチリージョン・DR: 単一リージョン構成から、災害復旧を見据えた複数リージョン展開へ
  • IAM permissions boundary: 第3章3.6節で留保した、Terraform実行者の自己権限昇格リスクへの構造的対策

本章のまとめ

  • 各章に散在していたコストの話を、リソース×課金ディメンションの1枚の表にまとめました。Fargate・ECR・CloudWatch Logs・Secrets Managerは、この章で初めて課金ディメンションとして言及しました
  • 削減定石として、RDSの一時停止 (ストレージ課金は継続する点に注意) とAuto Scaling最小値の2つを示しました。Regional NAT Gatewayは選択肢として存在は確認できましたが、第4章が留保したコスト削減効果は今回も解消できず、採用は見送りました
  • envs/devenvs/prodを安全にdestroyする手順を、RDS・S3・ECR・Route 53のリソース別に整理しました。tfstateバケットは最後にdestroyします
  • 第9章で留保したRDSインスタンスサイジングの非対称性を、運用フェーズでの見直し事項として回収しました
  • CI/CD・CloudFront・マルチリージョン・permissions boundaryを、この連載のスコープ外に置いた次の一歩として挙げました

この連載は、VPCからRDS・ECSサービスまでの構築、環境分離、そして安全な終わらせ方までを扱いました。ここから先は、実際のTasukuの機能開発や、運用の中で見えてくる課題に応じて、必要な箇所を深掘りしていくことになります。

次に読む

Footnotes

  1. 出典: Stopping an Amazon RDS DB instance temporarily。停止は最大7日間で、7日を超えると自動的に再起動するとしています。

  2. 出典: 同上。停止中もプロビジョニングストレージとバックアップストレージの課金は継続するとしています。

  3. 出典: StopDBInstance API Reference。RDS Custom・Aurora MySQL・Aurora PostgreSQLには適用されないとしています。

  4. 出典: 第4章4.5節、およびIntroducing Amazon VPC Regional NAT Gateway。単一のNAT Gatewayが複数のアベイラビリティゾーンを自動的にカバーする一方、アベイラビリティゾーンごとに帯域を確保する動作をしており、実際の課金がAZごとに2個用意する構成より安くなるかは第4章時点で確認できておらず、今回のfact-checkでも解消していません。 2

  5. 出典: terraform MCP (hashicorp/aws provider v6.53.0、aws_nat_gateway)。availability_mode = "regional"を指定しavailability_zone_addressを省略すると、ENI検出時に自動的にAZ・EIPを拡張するauto modeになるとしています。

  6. 出典: AWS NAT Gateway now supports regional availability (2025年11月のAWS公式アナウンス)。AWS GovCloud (US) リージョンと中国リージョンを除く全ての商用AWSリージョンで利用可能だとしています。

  7. 出典: DeleteHostedZone API Reference。ホストゾーンはデフォルトのSOA・NSレコードのみを含む状態でないと削除できず、それ以外のレコードは事前に削除が必要だとしています。