💰

【AWSコスト最適化】マルチアカウントでの Route 53 集約

2024/04/10に公開

はじめに

こんにちは、シンプルフォームでインフラエンジニアをやっている入江 純 (@jirtosterone) です。

シンプルフォームでは、プロダクト・環境ごとにアカウントを分けるマルチアカウントアーキテクチャを採用しています。マルチアカウントアーキテクチャは本番環境や検証環境を明確に分けられるため開発上安全であるとともに、アクセス権も分離しやすくセキュリティ的にも有用な構成です。

https://aws.amazon.com/jp/blogs/news/best-practices-for-organizational-units-with-aws-organizations/

一方で、リソースが倍々ゲームで増えていくためコストも倍々で増えていってしまい、社内でもコスト最適化が叫ばれていました。

そこで本記事では、AWS の DNS サービスである Route 53、Route 53 Resolver について、コスト最適化を実践した方法についてご紹介します。

対象読者

  • DNS の概念を理解されている方
  • Route 53 Resolver の基礎を理解されている方
  • マルチアカウントアーキテクチャのコスト最適化に悩まれている方

Route 53 Resolver について詳しく知りたい方は Black Belt の資料が分かりやすいので、そちらを参照することをオススメします。

https://aws.amazon.com/jp/blogs/news/webinar-bb-amazon-route-53-resolver-2019/

結論

時間が無い方のために結論から。

  • 複数のアカウントで Route 53 プライベートホストゾーンを立てており、相互に名前解決できるようにリゾルバーエンドポイント (Inbound/Outbound) をデプロイしていたが、それだけでコストが $3,000/月 を超えていた。
  • アーキテクチャを見直してリゾルバーエンドポイント (Inbound/Outbound) を半分にしつつ、複数のプライベートホストゾーンを一つの VPC に関連付けして従来通り相互に名前解決できるようにした。
  • 38 あったリゾルバーエンドポイントを 16 に減らし、約 $1,700/月 の削減ができた。

以下では、コスト最適化の考え方やアーキテクチャについてご紹介します。

背景

繰り返しになりますが、シンプルフォームではプロダクト・環境ごとにアカウントを分けるマルチアカウントアーキテクチャを採用しており、各アカウントでアプリ・サービスが完結するようにしています。

そのため、プロダクトによって違いますが、以下のようなリソースを各アカウントに立てて運用しています。

  • VPC などのネットワーク
  • 名前解決するための Route 53 (プライベートホストゾーン), Cloud Map
  • ECS, Lambda などのコンピューティング
  • RDS, Neptune などのデータベース

1 アカウント内ですべて完結するのが理想ですが、どうしてもアカウントを跨いで通信が必要なケースが出てきます。

  • プロダクト A からプロダクト B の情報を参照したい。
  • エンジニアが VPC 内リソースにアクセスするために VPN 接続するとき、各環境にシームレスに接続したい。

そのため、任意のアカウント、VPN 接続元から各アカウントの VPC へ通信できるように Transit Gateway でネットワークを接続するとともに、Route 53 Resolver を利用して、相互に名前解決できるようにしていました。

※Transit Gateway について詳しく知りたい方はこちら。

https://aws.amazon.com/jp/blogs/news/webinar-bb-aws-transit-gateway-2019/

Before

アーキテクチャ

アカウント跨ぎの名前解決を実現するため、各アカウントの VPC に Route 53 のリゾルバーエンドポイントをデプロイしていました。リゾルバーエンドポイントは、インバウンド/アウトバウンドの 2 種類、また AZ 毎に必要であるため 3AZ 構成としている場合は単純計算で 1VPC あたり 6 個のリゾルバーエンドポイントが必要 となります。

名前解決に限定してアーキテクチャを単純化すると下図のような構成になります (実際は少し違いますが単純化のためにデフォルメしています)。プロダクトアカウントとは別に、共有リソースを扱う shared-service アカウント を立てています。開発者が VPN 接続する時は、この shared-service に接続して各プロダクトアカウントの VPC に接続できるようにしています。

architecture_before

コスト

このような構成により、リゾルバーエンドポイントは計 38 個存在しており、コストは以下のように推移していました。

cost_before

なんと、リゾルバーエンドポイントの時間料金だけで $3,400/月 も費やしてしまっています... いくらマルチアカウントアーキテクチャが良いとは言え、さすがにこれは勿体ない...

削減案の検討

