【実務・中級編】 VPCエンドポイント(Gateway型)のルーティングメカニズムとプレフィックスリスト – クラウド&コンテナネットワーク実践ガイド

S3への通信が遅い?Gateway型VPCエンドポイントとプレフィックスリストの裏側を徹底解説

こんにちは。クラウドインフラの現場を渡り歩いているシニアSREの私です。

先日、後輩の若手エンジニアから「アプリケーションサーバーからAmazon S3に画像ファイルをアップロードする処理のレイテンシーが、なんだか不安定なんですよね。NATゲートウェイのメトリクスを見ると、時々パケットが溢れそうになっているし、通信コストもバカになりません。どうにかなりませんか?」という相談を受けました。

あなたも、AWS上でシステムの設計や運用をしていて、「S3やDynamoDBにアクセスするだけなのに、なぜインターネット経由(あるいはNATゲートウェイ経由)で通信させなきゃいけないんだ?」とモヤモヤしたことはありませんか?

今回は、このモダンクラウドアーキテクチャにおける永遠の課題をエレガントに解決する「Gateway型VPCエンドポイント」を取り上げます。教科書的な仕様の丸暗記ではなく、パケットがAWSのバックボーンネットワークをどう駆け巡っているのか、その裏側のルーティングメカニズムとプレフィックスリストのリアルな挙動を、現場の知見を交えて徹底解説します。

—

1. なぜGateway型VPCエンドポイントが必要なのか?

まずは、パケットの旅路を想像してみましょう。

プライベートサブネット(NATゲートウェイの背後)に配置されたEC2インスタンスから、S3バケットに保存されたオブジェクトを GET リクエストで取得しようとしたとします。VPCエンドポイントを導入していない場合、通信のフローは以下のようになります。

1. EC2インスタンスが宛先IP(S3のパブリックIP)に向けてパケットを送信する。
2. プライベートサブネットのルートテーブルに従い、トラフィックは一度NATゲートウェイへと投げられる。
3. NATゲートウェイが送信元IPを自身のElastic IPに書き換え(SNAT)、インターネットゲートウェイ(IGW)を経由して外のインターネット世界へパケットを送り出す。
4. パケットはAWSのネットワークの外に出るか出ないかの境界をさまよい、最終的にAWSのS3フロントエンドに到達する。

……ちょっと待ってください。通信相手も自分たちと同じAWS(S3)なのに、なぜわざわざ一度パケットを外の世界(の雰囲気を漂わせる場所)へ連れ出さなければならないのでしょうか?

これには大きなデメリットが3つあります。

  • セキュリティ上のリスク: トラフィックが一度でも外向きの経路に乗るため、セキュリティポリシーやパケットキャプチャの観点でノイズが増える。
  • 無駄なコスト: NATゲートウェイの処理データ量に応じた課金(GB単価)が容赦なく発生し、地味に痛いインフラコストになる。
  • パフォーマンスとスケーラビリティの限界: NATゲートウェイ自体の帯域制限や、コネクション数の枯渇(ポート exhaustion)リスクに常に怯える必要がある。

ここで登場するのが、Gateway型VPCエンドポイントです。これをVPCにアタッチすると、AWS内部のSDN(Software-Defined Networking)レイヤーでマジックが起き、「S3宛てのパケットは、外に出さずにAWSの超高速なプライベートバックボーンへ直接ねじ込む」ことが可能になります。

—

2. ルーティングの仕組みとプレフィックスリストの正体

では、Gateway型VPCエンドポイントを有効化すると、AWSの内部では何が起きているのでしょうか? キーワードは 「プレフィックスリスト(Prefix List)」 と 「ルートテーブルの書き換え」 です。

プレフィックスリストとは何か?

AWSを触っていると、pl- から始まるIDを見かけるはずです。これがプレフィックスリストです。
S3やDynamoDBなどのAWSサービスは、世界中に無数のIPアドレスを持っています。しかもそれらは日々変動します。ユーザーが手動で「S3の全IPアドレスをルートテーブルに書く」なんてことは不可能ですし、現実的ではありません。

そこでAWSが提供しているのが、サービスごとに最適化されたIPアドレス範囲の集約リストである プレフィックスリスト です。例えば、東京リージョン(ap-northeast-1)におけるS3のプレフィックスリストを参照すると、S3が内部で使用しているCIDRブロックの集合体が抽象化されています。

ルートテーブルにおけるマジック

Gateway型VPCエンドポイントを作成すると、VPCのルートテーブルに以下のようなカスタムルートを追加できるようになります。

  • 送信先 (Destination): pl-xxxxxx (com.amazonaws.ap-northeast-1.s3)
  • ターゲット (Target): vpce-xxxxxx (VPCエンドポイントID)

このルートが設定された瞬間、サブネットのルートテーブルに革命が起きます。
EC2インスタンスからS3のエンドポイントURL(例: s3.ap-northeast-1.amazonaws.com)に対して名前解決が行われ、返ってきたS3のパブリックIP宛てのパケットが送出されると、OSやハイパーバイザーのネットワークスタックは通常のインターネット向けルートではなく、「このIP宛ては、あのVPCエンドポイント(vpce-)へダイレクトに流し込め」という指示を受け取ります。

結果として、パケットはNATゲートウェイやIGWを華麗にバイパスし、AWSのグローバルバックボーンへ直接ルーティングされるのです。しかも、この通信は完全にAWSの管理下にあるセキュアな閉域網内で行われます。

