【入門編】 クロスAZ(アベイラビリティゾーン)NATゲートウェイ配置時のデータ転送コストと高可用性設計 – クラウド&コンテナネットワーク実践ガイド

こんにちは!クラウドの海を日々漂いながら、パケットの行く末を見守るSREのテックリードです。

「クラウドは使った分だけ払えばいいから安上がり」なんて言葉を信じて構築を始めたものの、月末の請求書を見て「えっ、この『Data Transfer』って何!? なんでこんなに高いの?」と椅子から転げ落ちそうになった経験、ありませんか?

実は、AWSやGCPといったメガクラウドの世界には、「アベイラビリティゾーン(AZ)という境界線をまたぐ時に発生する通行料」という、初心者泣かせの隠れたコストが存在します。

今日は、VPC設計の要となる「NATゲートウェイ」をテーマに、お財布に優しく、かつ障害に強いネットワークをどう作るべきか、郵便配達の仕組みに例えて丁寧に紐解いていきましょう!

—

1. そもそも「プライベートサブネット」と「NATゲートウェイ」の関係って?

まずは基本のキから。ネットワークの世界を「セキュリティ万全のオフィスビル」に例えてみましょう。

  • パブリックサブネット: ビルの「受付ロビー」です。外の人が自由に出入りできます。
  • プライベートサブネット: ビルの「奥にある機密執務室」です。部外者は立ち入り禁止。インターネットからも直接アクセスできません。
  • NATゲートウェイ: 執務室(プライベート)から外へ手紙を出したい時にだけ動いてくれる「専属の郵便局員さん」です。

プライベートサブネットに置かれたサーバー(EC2など)は、セキュリティのために外からの通信を遮断していますが、OSのアップデートや外部APIの呼び出しのために「自分から外へ繋ぎたい」時があります。その時、この郵便局員さん(NATゲートウェイ)に手紙を託して、外の世界へ届けてもらうのです。

—

2. 「1人体制」の罠:クロスAZデータ転送コスト

さて、ここからが本題です。
AWSなどのクラウドには、物理的に離れたデータセンター群である「AZ(アベイラビリティゾーン)」が複数あります。例えば「東京リージョンのAZ-A」と「AZ-C」のような形です。

コストを節約しようとして、「NATゲートウェイは1つだけ(AZ-Aに配置)にして、AZ-AとAZ-Cの両方のサーバーで共有しよう!」と設計したとします。これが「1人体制」の構成です。

郵便配達で考える「通行料」

AZ-Aにいるサーバーが手紙を出すのはスムーズです。同じ町内に郵便局があるからです。
しかし、AZ-Cにいるサーバーが手紙を出そうとすると、どうなるでしょうか?

1. AZ-Cのサーバーが手紙を書く。
2. わざわざ隣の町(AZ-A)まで重い荷物を運んでいく。
3. AZ-AのNATゲートウェイがそれを受け取ってインターネットへ出す。

この「隣の町(AZ)へ荷物を運ぶ」という行為に対して、クラウド事業者は「AZ間データ転送費用(Cross-AZ Data Transfer Cost)」という通行料を請求します。

「1GBあたり数円でしょ?」と侮ることなかれ。ログの転送や大きなファイルのダウンロードが頻繁に起きる環境では、この通行料が積み重なって、NATゲートウェイ自体の利用料よりも遥かに高額な「謎の課金」として牙を剥くのです。

—

3. 「各町内配置」のすすめ:高可用性とコスト最適化

この問題を解決するのが、「各AZに1つずつNATゲートウェイを置く」という冗長化パターンです。

「えっ、NATゲートウェイを2つに増やしたら、基本料金が2倍になっちゃうじゃないですか!」

その通りです。NATゲートウェイの設置には「1時間あたりの稼働費」がかかります。しかし、中〜大規模な通信が発生するシステムでは、「基本料金の増加」よりも「AZ間通行料の削減」の方が、結果的に安くなるケースが非常に多いのです。

さらに、もう一つ決定的なメリットがあります。それは「高可用性(壊れにくさ)」です。

  • 1つだけ配置の場合: AZ-Aがもし災害などでダウンしたら、AZ-Cのサーバーも道連れでインターネットに出られなくなります。全滅です。
  • 各AZ配置の場合: AZ-Aがダウンしても、AZ-Cのサーバーは自分の町内の郵便局を使って平然と通信を続けられます。

—

4. 実践!Terraformで構築する「賢い」NATゲートウェイ設計

それでは、実際にどのように構築するのか、インフラをコードで管理する「Terraform(テラフォーム)」の例を見てみましょう。
「各AZにNATゲートウェイを作る」という処理を、1つずつ手動でやるのではなく、ループを使ってスマートに記述します。

# 1. まずは利用可能なAZのリストを取得します
data "aws_availability_zones" "available" {
  state = "available"
}

# 2. 各AZごとにNATゲートウェイ用の「固定IP(EIP)」を確保します
resource "aws_eip" "nat" {
  # AZの数だけ作成するループ処理です
  count = length(data.aws_availability_zones.available.names)
  vpc   = true

  tags = {
    Name = "nat-eip-${data.aws_availability_zones.available.names[count.index]}"
  }
}

# 3. 本題!各AZの「パブリックサブネット」にNATゲートウェイを配置します
resource "aws_nat_gateway" "main" {
  # ここでもAZの数だけ作成します
  count         = length(data.aws_availability_zones.available.names)
  
  # 自分のAZにある固定IPを紐付けます
  allocation_id = aws_eip.nat[count.index].id
  
  # 自分のAZにあるパブリックサブネットに設置します
  # これにより、通信がAZをまたがない「地産地消」の形になります
  subnet_id     = aws_subnet.public[count.index].id

  tags = {
    Name = "nat-gw-${data.aws_availability_zones.available.names[count.index]}"
  }
}

# 4. 各AZのプライベートサブネット用ルートテーブルを設定
resource "aws_route_table" "private" {
  count  = length(data.aws_availability_zones.available.names)
  vpc_id = aws_vpc.main.id

  route {
    # 全てのインターネット宛通信(0.0.0.0/0)を
    # 「同じAZにあるNATゲートウェイ」へ流すように設定します
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main[count.index].id
  }

  tags = {
    Name = "private-rt-${data.aws_availability_zones.available.names[count.index]}"
  }
}

この設定のポイントは、nat_gateway_id = aws_nat_gateway.main[count.index].id の部分です。これにより、AZ-AのサーバーはAZ-AのNATへ、AZ-CのサーバーはAZ-CのNATへ、という「最短ルート」が自動的に構成されます。

—

5. まとめ:どっちを選べばいいの?

最後に、判断基準を整理しましょう。

| 項目 | 1つのNAT GWを共有 | 各AZにNAT GWを配置 |
| :— | :— | :— |
| 初期コスト | 安い(1台分の稼働費) | 高い(AZ数分の稼働費) |
| 通信コスト | 高い(AZ間転送費が発生) | 安い(AZ間転送費ゼロ) |
| 信頼性(HA) | 低い(1箇所壊れると全滅) | 高い(AZごとに独立) |
| 適したフェーズ | 開発環境・超小規模システム | 本番環境・データ通信量が多いシステム |

初心者のうちは「まずは1つ」で始めても構いません。ですが、サービスが成長し、データ転送量が増えてきたら、必ずこの「地産地消のネットワーク設計」を思い出してください。

「パケットがどこを通って、どこでお金が発生しているのか」を意識できるようになれば、あなたはもう立派なクラウドエンジニアの仲間入りです。

一歩ずつ、理想のインフラを作り上げていきましょう!応援しています。

コメント

タイトルとURLをコピーしました