コスト最適化の方法はいくつか考えられ、コスト削減効果・構成のシンプルさの観点で比較しました。構成のシンプルさを挙げた理由は、シンプルでないと運用が煩雑になるだけでなく、障害発生時の調査が難航したり拡張しづらくなったりすることで長期的にコスト増大の要因となるからです。

# 削減案 特徴 コスト削減効果 構成のシンプルさ
1 各アカウントの VPC にリゾルバーエンドポイント (インバウンド/アウトバウンド) を作成して、それぞれのホストゾーンに対して名前解決を行う。 要は Before のまま (得られない) (シンプルかつ単純)
2 各アカウントのプライベートホストゾーンを shared-service の VPC に関連付けて、shared-service ですべての名前解決を行う。 shared-service のアウトバウンドエンドポイント、プロダクトアカウントのインバウンドエンドポイントが削減できる (リゾルバーエンドポイントを半分にできる) (およそ半減できる) (プライベートホストゾーンの関連付けがやや手間であるが許容範囲)
3 各アカウントの VPC に各アカウントのプライベートホストゾーンを関連付けて名前解決を行う。 リゾルバーエンドポイントをゼロにできる (リゾルバーエンドポイント分の料金をゼロにできる) (たすき掛けの関連付け設定が必要となりメンテナンス性が悪い)

比較した中で、コスト削減効果と構成のシンプルさのバランスが良い 2 を採用することにしました。

なお、上記以外の案としてプライベートホストゾーンを 1 つに集約することも考えられますが、可能な限りアカウント内でアプリ・サービスを完結させる、プロダクト・環境間の対称性を確保する観点により、検討からは除外しています。

After

アーキテクチャ

前述の案 2 を実現するためのアーキテクチャを示します。

  • 各アカウントのプライベートホストゾーンを shared-service の VPC に関連付ける
  • 各アカウントのフォワーダー先を shared-service に向ける

architecture_after

実装

Terraform での実装について示します。設定内容は以下の 3 つです。

  1. (プロダクトアカウント) プライベートホストゾーンの関連付け先 VPC を承認
  2. (shared-service アカウント) VPC にプロダクトアカウントのプライベートホストゾーンを関連付け
  3. (すべてのアカウント) 不要なリゾルバーエンドポイントを削除

1, 2 では プライベートホストゾーン × VPC の数だけ設定が必要 となるため、関連付けする VPC とプライベートホストゾーンが多い場合は StackSets での一括設定等を検討した方が良いと思います。

1. (プロダクトアカウント) プライベートホストゾーンの関連付け先 VPC を承認

プロダクトアカウントで任意の VPC ID からの関連付け要求を承認するための設定を行います。

main.tf
# Route 53 プライベートホストゾーン
resource "aws_route53_zone" "example_com" {
  ...
}

# variable で指定した VPC ID への関連付けを承認するための設定
# 複数指定できるように for_each で設定
resource "aws_route53_vpc_association_authorization" "default" {
  for_each = var.associate_vpc_ids

  zone_id = aws_route53_zone.example_com.zone_id
  vpc_id  = each.value
}

2. (shared-service アカウント) VPC にプロダクトアカウントのプライベートホストゾーンを関連付け

shared-service アカウントで自アカウント内の VPC とプロダクトアカウントとの関連付け設定を行います。

main.tf
# Route 53 プライベートホストゾーンの関連付けを設定
# プロダクトアカウントの VPC ID を variable で指定する
# 複数指定できるように for_each で設定
resource "aws_route53_zone_association" "default" {
  for_each = var.associate_zone_ids

  zone_id = each.value
  vpc_id  = var.network.vpc_id
}

3. (すべてのアカウント) 不要なリゾルバーエンドポイントを削除

削除するだけなので実装内容は割愛しますが、最後に以下のリゾルバーエンドポイントを削除して完了です。

  • (プロダクトアカウント) リゾルバーエンドポイント (インバウンド) を削除
  • (shared-service アカウント) リゾルバーエンドポイント (アウトバウンド) を削除

コスト

これら構成変更により、リゾルバーエンドポイントを半分に減らし、コストも概ね半減することができました。変更前に比べ、約 $1,700/月 のコスト削減に成功です!!!

cost_after

さいごに

いかがだったでしょうか。本記事がマルチアカウントアーキテクチャのコスト最適化に悩まれている方の一助になれば幸いです。

本記事における検討には、以下サイトを参考にさせていただきました。
この場を借りて感謝申し上げます。

https://devlog.arksystems.co.jp/2022/01/13/16394/

SimpleForm Tech Blog

Discussion