こんにちは!クラウドの世界へ足を踏み入れたばかりの皆さん、日々のインフラ構築や運用、本当にお疲れ様です。
AWSやGCPといったパブリッククラウドを使い始めると、可用性を高めるために「マルチAZ(アベイラビリティゾーン)」という言葉を嫌というほど耳にしますよね。「サーバーは複数のAZに分散させましょう」「データベースもマルチAZで!」と、教科書には必ず書いてあります。
でも、実際にシステムを動かして月末の請求書を見たとき、「あれ……? なんか通信費(データ転送料金)が予想より高いぞ?」と冷や汗をかいた経験はありませんか?
その犯人の多くは、実は「NATゲートウェイの配置ミス」にあります。今回は、この厄介なクロスAZ通信コストの罠と、それを華麗に回避するインフラ設計のコツについて、身近な例えを交えながら一歩ずつ優しく紐解いていきましょう!
—
1. そもそも「NATゲートウェイ」ってなに? 身近な例えで理解する
クラウド上のプライベートサブネット(外の世界から直接アクセスできない安全な部屋)にあるサーバーたちが、ソフトウェアのアップデートや外部APIの呼び出しのために、インターネットへお出かけしたいときがあります。
しかし、プライベートな部屋にいるサーバーたちは直接外の世界に出られないため、代理で門番をしてくれる存在が必要です。それが「NAT(Network Address Translation)ゲートウェイ」です。
郵便局の本店に例えてみましょう
想像してみてください。あなたは「AZ-A」という地域にあるお家のリビング(プライベートサブネット)にいます。そこから外の友達に手紙を出したいのですが、直接外には行けません。
そこで、あなたの地域にある「AZ-Aの郵便局(NATゲートウェイ)」まで手紙を持っていき、そこから外の世界へ発送してもらいます。
- 同一AZ内でのやり取り: AZ-Aにあるお家から、AZ-Aにある郵便局を使う(スムーズで追加料金なし!)
- 異なるAZをまたぐやり取り: AZ-Aにあるお家から、わざわざ山を越えて遠くの「AZ-Cにある郵便局」まで手紙を持っていって発送する(時間もコストもかかる!)
クラウドの世界でも全く同じことが起きています。サーバーがいるAZと違うAZにあるNATゲートウェイへ通信を飛ばすと、クラウド事業者から「AZ間データ転送料金」という名の通行料をしっかり請求されてしまうのです。
—
2. 恐怖の「クロスAZ通信コスト」が発生するメカニズム
マルチAZ構成を組むとき、「とりあえずコスト削減のために、NATゲートウェイは1つだけ作って、すべてのAZのサーバーからそこに向かわせよう」と考える初学者は少なくありません(私も昔やりました!)。
しかし、これが大きな落とし穴です。
罠だらけの「NATゲートウェイ1台集中構成」
例えば、AZ-A、AZ-B、AZ-Cの3つのAZにサーバーを配置し、NATゲートウェイをAZ-Aに1台だけ置いたとします。
1. AZ-Bのサーバーがインターネットへ通信したい!
2. ルーティング設定に従い、AZ-AにあるNATゲートウェイへパケットを飛ばす。
3. この瞬間、AZ-BからAZ-Aへの「AZ間データ転送」が発生する。
4. 月末に「AZ間をまたいだ通信量が多すぎます」という理由で、高額な請求書が届く。
システムの規模が大きくなり、外部APIとの通信やファイルのダウンロード・アップロードが増えれば増えるほど、このクロスAZの通行料は雪だるま式に膨れ上がっていきます。「動いているのに、なぜかお金がかかる」というクラウドアルアルの正体はこれなんです。
—
3. 解決策:すべてのAZにNATゲートウェイを配置せよ!
このコストの幽霊を退治する特効薬は非常にシンプルです。それは、「サーバーがあるすべてのAZに、それぞれNATゲートウェイを置く(マルチAZ配置)」という原則を守ることです。
郵便局の「各街への支店設置」作戦
先ほどの例えに戻りましょう。AZ-A、AZ-B、AZ-Cのすべてのお家から遠くの郵便局まで行かせるのではなく、それぞれの街(AZ)に専用の郵便局を1つずつ建ててあげます。
- AZ-Aのサーバーは、AZ-AのNATゲートウェイを使う。
- AZ-Bのサーバーは、AZ-BのNATゲートウェイを使う。
- AZ-Cのサーバーは、AZ-CのNATゲートウェイを使う。
これで、通信は常に同じAZ内で完結し、余計なAZ間データ転送料金を綺麗にゼロに(あるいは最小限に)抑えることができます!
—
4. 実践!AWS(Terraform)でのコスト最適化構成の書き方
理屈が分かったところで、実際にインフラをコードで構築する際のサンプルを見てみましょう。今回は、インフラ界の共通言語であるTerraformを使って、各AZに綺麗にNATゲートウェイを配置する設定を覗いてみます。
# ----------------------------------------------------
# 1. 各AZ(可用性ゾーン)ごとのパブリックサブネットとNATゲートウェイの定義
# ----------------------------------------------------
# AZ-1a 用のパブリックサブネット
resource "aws_subnet" "public_az_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-1a" # 東京リージョン 1a
tags = {
Name = "public-subnet-az-a"
}
}
# AZ-1c 用のパブリックサブネット
resource "aws_subnet" "public_az_c" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "ap-northeast-1c" # 東京リージョン 1c
tags = {
Name = "public-subnet-az-c"
}
}
# AZ-1a 用のEIP(固定IP)
resource "aws_eip" "nat_az_a" {
domain = "vpc"
tags = {
Name = "nat-eip-az-a"
}
}
# AZ-1c 用のEIP(固定IP)
resource "aws_eip" "nat_az_c" {
domain = "vpc"
tags = {
Name = "nat-eip-az-c"
}
}
# 【重要】AZ-1a に配置するNATゲートウェイ
resource "aws_nat_gateway" "nat_a" {
allocation_id = aws_eip.nat_az_a.id
subnet_id = aws_subnet.public_az_a.id
tags = {
Name = "nat-gw-az-a"
}
}
# 【重要】AZ-1c に配置するNATゲートウェイ(AZごとの分散配置!)
resource "aws_nat_gateway" "nat_c" {
allocation_id = aws_eip.nat_az_c.id
subnet_id = aws_subnet.public_az_c.id
tags = {
Name = "nat-gw-az-c"
}
}
# ----------------------------------------------------
# 2. プライベートサブネットから各AZのNATへ向けるルートテーブルの定義
# ----------------------------------------------------
# AZ-1a のプライベートサブネット用ルートテーブル
resource "aws_route_table" "private_az_a" {
vpc_id = aws_vpc.main.id
# AZ-1a のサーバーからの外部通信は、必ず同じAZ-1aにあるNATゲートウェイへ流す!
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_a.id
}
tags = {
Name = "private-rt-az-a"
}
}
# AZ-1c のプライベートサブネット用ルートテーブル
resource "aws_route_table" "private_az_c" {
vpc_id = aws_vpc.main.id
# AZ-1c のサーバーからの外部通信は、必ず同じAZ-1cにあるNATゲートウェイへ流す!
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.nat_c.id
}
tags = {
Name = "private-rt-az-c"
}
}
このコードのポイントは、aws_route_table の中で、「自分のいるAZと同じ場所にあるNATゲートウェイのID(nat_gateway_id)」を指し示している点です。
これにより、パケットが余計な山(AZ)を越えることなく、最短距離でインターネットへ飛び出していく美しいルーティングが完成します。
—
5. 「でも、NATゲートウェイの台数が増えると固定費が上がるのでは?」という疑問
ここで鋭い読者の皆さんなら、こう気付くはずです。
「おいおい、NATゲートウェイって1台あたりにもう稼働費(時間あたりの料金)がかかるよね? 各AZに置いたら、固定費が爆上がりするんじゃないの?」
その通り!ここはインフラ設計のとても悩ましいトレードオフ(ジレンマ)です。
- パターンA:NATゲートウェイを1台にする
- 固定費:安く済む(1台分の稼働費)
- 変動費(通信費):クロスAZのデータ転送料金で月末に爆発する可能性がある
- パターンB:すべてのAZにNATゲートウェイを置く
- 固定費:AZの数だけ高くなる(例:3AZなら3台分の稼働費)
- 変動費(通信費):クロスAZ料金がゼロになり、予測しやすい
現場で使えるSREの判断基準
一般的に、トラフィック(通信量)が少ない開発環境や検証環境であれば、コスト削減のために「NATゲートウェイ1台構成」や「VPCエンドポイントの活用」で逃げるのも一つの手です。
しかし、本番環境(プロダクション環境)で、外部との通信量(API連携やログ送信、S3との大量データやり取りなど)が多いシステムであれば、迷わず「全AZ配置(パターンB)」を選ぶべきです。
なぜなら、トラフィックが増えれば増えるほど、クロスAZのデータ転送料金はNATゲートウェイの固定費を遥かに超えて高額になるからです。
さらに言えば、もし1つのAZが障害でダウンしたとき、別AZのNATゲートウェイに頼る構成にしていると、そのAZが復旧するまで外部通信が全滅するリスク(可用性の低下)も抱えることになります。コストと可用性の両面から見ても、基本は「マルチAZに各1台」がベストプラクティスです。
—
まとめ
今回は、クロスAZ通信コストの最適化とNATゲートウェイの配置パターンについて解説しました。
1. クロスAZ通信の罠: 異なるAZをまたぐ通信には、目に見えないデータ転送料金(通行料)が発生する。
2. 原因: NATゲートウェイを1箇所に集中させると、他のAZからの通信ですぐにコストが膨れ上がる。
3. 解決策: 基本はサーバーがあるすべてのAZにNATゲートウェイを配置し、通信を同じAZ内で完結させる。
4. トレードオフ: システムの規模や通信量に合わせて、固定費と変動費のバランスを冷静に見極める。
インフラやネットワークの世界は、一見難しそうに見えても、今回のように「郵便配達」や「道路の最短ルート」に置き換えてみると、とてもスッキリ理解できるようになります。
「動けばいいや」から一歩進んで、「お財布にも優しく、災害にも強い美しいネットワーク」をデザインできるエンジニアを目指して、一緒に一歩ずつ進んでいきましょう!
それでは、また次回の技術解説でお会いしましょう。SREチームの主筆ライターより、愛を込めて!
コメント