はじめに ─ AI に請求書を読ませたら、無駄が次々と見つかった
AWS の月次請求書は、合計額しか見ていない人が大半だと思います。MOOBON でも長らくそうでした。「合計 $X、まあこんなものか」とだけ確認して閉じる、というルーチンです。
ある日、思い立って AI に AWS の請求書を読み込ませて、コスト構造について詳細に議論してみました。すると 「使っているつもりはないのに毎月確実に払い続けていた費用」 が次々と浮かび上がってきました。Cost Explorer の usage type 別ビューを 1 行ずつ目視で追いかけるよりも数倍速く、しかも見落とし無く列挙できたのが収穫でした。
発見した無駄は最終的に 毎月 $310 規模。本記事はそれを いくら払っていたか / なぜそれが無駄だったか / どう取り戻したか の 3 観点で 1 つずつ深掘りした記録です。次のセクションで Phase 別の見取り図を示してから、各施策の詳細に入っていきます。
※ $310 は施策 #1〜#5 / #7 / #8 の合計値です。施策 #6(EC2 を AL2 → AL2023 へ移行 + EBS 縮小、moobon 単体で 追加 -$125 / 月)は 別記事にて単独で詳述しているため、本記事の合計には含めていません。
記事執筆時点(2026-05)では、Amazon Linux 2 → 2023 への載せ替え移行の都合で 旧 EC2 の並行稼働 + 追加 EIP が一時的に立っており、現在のコストは数十ドル / 月単位で水増しされています。移行完了とともに自然減する見込みですが、本記事の数字は「移行 overhead 込み」の保守的な値だとご理解ください。
1. 見直しの 2 段階 ─ 「やってる気」から「見つけた・取り戻した」へ
資格を持っていて、10 年以上使っていて、それでも「やってる気」だった
私自身は AWS Solutions Architect Associate(SAA)を保有し、AWS を 10 年以上使い続けてきた立場です。コスト最適化のポイントは大方押さえているはず ── そう思い込んでいました。
実際、EC2 / RDS / ECS のインスタンスタイプ管理や、Reserved Instance(RI)の購入は計画的に行ってきました。それで 「やることはやっている」 気持ちでいたのが Phase 0 の状態です。
でも請求書は 合計額だけをざっと眺めて閉じる のがルーチン。サービス別 / usage type 別の内訳まで 1 行ずつ追いかけたことはありませんでした。「やっておけば良いことは大体やっている」と思い込んでいた、これが本記事を書くきっかけになった気付きの出発点です。後述しますが、実際にこの思い込みを破ったのは AI に請求データを分析させた瞬間でした。資格を持っていても、10 年以上使っていても、人間が手で請求書を追いかけるだけでは無駄は見えない。
VPC 環境を見直したら、固定費の塊が出てきた
AI に AWS の請求データを読み込ませて指摘させると、まず VPC 周りで「気付かず払っていた無駄」が次々出てきました。Cost Explorer の usage type 別ビューを目視で追いかけても同じ結論には行き着けるはずですが、AI に頼むと 「合算するといくら」「課金構造的に何が無駄」 までセットで指摘してくれるので、判断のスピードが段違いに速かったのが本件のスタートです。
- ALB が 3 本走っていた(クライアントのサービス専用 ALB / EC2 用 ALB / ECS 用 ALB の 3 系統)。 リスナールールで集約すれば 1 本で済む構成だった。ELB 月額 + Public IPv4 で 月 -$57 の無駄。→ 施策 #1 へ
- NAT Gateway を毎月 $107 払って使っていた(時間課金 $45 + データ処理 $62)。ECR pull や OS パッチ、ECS task 起動などのアウトバウンド通信が地味に積み上がっていたためデータ処理量がかさんでいた。EC2 NAT(FCK-NAT)へ置換すると 月 約 $8 へ圧縮できた。月 -$99 の大型削減。→ 施策 #2 へ
- 副産物として WAF が複数本走っていたことに気付いた。ALB 統合に合わせて Web ACL も 1 本に集約。月 -$16。当初の計画には無かった発見。→ 施策 #3 へ
EC2 / ECS / RDS / バックアップ層を意識すると、組み合わせ最適化ができていなかった
Phase 1 で VPC を片付けたら、コンピュート層と保管層にも目が向きました。 Phase 0 でやってきた RI 購入や スペック管理は確かに効いていたのですが、個別最適に留まり、組み合わせて活かせていなかったことが見えてきます。
- RI のカバレッジが穴だらけだった。過去に EC2 → ECS Fargate へ移行した結果、購入していた EC2 RI が余って遊んでいた。本番の安定ワークロードの一部を Fargate → EC2 に戻し、ECS Capacity Provider で RI を活かす構成へ。→ 施策 #8 へ
- ECS タスクに Public IP が振られたまま動いていた(2024-02 から課金開始)。プライベートサブネットへ移し Public IPv4 課金から外した。→ 施策 #4 へ
- Fargate が思ったより高かった(本件で moobon 単体 月 $263)。ステージング系は Fargate Spot で 70% 引き、本番は 施策 #8 と組み合わせて EC2 RI 寄せ、それでも残ったオンデマンド分は Compute Savings Plans で被せる、を検討中。→ 施策 #7 + 今後の課題
- EBS が無自覚に肥大化していた。AL2 → AL2023 移行のタイミングで gp3 化 + 容量ダイエット(100GB → 30GB)。EC2-Other で 月 -$125 / -75% と最大の効果を出した。→ 施策 #6 へ
- ログがバラバラに置かれていた。EBS 上に nginx ログや DB ダンプが堆積していたのを、logrotate / cron 経由で S3 に即時退避する運用に統一。EBS 縮小と組で効いた。→ 詳細は AL2 → AL2023 移行記事(セクション 6)
加えて、上記の流れと並行で CloudWatch Agent のデフォルト設定で発行されていた不要メトリクスの整理(施策 #5)も実施しました。
次のセクション以降では、上記の各施策を「いくら払っていたか / なぜそれが無駄だったか / どう取り戻したか」の 3 観点で 1 個ずつ深掘りします。Phase で読みたい方は、上記リンクから対応する施策にジャンプしてください。
2. ALB 3 つを 1 つに統合(リスナールール 23 本に集約)
何をしたか
サービスごとに分かれていた ALB を 3 本 → 1 本 に統合。ドメイン数は変えず、HTTPS リスナー(443)に 23 個のリスナールールを作成し、ホストヘッダ(Host: example.com)+ パスベース(/api/* 等)で適切なターゲットグループに振り分ける構成にしました。HTTP リスナー(80)は 1 ルールで HTTPS にリダイレクトするだけのシンプルな形です。
なぜ効くのか
ALB は 1 本あたり 約 $16 / 月の固定費 + LCU 課金。3 本動かしていれば固定費だけで $48/月。トラフィックが集約された 1 本でも LCU 課金は同じ規模で済むので、固定費が単純に 1/3 になります。
さらに見落とされがちなのが、2024 年 2 月以降に始まった Public IPv4 課金。ALB はマルチ AZ 配置(本件は 3 AZ)で AZ ごとに Public IPv4 を 1 個ずつ消費するので、ALB 3 本 × 3 AZ = 9 個の Public IPv4(= $32.85/月)が掛かっていました。1 本に集約すると 3 個 = $10.95/月 まで圧縮できるため、VPC バケットに紛れた Public IPv4 課金で -$22/月の隠れ削減が同時に発生します。
つまり施策 #1 の総効果は 「ELB 月額の -$35 / 月」+「Public IPv4 の -$22 / 月」≒ 約 -$57 / 月。Cost Explorer のサービス別ビューだけ見ていると気付きにくいので、Public IPv4 課金の存在は ALB 統合の判断材料として大きな影響を持ちます。
ハマりどころ
- リスナールールの優先度設計:23 ルール並ぶと「より具体的なルールを上に」の原則を厳格に守らないと意図しないバックエンドに流れる。リダイレクト系は最後に集約すると安全。
- ターゲットグループのヘルスチェックパス重複:バックエンドが同じパスを返す設計だと、別サービスへの誤マッピング時にヘルスチェックが通ってしまい気付きにくい。
/healthz等のサービス固有パスにする。 - WAF / アクセスログの引き継ぎ:統合する側の ALB に紐付いていた WAF・ログ設定を新 ALB 側へ移植し忘れると、統合後にコンプラ要件が抜ける。
- DNS 切り替えのタイミング:Route 53 の TTL を事前に短縮(60 秒など)し、切り戻し可能な構成にしてから Alias レコードを切り替える。
Before / After
| 項目 | Before | After |
|---|---|---|
| ALB 数 | 3 本 | 1 本 |
| リスナールール | ALB ごと数本ずつ | 443 に 23 ルール集約 / 80 は HTTPS リダイレクトのみ |
| ALB が消費する Public IPv4 | 9 個(3 ALB × 3 AZ) | 3 個(1 ALB × 3 AZ) |
| ELB 月額(moobon 単体) | $77 | $42 (-$35 / -45%) |
| Public IPv4 月額(ALB 由来) | 9 × $3.65 ≈ $33 | 3 × $3.65 ≈ $11 (-$22 / -67%) |
| 施策 #1 の総削減 | - | 約 -$57 / 月 |
3. NAT Gateway を EC2 NAT(FCK-NAT)に置換
何をしたか
マネージド NAT Gateway を、EC2 ベースの NAT インスタンス(FCK-NAT パターン)に置き換えました。インスタンスは t3a.micro 1 台、Amazon Linux 2023 ベース、Auto Scaling Group(min=max=desired=1) でラップして自動復旧させる構成です。
本番採用にあたっての Launch Template / UserData / IAM ポリシー / ASG 設定の実物、Launch Template を 6 回書き直したリアル、運用上の注意点は 別記事「ECS の outbound IP を固定したい ── fck-nat を本番採用した記録」 に整理しています。本記事ではコスト削減効果の検証に主軸を置きます。
「Auto Scaling」と書きましたが、実態は スケールではなく self-healing。EC2 ヘルスチェックが unhealthy になった瞬間に ASG が同じ起動テンプレートで代わりのインスタンスを立ち上げてくれます。利用者の作業は Private Subnet のルートテーブルに 0.0.0.0/0 → NAT インスタンスの ENI(または インスタンス) を向けるだけ。FCK-NAT の AMI が IP forwarding / NAT 用 iptables / ENI の SourceDestCheck 解除まで全て内蔵で面倒を見てくれるので、サーバ内の OS 設定を手で触る必要はありません。Public IPv4 は EIP を関連付けて固定 IP 化しています。
なぜ効くのか(moobon の実請求で確認)
ap-northeast-1 のマネージド NAT Gateway は 時間課金 $0.045/h × 720h = 約 $32/月 に加えて 処理データ量 $0.045/GB。"カタログ通り" の理屈ではこれだけです。が、moobon の実請求を見るとアウトバウンド通信(ECR pull / OS パッチ / ECS task 起動 / 外部 API 呼び出し 等)で 毎月 1.4 TB 相当が NAT 経由で流れており、データ処理量だけで毎月 $62 を払っていました。
| 課金項目 | 月額(2025-11 実費) |
|---|---|
APN1-NatGateway-Hours(時間課金) | $44.64 |
APN1-NatGateway-Bytes(データ処理) | $62.27 |
| 合計(NAT Gateway 1 個 / 月) | $106.91 |
「固定費 $32 + 処理量数十ドル」程度のつもりが、実際は 月 100 ドル超を 1 個の NAT GW に支払っていました。マネージドだから便利、と漠然と使っているうちに、データ処理量がジワジワ積み上がっていたのが正体です。
一方で t3a.micro + EBS 8GB の NAT EC2 はインスタンス + ストレージで 合計 約 $8 / 月。EC2 アウト課金は AZ 内 / リージョン内の通信は無料で、AZ 外への通信のみ課金される構造なので、トラフィックが大きくても課金構造が軽量です。
ハマりどころ・可用性の話
- 「ダウン = 全リクエストエラー」ではない:NAT EC2 が落ちても 影響を受けるのはサーバから外部への通信(API 呼び出し / OS パッケージ更新 / ECR pull / 外部 SaaS との連携)だけ。ALB → アプリ → DB(RDS / ElastiCache 等の VPC 内リソース)で完結するリクエストには影響しない。 つまり NAT のダウンが即座にユーザー向けレスポンスを壊すかは、システムの構造によって変わる。Web アプリの大半が VPC 内リソースで完結する設計なら、NAT 障害は 「外部依存処理だけ部分的に失敗する」限定的なものに留まる。
- 復旧時間:ASG の self-healing で 2〜4 分。マネージド NAT Gateway の SLA 99.99% に比べれば落ちるが、上記のとおり「全断にはならない」「外部通信が必要な機能だけ一時的に効かなくなる」程度。本番でも要件次第で許容できるケースは多い。
- 設定はルートテーブルだけ:FCK-NAT の AMI 側で IP forwarding / iptables / SourceDestCheck の解除を済ませてくれているので、サーバ内 OS 設定を触る作業は発生しない。利用者は ルートテーブルに
0.0.0.0/0 → NAT 用 ENIを 1 行書くだけ。手動で NAT サーバを Amazon Linux から組む方式と比べて事故が起きにくい。 - ASG で再起動した際の ENI 切替:インスタンスが入れ替わると ENI が変わる。FCK-NAT には起動スクリプトが同梱されており、自身の ENI をルートテーブルに自動で再設定してくれる。起動テンプレートでルートテーブル ID と Tag が正しく渡っているかは事前に確認する。
- 帯域・接続数の上限:
t3a.microは burstable で最大 5 Gbps、conntrack 上限も控えめ。常時高トラフィックや大量同時接続が想定されるワークロードではt3.small以上、もしくは Network 最適化系インスタンスを検討する。 - 監視:CloudWatch で NAT インスタンスの NetworkOut / CPUUtilization、および 「外部 API 呼び出しの成功率」アプリ側メトリクスをアラーム化。マネージドではないので「気付くと外部連携だけ壊れている」を防ぐ。
Before / After
| 項目 | Before | After |
|---|---|---|
| NAT 構成 | Managed NAT Gateway × 1 | EC2 t3a.micro × 1 (FCK-NAT, AL2023 + ASG self-healing) |
| NAT Gateway 月額(moobon 実費, 2025-11) | Hours $44.64 + Bytes $62.27 = $106.91 | ─(廃止) |
| EC2 NAT 月額(t3a.micro + EBS 8GB) | ─ | 約 $8 / 月 |
| 削減額 | - | 約 -$99 / 月(-93%) |
| 可用性 / 障害時の影響 | AWS 管理(SLA 99.99%) | ASG 自動復旧(2-4 分)。ただし全断にはならず、外部通信が必要な処理(API 呼び出し / ECR pull 等)に限定される |
4. WAF 複数本を 1 つに統合
何をしたか(施策 #1 の副産物として実施)
本施策は当初の削減計画には載っていなかった副産物です。施策 #1 で ALB を 3 本 → 1 本に集約した結果、それぞれの ALB に紐付いていた WAF Web ACL も 1 つに統合する自然な流れになりました。Web ACL を 1 本に集約する過程で重複ルールやモード違い(Count / Block の混在)が発見でき、ルール構成の整理も一緒に進められました。統合後の構成は以下の 8 ルール:
| 優先度 | ルール | タイプ |
|---|---|---|
| P0 | AWSManagedRulesLinuxRuleSet | Managed |
| P1 | AWSManagedRulesSQLiRuleSet | Managed |
| P2 | AWSManagedRulesCommonRuleSet | Managed |
| P3 | AWSManagedRulesWordPressRuleSet | Managed |
| P4 | AWSManagedRulesPHPRuleSet | Managed |
| P5 | AWSManagedRulesBotControlRuleSet | Managed |
| P8 | allow-overseas-for-allowed-hosts | Custom Regex |
| P9 | block-from-overseas-countries | Custom And |
なぜ効くのか
WAF Web ACL は 1 本あたり $5/月の基本料金に加え、ルール 1 つあたり $1/月、リクエスト 100 万件あたり $0.60 の課金構造。WAF を複数本動かすと基本料金 × 本数分が固定で乗っていきます。同じ Managed Rule Group を複数 ACL でロードしていれば、それぞれにルール課金が重複発生する非効率も解消されます。
ハマりどころ
- ALB 統合と順番を合わせる:#1 の ALB 統合と並行して進めると、紐付け対象が減るので作業しやすい。
- カスタムルールの優先度:管理ルールグループ(P0-P5)を先に評価し、地域フィルタ系の自社カスタムを後ろに置く構成。逆順だと正常リクエストまで誤ブロックする可能性。
- BotControl は要金額確認:AWSManagedRulesBotControlRuleSet は標準モードで 追加課金 $10/月 + リクエスト課金(他の Managed と単価が違う)。要件によって ON/OFF を判断。
Before / After
| 項目 | Before | After |
|---|---|---|
| Web ACL 数 | 複数本(各 ALB に紐付け) | 1 本(統合 ALB に紐付け) |
| ルール数(統合 ACL) | 重複あり | 8(Managed 6 + Custom 2) |
| WAF 月額(moobon 単体) | $31 | $15 |
| 削減額 | - | -$16 / 月(-52%) |
5. ECS をプライベートサブネットへ(Public IPv4 削減)
何をしたか
ECS タスクをパブリックサブネット + Public IP 直接付与の構成から、プライベートサブネット + NAT(EC2 NAT)経由のアウトバウンドに切り替え。これによりタスクごとに割り当てられていた Public IPv4 を不要にしました。同時に #1 の ALB 統合で削減した分も含めて、Public IPv4 の課金対象アドレス数が大きく減っています。
なぜ効くのか
2024 年 2 月から AWS は すべての Public IPv4 アドレスに $0.005/h(= 約 $3.65/月)を課金するように変更しました。それまで「ENI に Auto-assign Public IP」で気軽に振っていた IP が、すべて課金対象になります。当月(2026-04)の MOOBON では APN1-PublicIPv4:InUseAddress が $97.79(=27 アドレス相当 / 月)、APN1-PublicIPv4:IdleAddress が $5.51。ECS タスク数が 10 でもパブリック配置なら毎月 $36 が「ただ IP を持つだけ」で発生します。
ハマりどころ
- ECR からの pull が NAT 経由になる:プライベートサブネット化により、ECS タスクが ECR からイメージを pull するとき NAT を経由する。EC2 NAT 化(施策 #2)後は転送コスト自体は軽量だが、Fargate のタスク起動時間が NAT 経由の分わずかに伸びる傾向あり。気になる規模なら VPC エンドポイント(Interface 型)を ecr.api / ecr.dkr / s3 / logs / secretsmanager に追加して NAT 経由を回避する手もあるが、本件では未検討(今後対応していく予定の項目に列挙)。
- 外部 API の IP ホワイトリスト(むしろ正解構成になる側面):特に 決済 API(クレジットカード・コンビニ・銀行振込連携 等)では、業務要件として接続元 IP の事前申告・固定化が求められるケースが多い。ここで気付いておきたいのは、ECS Fargate のタスクに割り当てられる Public IP は再起動のたびに変わる動的なもので、そもそもホワイトリスト用途には使えないということ。プライベートサブネット + NAT EIP 経由の構成にすると、外向き通信が NAT の固定 EIP に集約されるため、これを外部に申告すれば固定 IP として登録できるようになる。コスト削減と並行して、ホワイトリスト要件のある外部連携にとっての "正解構成" にも自動的になるのがこの施策のもう一つの効能(ALB 経由のインバウンド API なら従来通り ALB 側の IP)。
Before / After
| 項目 | Before | After |
|---|---|---|
| ECS サービスタスクが消費していた Public IPv4 | 8 個 | 0 個(全タスクが NAT 経由) |
| 削減効果 | 8 個 × $3.65 / 月 ≈ 約 -$29 / 月 | |
USAGE_TYPE を APN1-PublicIPv4:InUseAddress / :IdleAddress でフィルタすれば一発で見える。「気付かないうちに膨れる」典型費目なので半年に 1 回はチェックしたい。6. CloudWatch Agent の不要メトリクス整理
何をしたか
EC2 に CloudWatch Agent を導入したとき、特に深く設定を詰めずにそのまま動かしていたため、1 台あたり 10 個前後のカスタムメトリクスが流れている状態になっていました。実運用で本当にアラーム / 障害解析に使っていたのは mem_used_percent と disk_used_percent の 2 つだけだったので、これだけに絞り込みました。
整理後の moobon の config.json は次の通り。mem と disk のみの最小構成に揃えています(SSM で実機から取得して確認):
{
"agent": {"metrics_collection_interval": 60},
"metrics": {
"append_dimensions": {"InstanceId": "${aws:InstanceId}"},
"metrics_collected": {
"mem": {"measurement": ["mem_used_percent"]},
"disk": {"measurement": ["disk_used_percent"], "resources": ["/"]}
}
}
}なぜ効くのか:1 台 10 個 → 2 個
整理を始めた時点では、初期セットアップで適当に設定した結果、1 台あたり 10 個前後のカスタムメトリクスが流れていた状況でした。これを mem + disk の 2 個に絞り、CPU は EC2 標準メトリクス(無料)で代用、ディスク IO・netstat・swap・プロセス等は使う頻度が低かったため発行を停止しました。
| 状態 | / 台 | 8 台合計 | 月額(USD) |
|---|---|---|---|
| Before(適当に設定) | 10 個 | 80 メトリクス | 約 $24 |
| After(mem + disk のみ) | 2 個 | 16 メトリクス | 約 $5 |
| 削減 | −8 個 / 台、合計 −64 メトリクス | 約 −$19 / 月 | |
絶対額としては 月 -$19 の小規模ですが、CloudWatch カスタムメトリクスは 1 メトリクスあたり $0.30 / 月(最初の 10K まで)で台数に正比例して増える費目。「収集レベルを最小に揃える」運用習慣はフリートが大きくなるほど比例で効くため、初期から徹底する価値があります。
ハマりどころ:なし
この施策に関しては ハマりどころは特にありません。アラームに使っていないカスタムメトリクスは収集する意味がなく、データを取り続けるだけでもリソース(CWAgent の常駐 + ネットワーク + メトリクス課金)を消費しています。使っていないメトリクスは真っ先に削除して問題なし。「将来必要になるかも」で残しても、必要になったタイミングで設定すれば即時に流せます。
7. EC2 を AL2 → AL2023 へ移行 + gp3 + EBS 縮小
本件は単独で詳細記事を書いています。要点は EBS を 100GB gp2 → 30GB gp3 に圧縮、不要バックアップとログを S3 にオフロードして EBS 上の堆積を一掃、AMI スナップショット 10 世代保持時のコスト試算込み。moobon 単体で EC2 - Other が $166 → $41(-$125 / -75%)と、本件の中で最大級の削減幅を出した施策です。
14 サイト・28 WordPress を Amazon Linux 2 → 2023 へ移行した記録Before / After(本件への寄与)
| 項目 | Before | After |
|---|---|---|
| EBS ボリューム | 100GB gp2 | 30GB gp3 |
| EBS 月額(単体) | $12.00 | $2.88 |
| AMI 10 世代スナップショット | $4.68 | $1.44 |
| EC2 - Other 月額(moobon 単体) | $166 | $41(-$125 / -75%) |
8. ステージング環境の ECS を Fargate Spot へ
何をしたか
リリース前検証用の ステージング環境の ECS タスクを Fargate Spot に切り替え。Capacity Provider に FARGATE_SPOT を 100% で指定するか、ベース 0 + ウェイト 1 にして全タスクを Spot で起動するようにしました。
なぜ効くのか
Fargate Spot は通常 Fargate の最大 70% OFF。ap-northeast-1 で 0.25 vCPU / 0.5 GB のタスクなら、通常 Fargate $0.0123/時 → Spot $0.0037/時 程度(時期により変動)。月にすると 1 タスクあたり通常 $9 → Spot $2.7 ぐらい。ステージングを 5 タスクほど常時起動していれば毎月 $30 近く下がる計算です。
ハマりどころ(本件では問題なし)
- 2 分前の中断通知:Spot は AWS の都合で中断され得るが、ECS は自動で再起動。ステージング目的なら全く気にならない(本番では用途による)。
- キャパシティ確保:極端にトラフィックの多いインスタンスタイプを大量に Spot で要求すると、確保できないことがある。最小タスク数を 0 から起動する設計に向いている。
- 本番には推奨しないケース:長時間処理(動画エンコード等)、SLA 99.9% 以上が求められる API。長時間ジョブは中断されると最初から、SLA 系は中断分の SLA 損失が発生する。
本番タスクでも、1 タスクの通常 Fargate より、2 タスクの Fargate Spot を並走させた方が安く・落ちにくい構成になるのでは?と考えています。 単価は
$9 → $2.7 × 2 = $5.4 と安く、片方が中断されてももう片方が継続するので可用性も上がる(ALB のターゲットグループに 2 タスク登録しておけば、中断中でも別タスクへ振り分けられる)。 中断頻度や AZ 分散の検証はこれからですが、要件が許す本番ワークロードでは試す価値がありそうです。9. EC2 Reserved Instance を活かすため Fargate → EC2 化
何をしたか
元々は EC2 で動かしていた本番ワークロードを ECS Fargate に移行した経緯があり、その結果 過去に購入した EC2 Reserved Instance(RI)が余って遊んでしまっているという想定外の事態になっていました。RI は購入済みの固定費なので、使わなくても払い続けることになります。
そこで 余っていた t3a.small の RI に、Fargate で動かしていたタスク(0.25 vCPU の小タスク 3 つ + 1 vCPU のタスク 1 つの計 4 つ)を寄せて ECS on EC2 に移行しました(本番 ECS の Capacity Provider を EC2 起動タイプに切り替え)。RI を使い切れる状態にしただけのつもりでしたが、結果的に 想像以上の削減になりました。
なぜ効くのか:Fargate は vCPU と RAM が別課金
実際にやってみて気付いたのは、Fargate の単価が思っていた以上に高いということ。Fargate は vCPU と RAM が別々に時間課金される料金体系で、ap-northeast-1 のオンデマンド単価は次の通り:
| 課金軸 | 単価(オンデマンド) |
|---|---|
| Fargate vCPU | $0.05056 / vCPU・時間 |
| Fargate メモリ | $0.00553 / GB・時間 |
本件で寄せたのは Fargate タスク合計 4 つ(0.25 vCPU + 0.5 GB の小タスク × 3 と 1 vCPU + 2 GB のタスク × 1)を、t3a.small の RI を 2 台分に分けて ECS on EC2 へ移行する形にしました。試算は次のとおり:
| 構成 | 月額(USD) |
|---|---|
| Fargate(0.25 vCPU + 0.5 GB)× 3 タスク | 約 $34 |
| Fargate(1 vCPU + 2 GB)× 1 タスク | 約 $45 |
| Fargate 合計(Before) | 約 $79 |
t3a.small 3 年 RI × 2 台に集約(After) | 約 $17 |
| 削減効果 | 約 -$62 / 月(-78%) |
ワークロード自体は変わらず、稼働環境を Fargate から 3 年 RI の EC2 に寄せただけで 月 8 割近い削減。「Fargate のマネージド性に追加で払う "運用便利代" が、想像していたより大きく乗っていた」というのが本件で得た最大の学び。RI が余っているなら、Fargate で動かしているタスクを RI に寄せるだけで想像以上に効きます。
副次的な効果として、1 vCPU + 2 GB だったタスクは、t3a.small(2 vCPU + 2 GiB)に載ったことで実効スペックが上がる形になりました。Fargate は要求した vCPU / メモリを そのまま割り当てる 課金モデル、EC2 上の ECS タスクは ホストの空きを使い切れる モデル、というのは料金体系を考えるうえで地味に効いてきます。
ハマりどころ
- ECS Capacity Provider の設計:EC2 を Capacity Provider にする場合、ASG を使ってインスタンスを準備し、ECS と紐付ける必要がある。Fargate のように「タスク数だけ宣言すれば良い」とはいかない。
- ローリングデプロイで EC2 の空きが足りない:タスク要求スペックぴったりの EC2 に寄せると、デプロイ時の新タスク起動分を載せる空きが無くなり、デプロイが詰まる。本件ではデプロイ前に ASG を一時的にスケールアウトして "デプロイ用の空き EC2" を先に立てておく仕掛けを入れて対応した。本来は、大きめの EC2 に対して小さいタスクを複数載せる設計(ホスト 1 台あたりに余白を残す)にしておくのが正解。RI 在庫に合わせた "ピッタリ詰め" は、デプロイ運用の複雑さで返ってくる。
- EC2 のメンテ責任が戻る:OS パッチ、AMI 更新、ECS Agent バージョン管理などの運用工数が発生。Fargate の良さ(マネージド)は手放す。
10. 教訓 ─ やってみて分かったこと
- 2024 年 2 月の Public IPv4 課金は地味に効く。1 IP あたり $3.65 / 月。ALB / NAT / ECS タスク / EIP に散らばっていると、気付かないうちに 2 桁ドル単位で膨らむ。「この場所に本当に Public IP が必要か」を設計時に問う癖をつけたい。
- マネージドの "便利代" は思ったより乗っている。NAT Gateway / Fargate は確かに便利だが、本件では NAT Gateway → FCK-NAT で月 $99、Fargate → EC2(RI)で月 $62 が浮いた。SLA 要件と "便利代" の支払い意志を、ワークロードごとに分けて判断する。社内系・ステージング系はマネージドを外しても痛くない。
- 過去の決定の残骸を片付ける。EC2 → Fargate に移行したのに RI が残っていた、サービスごとに ALB が分散していた、WAF も ALB ごとに別建てになっていた ── 「昔やった移行や立て付けの遺産」が地味な固定費として滞留している。新規最適化より片付けの方が効くことは多い。
- AI を併走させると "勉強しながら実践" ができる。請求書の読み解きから、削減方法の選定、未使用サービスの洗い出し、ハマったときの回避策まで、本件は AI に都度相談しながら進めた。一人では「気付かなかった費目」「触ったことのなかったサービス」も、料金体系・代替手段・ハマりどころをまとめて当たれるので、結果として トータルで学びながら手も動かせたのが、本件で得た一番大きな手応えでした。
11. 今後対応していく予定の項目
記事執筆時点(2026-05)で、続けて取り組む予定の項目を共有します。同じ規模感の AWS 環境で改善を検討されている方のチェックリストとしてもご活用ください。
直近で実施予定の優先項目
AL2023 移行の完了 ─ 並行稼働 EC2 / EIP の撤去
現在は AL2 → AL2023 の載せ替え途中で、旧サーバーと新サーバーを並行稼働させている都合上、EC2 インスタンスと EIP が増えている状態。移行完了後に旧側を停止 → 削除すれば、固定費が 月数十ドル単位で自然減する見込み。記事中の Before/After 数値はこの移行 overhead を含んだ保守的な値です。
ECS Fargate のコスト最適化:Savings Plans vs EC2 RI(ECS on EC2)の更なる適用
施策 #8 では 余っていた RI に対して 4 タスクを寄せた限定的な適用に留めましたが、moobon 単体で見ると Fargate 課金は依然として月 $263 規模(増加分を含めると ECS だけで全体の 1/3)。残りの本番タスクをどう扱うかについて、以下 2 案で比較検討しています。
| 案 | 概要 | 想定削減 | 運用負担 |
|---|---|---|---|
| 案 1 Compute Savings Plans | Fargate / EC2 / Lambda を横断する 1 年または 3 年の Compute SP を購入。コミット額に応じて時間単価が下がる。 | 最大 30〜50%(3y All Upfront 時) | 低(購入のみ。インフラ変更不要) |
| 案 2 EC2 RI + ECS on EC2 | 本番タスクを ECS on EC2 へ寄せ、EC2 Reserved Instance を購入。Spot キャパシティプロバイダと併用。 | 最大 40〜70%(3y, 安定ワークロード) | 中(ASG / Capacity Provider 設計、AMI 更新運用) |
現時点の暫定方針は、「ベースの安定ワークロードは EC2 RI で取り、スパイク部分とジョブ系は Fargate(オンデマンド + Spot)で残す」のハイブリッド。Compute SP は最終的なベース確定後に「残ったオンデマンドを覆う」形で 1 年 No Upfront を被せる構成を検討中です。実施できたら別記事で結果を報告します。
あとがき
本記事の根っこにあるのは、AWS の無駄を省いて、きれいに運用していきましょう、というシンプルなメッセージです。AWS は便利な分、無自覚に使うと固定費が静かに膨らみ続ける仕組みでもあります。料金の無駄を削減することは、日本のデジタル赤字を削減することになり、円安に立ち向かう行動でもあります。
本記事の発端そのものが AI に AWS の請求書を読み込ませて無駄を指摘させたことでした。同じ仕組みを誰でも試せるように、MOOBON では AWS コスト分析ツール を提供しています。自分の環境にどれだけ "見えていない無駄" があるか把握したい方は、一度通してみてください。コスト診断 / 設計レビューのご相談は info@moobon.jp までお気軽にどうぞ。
AL2023 移行 / Compute Savings Plans / RDS RI 等の進捗にあわせて、本記事は随時アップデート予定です。
よくある質問
QNAT Gateway と EC2 NAT(FCK-NAT)で可用性はどう違いますか?
AWS マネージドの NAT Gateway は AZ ごとに冗長化され、可用性 SLA 99.99% が保証されます。一方の EC2 NAT(FCK-NAT を含む)は単一インスタンス構成だと AZ 障害時にダウンするため、Auto Scaling Group とヘルスチェックで自動復旧する構成にして冗長性を確保するのが基本です。トラフィック量とダウンタイム許容値を見て、ミッションクリティカルなワークロードは引き続き NAT Gateway を選ぶ判断もあります。
QPublic IPv4 の課金はいつから始まりましたか?
2024 年 2 月 1 日から、すべての Public IPv4 アドレス 1 個につき $0.005/時間(およそ $3.6/月)が課金されるようになりました。EC2 だけでなく ALB のノード、NAT Gateway、VPC エンドポイントなど Public IP を持つすべてのリソースが対象です。AWS Cost Explorer の「PublicIPv4」フィルタで実態を確認し、削減できそうな箇所を洗い出すのがおすすめです。
QECS Fargate から EC2(ECS on EC2)に戻すメリットは?
EC2 Reserved Instance を保有している場合、その空き容量を ECS タスクで活用することで Fargate のオンデマンド費用を削減できます。本記事の例ではステージング系を Fargate Spot に置き、本番系の一部は EC2 RI 余剰に乗せる構成で月 $25 程度の削減を実現しました。ただし AMI 更新・キャパシティプランニング・スケール特性の差異など運用上の手間は増えるため、どこまで戻すかは慎重に判断が必要です。
QALB を 1 つに統合する際のリスクは?
リスナールール上限(デフォルト 100、サポートリクエストで 200 まで引き上げ可)、SSL 証明書の枚数(1 ALB あたり最大 25)、複数チーム間の責任範囲の分離あたりが主な検討事項です。本記事では 23 ルールに集約しましたが、これ以上増える場合は ALB 分割や CloudFront 経由のパスベースルーティング併用を検討します。
Qコスト削減の作業にどれくらい時間がかかりましたか?
設計から実施まで合計で約 3 ヶ月、稼働日換算で 5 営業日程度です。最も時間がかかったのは段取り(影響範囲の調査・関係者調整・安全な切替時間の確保)で、実作業自体はリソースごとに 1〜数時間ずつでした。月次の請求書を見ながら効果を確認し、効果の薄い施策は早めに撤退判断する運用が大事です。