—

3. 実践:TerraformでのVPCエンドポイント構築コード

口で言うだけではなく、実際にコードでどう表現されるのかを見てみましょう。現場でよく使われるTerraformを使った構成例です。プライベートサブネットからインターネットを出ずにS3へアクセスする環境を定義します。

# 1. 既存のVPCおよびプライベートサブネットのルートテーブルIDがあると仮定
# (ここでは分かりやすくリソース定義を簡略化しています)

# S3用のGateway型VPCエンドポイントの作成
resource "aws_vpc_endpoint" "s3" {
  vpc_id            = aws_vpc.main.id
  service_name      = "com.amazonaws.ap-northeast-1.s3"
  vpc_endpoint_type = "Gateway" # ここでGateway型を指定

  # エンドポイントポリシー(必要に応じてアクセス元を厳格に制限する)
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "AllowSpecificBucketAccess"
        Effect    = "Allow"
        Principal = "*"
        Action    = [
          "s3:GetObject",
          "s3:PutObject"
        ]
        Resource = [
          "arn:aws:s3:::my-production-bucket-foobar/*" # 特定のバケットのみにアクセスを絞る
        ]
      }
    ]
  })

  tags = {
    Name = "prod-s3-gateway-endpoint"
  }
}

# 2. プライベートサブネット用のルートテーブルにプレフィックスリストのルートを関連付け
resource "aws_route" "private_s3_route" {
  route_table_id          = aws_route_table.private.id
  destination_prefix_list_id = aws_vpc_endpoint.s3.prefix_list_id # AWSが管理するS3のプレフィックスリストIDを指定
  vpc_endpoint_id         = aws_vpc_endpoint.s3.id
}

このTerraformコードを適用すると、AWS側で自動的にプレフィックスリストがルートテーブルに組み込まれ、プライベートサブネットからのS3トラフィック経路が切り替わります。

—

4. 現場で役立つ!トラブルシューティングとデバッグ手法

「エンドポイントを作ったのに、なぜかS3に繋がらない」「タイムアウトする」といったトラブルは、現場のエンジニアなら一度は踏む地雷です。最後に、私が修羅場で培った実践的なデバッグ手順を伝授します。

① 名前解決(DNS)の確認

Gateway型VPCエンドポイントは、Interface型(AWS PrivateLink)とは異なり、プライベートIP(ENI)を持ちません。 そのため、エンドポイントを作っても nslookup や dig で返ってくるS3のIPアドレス自体は、これまでと変わらずパブリックIPのままです。
「IPが変わらないのに、どうやってルーティングを判断しているのか?」と混乱しがちですが、前述の通り「ルートテーブルのプレフィックスリスト」がそのルーターの役割を果たしているからです。
名前解決結果がパブリックIPであっても焦らず、次へ進みましょう。

② ルートテーブルの適用漏れを確認する

最も多いミスが、「VPCエンドポイントは作ったけれど、該当するプライベートサブネットのルートテーブルにプレフィックスリストのルートを追加し忘れていた」というパターンです。
AWS CLIを使って、ルートテーブルが正しくエンドポイントを向いているか確認してみましょう。

# ルートテーブルのルーティング情報を確認するコマンド
aws ec2 describe-route-tables \
  --route-table-ids rtb-0123456789abcdef0 \
  --query "RouteTables[].Routes[*]"

出力結果の中に、DestinationPrefixListId が設定されており、その VpcEndpointId が正しく紐づいているかをチェックしてください。

③ エンドポイントポリシーの罠

「ルートもうまくいっている、セキュリティグループ(※Gateway型にはSG自体が存在しませんが)も関係ない、なのに403 Access Deniedになる」という場合、大体犯人は VPCエンドポイントポリシー です。

デフォルトのエンドポイントポリシーは FullAccess(すべて許可) ですが、セキュリティ要件を厳しくするあまり、以下のようなポリシーを設定してしまい、自らの首を絞めているケースが後を絶ちません。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": "*"
    }
  ]
}

エンドポイントポリシーは 「デフォルトで拒否、明示的な許可が必要」 または 「デフォルトで許可、明示的な拒否が優先」 といったIAMポリシーの評価ロジックに従います。接続テストを行う際は、一度ポリシーをオープン(FullAccess)にして切り分けを行うのが現場の鉄則です。

—

まとめ

今回は、VPCの設計において極めて重要である「Gateway型VPCエンドポイント」のルーティングメカニズムとプレフィックスリストの挙動について解説しました。

  • Gateway型VPCエンドポイントは、NATゲートウェイやIGWを介さずに、AWSのバックボーンへ直接トラフィックを流すための強力な仕組みである。
  • その裏側では、変動するS3やDynamoDBのIP群が「プレフィックスリスト」として抽象化され、ルートテーブルのターゲットとして機能している。
  • インターネット経由の通信コスト削減、セキュリティ向上、パフォーマンス安定化の観点から、プライベートサブネットからのS3/DynamoDBアクセスには必須のアーキテクチャである。

インフラの基礎を支えるルーティングの仕組みを深く理解していると、障害時の原因切り分けスピードが劇的に変わります。「なんとなく動いている」から「仕組みを完全に理解して使いこなしている」状態へ、ぜひ今回の知識を現場の設計に活かしてみてください。

それでは、また次回の技術現場でお会いしましょう!

コメント

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