こんにちは!クラウドの世界へようこそ。第一線でSRE(サイト信頼性エンジニア)をやっていると、夜中に突然「なんだかウェブサイトに繋がりにくいぞ!」というアラートが飛んできたりします。その原因を紐解いていくと、実は今回のテーマである「ポート枯渇問題」に行き着くことが本当に多いんです。
インフラやネットワークの世界に初めて触れる方にとって、IPアドレスやポート番号といった言葉は、ちょっと取っつきにくく感じてしまいますよね。でも、大丈夫です!一歩ずつ、私たちの身の回りの身近な例えから優しく紐解いていきましょう。
今回は、クラウド(AWSやGCPなど)の心臓部を支える「NATゲートウェイ」と、そこで起きる「ポートの枯渇」というドラマについて、じっくりお話ししていきますね。
—
1. そもそもNATって何をしているの?(郵便局に例えてみよう)
私たちが普段使っているクラウド(AWSのVPCやGCPのVPCなど)の中には、外のインターネットの世界からは直接見えない「プライベートな空間(プライベートサブネット)」があります。この空間にあるサーバーたちは、セキュリティを守るために自分専用の隠し部屋に住んでいるような状態です。
「じゃあ、この隠し部屋にいるサーバーたちは、どうやってインターネット上のウェブサイトを見に行ったり、アップデートをダウンロードしたりするのでしょうか?」
ここで登場するのが、NATゲートウェイ(Network Address Translation Gateway)です。
郵便局の本局窓口のような存在
身近な例えで考えてみましょう。社内のたくさんのスタッフ(プライベートサブネットのサーバーたち)が、外の取引先へ一斉に手紙を出したいとします。でも、スタッフ全員がバラバラの住所で手紙を出すと管理が大変ですし、そもそも社内の秘密の小部屋にいるので、外からは直接返事が返せません。
そこで、「会社の代表窓口(NATゲートウェイ)」を一つ用意します。
1. スタッフが手紙を書き、代表窓口に持っていく。
2. 代表窓口の担当者は、その手紙の差出人を「自分の名前(NATゲートウェイのパブリックIPアドレス)」に書き換えて、外のポストに投函する。
3. 相手から返事が返ってくると、代表窓口の担当者は「あ、これはさっきのA君宛てだな」と思い出し、宛先をA君に書き直して渡してあげる。
これが、NAT(正確には複数の通信を1つのIPで束ねるNAPT / PAT)の仕組みです。代表窓口の担当者が、うまく帳面(管理テーブル)をつけてくれているからこそ、みんなが安全に外の世界とやり取りできるんですね。
—
2. 最大の壁:使える「番号札」は、たったの65,535枚?
さて、ここからが今回の本題です。
代表窓口(NATゲートウェイ)は、外の世界と通信するときに、どのスタッフからの通信かを区別するために「ポート番号」という番号札を使っています。
「ポート番号って何だか難しそう……」と思いますよね?
これは、マンションの「部屋番号」や、クロークに荷物を預けたときにもらう「番号札」のようなものです。一つの大きな住所(パブリックIPアドレス)に対して、何番から何番まで部屋があるでしょうか?
コンピュータの世界では、このポート番号は最大で「65,535番」までと決まっています。
郵便局の窓口で起きる悲劇
想像してみてください。あなたの会社で、一瞬のあいだに外のサーバーへアクセスする通信が、なんと60,000件も発生したとします。
代表窓口には、使える番号札が65,535枚しかありません。
- 1番の札:サーバーA用の通信
- 2番の札:サーバーB用の通信
- ……
- 65,535番の札:サーバーZ用の通信
もし、ここでさらに新しい通信が「外に行きたい!」とやってきたらどうなるでしょうか?
そう、「あぁっ、もう配れる番号札(ポート)が1枚も残っていないよ!」という状態になってしまいます。これが、インフラエンジニアが恐れる「ポート枯渇問題(Port Exhaustion)」の正体です。
番号札がなくなると、新しくウェブページを見に行こうとしても、通信がその場でピタリと止まってしまい、タイムアウトエラー(Connection Timeout)が起きてしまうのです。
—
3. どんなときにポートが枯渇するの?(現場のリアルな背景)
「65,535個も番号があるなら、そうそう枯渇しないんじゃないの?」と思われるかもしれません。しかし、現代のクラウドシステムは、驚くようなスピードで大量の通信を発生させます。
例えば、次のようなシーンでポート枯渇の危険性が急上昇します。
1. マイクロサービス間の大量のAPI通信
ひとつの画面を表示するために、背後で数十個のコンテナ(KubernetesのPodなど)が、外部の決済APIやSaaSへ一斉にリクエストを投げるシステム。
2. 踏み台サーバーやバッチ処理
短時間に数万件のデータを外部APIからスクレイピングしたり、一斉にデータを同期したりするバッチ処理プログラム。
3. Keep-Aliveの設定ミス
HTTPの接続維持(Keep-Alive)が正しく行われず、通信のたびに毎回新しいポートを使い捨ててしまうような非効率なプログラム。
—
4. どうやって解決するの?実践的なアプローチとコード例
「じゃあ、ポートが足りなくなったらどうすればいいの?」
安心してください。SREやクラウドアーキテクトたちは、次のような手口でこの問題を華麗に解決していきます。
解決策①:NATゲートウェイの「数」を増やす(スケールアウト)
AWSなどのパブリッククラウドでは、NATゲートウェイは1つだけでなく、複数作成することができます。
IPアドレスが1つ増えれば、使えるポートも「65,535個 × IPの数」へと倍増します。
例えば、TerraformなどのIaC(Infrastructure as Code)ツールを使って、複数のAZ(アベイラビリティゾーン)にそれぞれNATゲートウェイを配置する設定は、実務の現場では定番中の定番です。
# Terraformで複数のNATゲートウェイを配置するイメージ
resource "aws_nat_gateway" "nat_az1" {
allocation_id = aws_eip.nat_ip_az1.id
subnet_id = aws_subnet.public_az1.id
# タグで管理をわかりやすくする
tags = {
Name = "production-nat-gw-az1"
}
}
resource "aws_nat_gateway" "nat_az2" {
allocation_id = aws_eip.nat_ip_az2.id
subnet_id = aws_subnet.public_az2.id
tags = {
Name = "production-nat-gw-az2"
}
}
解決策②:アプリケーション側で「接続の使い回し(コネクションプーリング)」をする
一番根本的な解決は、プログラム側で無駄なポート消費を抑えることです。毎回新しい通信を作るのではなく、一度つながったパイプ(コネクション)を使い回すようにコードを書き換えます。
例えば、Pythonのrequestsライブラリを使って外部APIを叩く場合、Sessionオブジェクトを使うことでコネクションが再利用され、ポートの無駄遣いを防ぐことができます。
import requests
# 良い例:Sessionオブジェクトを使ってコネクションを維持(プーリング)する
# これにより、毎回新しいポートを消費するのを防ぎます。
session = requests.Session()
def fetch_external_api(urls):
for url in urls:
# 同じセッションを使い回すことで、TCPコネクションとNATポートを節約!
response = session.get(url)
print(f"ステータスコード: {response.status_code}")
# 使用例
target_urls = [
"https://api.example.com/v1/data1",
"https://api.example.com/v1/data2",
"https://api.example.com/v1/data3"
]
fetch_external_api(target_urls)
もしこれをrequests.get(url)という書き方だけでループさせてしまうと、リクエストのたびに新しいポートが強制的に割り当てられ、あっという間にポート枯渇の罠にハマってしまいます。注意したいポイントですね!
—
まとめ
今回は、クラウドネットワークの裏側でこっそり行われている「ポートアドレス変換(NAPT)」の仕組みと、そこに潜む「ポート枯渇問題」について、郵便局の窓口に例えて優しく解説しました。
- NATゲートウェイは、プライベートなサーバーたちが外と通信するための「代表窓口」。
- 一つのIPアドレスで使える番号札(ポート番号)は、最大で65,535枚しかありません。
- 大量のリクエストをさばくシステムでは、この番号が足りなくなる「ポート枯渇」が起きる。
- 対策としては、「NATゲートウェイ自体の数を増やすこと」と、「アプリ側でコネクションをしっかり使い回すこと(コネクションプーリング)」が有効。
インフラやネットワークのトラブルに直面したとき、「あ、今パケットの番号札が足りなくなっているのかもな」と、この郵便局の窓口の景色を思い出していただけたら、エンジニアとしての視界がぐっと広がること間違いなしです。
それでは、また次回のクラウド・ネットワーク散歩でお会いしましょう!
コメント