今のところ、AWS IPv6化や PublicIP 外しはボチボチやったり、いったんやらない判断したり色々です。
そんな中で、考察し直した部分や、新しく考察した事例などが出てきましたので、整理していきます。
はじめに
既に AWS IPv6 についてはいくつか書きましたので、その続編ということで。- AWSのPublic IPv4構成をIPv6に切り替える | 外道父の匠
- AWSの削減対象なPublicIPの調査 | 外道父の匠
- AWS Lambda IPv6 と APIエンドポイントと NAT G/W | 外道父の匠
- AWSコンテナ系アーキテクチャの選択肢を最適化する | 外道父の匠
当初は PublicIPv4 有料化対策のつもりで書き始めたシリーズであり、それ自体は別に間違いじゃないのですが、IPv6 化をすれば即・万事メデタシになるというわけでもない、ということで色々学びつつ判断していきましょうという感じです。
既存記事と若干内容が重複する箇所もありますが、整理し直すという意味で気にしないで書いていきます。
基本構成の確認
当初とそう変わったわけではないものの、基本的な設計について改めると、こんな感じが無難になるのでないでしょうか。IPアドレス
多くを PublicIP 無しにしたいとしても、PublicIP を使う方が優位な処理もあったりするので、Public では使えるように残しておきます。IPv6 はどちらでも使えるようにし、従来の PrivateIPv4 は VPC 内でメインで使うのでもちろんそのままです。
Subnet | PublicIP | IPv6 | PrivateIP |
Public | ◯ | ◯ | ◯ |
Private | ☓ | ◯ | ◯ |
ルーティング
世の中 IPv6 を持たない接続先もまだまだ多いので、NAT G/W は必須となります。Well-Known Prefix な 64:ff9b::/96 は Public でも使われる可能性があるのと、ルーティングを通しておくこと自体は害じゃないので、こんな構成になりました。
Subnet | 送信先 | ターゲット |
Public | 0.0.0.0/0 | IGW |
::/0 | IGW | |
64:ff9b::/96 | NAT G/W | |
Private | 0.0.0.0/0 | NAT G/W |
::/0 | EIGW | |
64:ff9b::/96 | NAT G/W |
Internet Gateway (IGW) と NAT Gateway の費用は既知として、Egress Only Internet Gateway (EIGW) は公式に明確に書いていなくて、どこかの記事に小さく EC2 と同じだよって書いてたので、INPUT 無料ということになります。
IPv4 & IPv6 の優先順位
AWS Lambda IPv6 と APIエンドポイントと NAT G/W | 外道父の匠 で書いた通り、aws コマンドなどで API を叩く際には、API エンドポイントへの接続が IPv4 なら IPv4用URLを(デフォルト)、IPv6 なら IPv6用URLを指定する必要があり、東京リージョンはそもそも IPv6非対応という実情があります。要は漠然と IPv6 で叩いてはならない、ということなのですが、IPv6化しているうちにおそらく気になると思われます。その条件は Public Subnet + IPv6 付与 で起きて不思議に感じるかもしれません。
IPv6 ON かつ PublicIP を自動付与している場合で、DNS名前解決でのレスポンスに IPv4 & IPv6 を含む場合はどうなるでしょうか。例えば aws s3 ls を実行すると名前解決時の tcpdump はこうなります。IPv6 が無い代わりに DNS64 のおかげで変換済み IPv6 が同時に返ります。
1 2 3 4 |
54080+ A? s3.ap-northeast-1.amazonaws.com. (49) 589+ AAAA? s3.ap-northeast-1.amazonaws.com. (49) 54080 7/0/0 A 52.219.16.46, A 52.219.136.134, A 52.219.9.28, A 52.219.150.112, A 52.219.1.106, A 52.219.136.114, A 52.219.199.16 (161) 589 8/0/0 AAAA 64:ff9b::34db:9630, AAAA 64:ff9b::34db:842, AAAA 64:ff9b::34db:822, AAAA 64:ff9b::34db:ac64, AAAA 64:ff9b::34db:9704, AAAA 64:ff9b::34db:c06, AAAA 64:ff9b::34db:c7 |
この時、通常は IPv6 への接続を優先しようとします。
これは GetAddressInfo の /etc/gai.conf に記述されている条件です。
1 2 3 4 5 |
#precedence ::1/128 50 #precedence ::/0 40 #precedence 2002::/16 30 #precedence ::/96 20 #precedence ::ffff:0:0/96 10 |
もし IPv6 のルーティングが ::/0 → IGW しかなく、64:ff9b::/96 → NAT G/W がない場合は、変換済み IPv6 で IGW から出ていこうとしてしまうので、接続が成り立たないことになります。
そのため、この設定コメントにも書かれている通り、IPv4 を優先したければ、100 のところのコメントアウトを外すと、IPv4 で通信するので接続が成功します。
1 2 3 4 |
# # For sites which prefer IPv4 connections change the last line to # precedence ::ffff:0:0/96 100 |
設定反映には reboot が必要と書いているサイトもありますが、私が Debian 12 (bookworm) で試した場合は、編集するだけで反映されました。
送信先アドレスとルーティングの関係
なぜこんな /etc/gai.conf について書いたかというと、条件によってネットワーク経路が変わるからで、より最適な設計にするために必要な知識となりえるからです。送信先がどのタイプのアドレスを割り当てているかによって、どのように変化するかを整理してみます。DNS64 を有効にしていて、IPv4 のみの場合、変換済み IPv6 も取得することに注意が必要です。
Subnet | GAI優先 | 送信先タイプ | ターゲット |
Public | IPv4 | IPv4のみ | IGW (IPv4) |
IPv6のみ | IGW (IPv6) | ||
両方所有 | IGW (IPv4) | ||
IPv6 | IPv4のみ | NAT G/W (変換済みIPv6) | |
IPv6のみ | IGW (IPv6) | ||
両方所有 | IGW (IPv6) | ||
Private | IPv4 | IPv4のみ | NAT G/W (IPv4) |
IPv6のみ | EIGW (IPv6) | ||
両方所有 | NAT G/W (IPv4) | ||
IPv6 | IPv4のみ | NAT G/W (変換済みIPv6) | |
IPv6のみ | EIGW (IPv6) | ||
両方所有 | EIGW (IPv6) |
混乱しそうな内容だけに、何度も確認したので多分あってます多分。
黄色をつけた2箇所がポイントで、GAI 優先度を逆にした緑色の場合と比べて、NAT G/W を通る経路になることがわかります。通信の成否自体は変わりませんが、データ転送費用に影響してくることになります。
どちらが費用的に優位になるかは処理によりますが、たいていは外部へ通信する処理はダウンロードの容量が多くなるので、INPUT 無料部分が強いとすると、NAT G/W をできるだけ通さない方が優位になるパターンが多いと考えられます。
それを踏まえると、Public ではせっかく月額 $3.6 もする PublicIP があるのだから、可能な限り IGW を通すよう IPv4 を優先し、Private では IPv6 がある場合は IPv6 を優先して EIGW を使うことで INPUT を無料にする、という流れになりそうです。
DNS64 の必要性
上記ルーティングは、DNS64 有効化を前提にした設定ではありますが、無効化にしたとしてもルーティング自体が害になることはないので、いつか使うときのために置いておいてもよいと思います。問題は、というか考察ポイントとして、DNS64 は必要なのかという点です。DNS64 の存在意義は、あくまで「IPv6 専用サービス」が IPv4 専用の接続先と通信をできるようにするための変換機能です。
Public では PublicIP を付けるし、PrivateIPアドレスは全てに付けるので、なかなか「IPv6 専用」というリソースは現れないのではないかと思います。
DNS64 を無効にしておけば、Public において /etc/gai.conf によるターゲット変化を気にする必要はなくなりますので、少なくとも Public では無効、Private は「IPv6 専用」を作るために有効にしておいて損はない、くらいの感じになりそうです。
ここまで色々細けぇ~と思うかもですが、互換性のない IPv4 と IPv6 を同時に扱うってのはこういうことなんだと思います;-(
ECR は IPv6 非対応
IPv6 の恩恵を受けたかったことは PublicIPv4 有料化対策以外に、Private Subnet での INPUT を EIGW を通すことで無料にする、というものがありました(個人的願望)。特に INPUT 転送無料で意味があるのはコンテナイメージのダウンロードです。しかし、残念ながら ECR の API も Repository も IPv6 非対応なので EIGW を通して無料にすることはできません。
ECR の API (https://t.co/5CdNU55BOw) も リポジトリ(https://t.co/sWhJccySTq)も、IPv6 を持ってなくて ECS では PublicIP or NAT G/W 必須になるんですけど、この仕様のまま PublicIPv4 有料化を決めた中の人はド畜生でありませんこと!?
— 外道父 | Noko (@GedowFather) November 8, 2023
これを受けてどうすべきかは、3つほど選択肢が考えられます。
① Public Subnet で PublicIP を持ち INPUT を無料にする。ただし、2024/02 から 1 IP $3.6/月 かかるので、Autoscaling なら1日の平均 PublicIP 数から月額を試算します
② Private Subnet で NAT G/W を通します。その存在数にかかる費用と、GB あたりの費用を足して試算します。Autoscaling なら1日の起動回数と1回あたりの GB を元に月額を試算します
③ Private Subnet でPrivateLink を使って VPC Endpoint を通します。転送料金は激安になるけど、必要個数にかかる費用が結構多くなるのと、リソース構成が複雑化するのもあり、安易に採用できるわけでもありません
これらを踏まえると、変数としてはこの辺で優劣が付くことになります。
- 1タスクあたりのダウンロード容量
- 1日あたりのタスク起動回数
- 1日あたりの平均タスク数
ザックリ 500~1000 GB / 月 の転送量が分岐点になりそうな感じになると思いますが非常に微妙な話で、例えばvCPUを増やしてタスク数を減らせたり、サービスごとに1タスクの容量が小さかったり大きかったりもするので、これという正着を決めづらいです……
……が私見を述べると、コンテナの場合は vCPU を大きめにして PublicIP を持つのが、多くのサービスで最も安定した運用になると考えています。リソースの複雑さを増したり、サービスごとに最適化することよりも、シンプルに PublicIP 課金だけで調整する方が総合コストが安く済むことも多い気がします。
インスタンスの場合や、PublicIP 数が多い場合で、かつ NAT G/W を通る大きなダウンロードが少ないならば、Private で稼働させる方が安くなる可能性が高いので、いったん試算してみるとよいでしょう。
CodeBuild VPC は非Public
ちょっと話はズレますが、CodeBuild を使う時に on VPC にする必要がある場合、昔から NAT G/W が必須になります。Subnet で自動付与を有効にしていても PublicIPv4 , IPv6 どちらも扱えないためです。- Amazon Virtual Private Cloud での AWS CodeBuild の使用 – AWS CodeBuild
- 記載すら無し:AWS services that support IPv6 – Amazon Virtual Private Cloud
これにより、CodeBuild はパブリックエンドポイントにアクセスできるようになります (ビルドの実行時に CLI コマンドを実行する場合など)。
CodeBuild は、作成したネットワークインターフェイスへの Elastic IP アドレスの割り当てをサポートしていないため、NAT ゲートウェイや NAT インスタンスの代わりにインターネットゲートウェイを使用することはできません。
また、Amazon EC2 は、 Amazon EC2 インスタンスの起動以外で作成されたネットワークインターフェイスに対しては、パブリック IP アドレスの自動割り当てをサポートしていません。
インストール処理などで、通常は apt や gem で公開パッケージを取得しますが、社内用リポジトリを併用する場合は VPC 内や VPC Peering 経由先にあったりするので、VPC 所属で CodeBuild を構築することになります。
その場合、イメージのダウンロードや、インストール関連のパッケージダウンロードなど、NAT G/W を通る通信量が多くなると思われるため、VPC 不要なビルドでは無駄に VPC 所属にさせないようにしましょう。
プロキシサーバー経由
それでも、どうしても VPC 所属で大容量 INPUT をする場合は、古き良きプロキシサーバー squid を通して回避することができます。管理リソースは増えますが、プロキシ自体は CPU もメモリも多くは必要としないため、NAT G/W を通るのと比べれば遥かに費用が安く済むことも多いでしょう。
おわりに
IPv6 を有効にしたサーバーで色々名前解決してみると、大手を含めてまだまだ世の中は IPv6 非対応なサービスが多く、システムごとにも扱いや最適化が異なったりするため、IPv6 化がシンプルに幸せを提供してくれるわけではないことを実感できます。恩恵を濃く受けるとしたら、PublicIP を超多く使っているサービスとかは確実ではあります。仮に 100 PublicIP を外せたら、月額5万円、年間60万円のコスト高騰回避になるので、NAT G/W 利用が多くなったとしても、その方が安く済む可能性があります。
まぁ費用全体から見たら、これらの部分の費用は微々たるものなのですが、多少の違いはあれど、どのような設計にしても『正常に安定した通信ができる』としたら、最も費用が安く済む設計にしておきたいのは当然です。
とりあえず2月以降にコスト管理画面で PublicIP の日割り費用でも見てみて、その放置を許容できるかどうかってところから始めて、じわじわと最適化ゲームを楽しんでいきましょうそうしましょう:-)