VPC IP枯渇の悪夢を断つ!セカンダリCIDRとマルチCIDRサブネット設計の極意
こんにちは。クラウドインフラの現場を渡り歩いてきたシニアSREの私です。
夜中に突発的なアラートが鳴り響く。その原因が「コンテナ基盤(Kubernetes)のノードスケールアウトに伴う、VPCプライベートサブネットのIPアドレス枯渇」だったとしたら……。冷や汗が背中を伝う感覚、皆さんも一度や二度は経験があるのではないでしょうか。
「プライベートサブネットを /24 で切っておけば当分大丈夫だろう」と高を括っていたら、Pod密度が高まったEKSクラスターと、Lambda、RDS、そして思わぬところで増殖したEC2インスタンスによって、あっと言う間にIPアドレスプールが底をつく。クラウドの柔軟性に甘え、CIDR設計を甘く見ていた代償は高くつきます。
AWSのVPCやGCPのVPCにおいて、初期割り当てられたプライマリーCIDR(例: 10.0.0.0/16)が枯渇した際、あるいは異なるセグメントのIPアドレスを追加で収容したい場合に救世主となるのが「セカンダリCIDRブロックの付与」と「マルチCIDRサブネット設計」です。
今回は、パケットがどのようにルーティングされ、どのような制約や落とし穴があるのか、現場の泥臭い知見を交えながら徹底的に解説します。
—
1. なぜIP枯渇は起きるのか? クラウドネットワークの現実
オンプレミス環境であれば、ネットワーク設計はハードウェアの物理制約と厳格なIPAM(IP Address Management)によってガチガチに管理されていました。しかし、クラウドネイティブな世界では、以下のような要因で爆発的にIPアドレスが消費されます。
1. Kubernetes(CANI)のIP消費: VPCネイティブなCNI(AWS VPC CNIなど)を使用する場合、ノード上の各PodにVPCのプライベートIPが直接割り当てられます。
2. サーバーレスの爆発的スケール: AWS LambdaがVPC内リソース(RDSなど)にアクセスする際、ENI(Elastic Network Interface)がサブネット内に生成され、IPアドレスが一時的に占有されます。
3. マイクロサービスの乱立: ECSやEC2、コンテナが細分化され、サービスメッシュやサイドカーが日常的に通信を行います。
初期設計で 10.0.0.0/16 を切ったとしても、ルーティングや可用性(AZ分散)を考慮してサブネットを分割していくと、意外なほど早く枯渇の足音が聞こえてきます。ここでVPC全体を作り直す(リプレイスする)のは、本番環境においては悪夢のようなダウンタイムを伴います。
そこで、既存のVPC構造を維持したまま、セカンダリCIDRを追加してIP空間を拡張するアプローチが必要になるのです。
—
2. セカンダリCIDRブロックとマルチCIDRサブネットの基本ルール
VPCにセカンダリCIDRを追加する場合、いくつかの厳格なルールが存在します。これを無視して設計すると、APIコール時に容赦なくエラーが返されます。
VPC CIDRの制約事項
- プライベートIPv4アドレス範囲の利用: RFC 1918で規定されているプライベートIP範囲(
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16)を使用するのが一般的です。 - 重複・競合の禁止: すでにVPCに割り当てられているCIDR、あるいはVPCピアリングやAWS Direct Connect/VPN等で接続しているリモートネットワークのCIDRと重複してはなりません。
- プレフィックスの制約: AWSの場合、VPCに割り当てられるCIDRブロックのサイズは
/16(最大65,536個のIP)から/28(最小16個のIP)の間である必要があります。また、最大で5つのCIDRブロック(プライマリー1つ + セカンダリ4つ)を1つのVPCに紐づけられます。
サブネットにおけるマルチCIDR設計の挙動
VPCにセカンダリCIDR(例: 100.64.0.0/16)を追加した後、既存のサブネット、あるいは新しく作成するサブネットに対して、このセカンダリCIDRからの範囲を割り当てることができます。
ここで重要なのは、「1つのサブネット内に、プライマリーCIDR由来のIPとセカンダリCIDR由来のIPが混在可能になる」という点です。
+-------------------------------------------------------+
| VPC: 10.0.0.0/16 (プライマリー) + 100.64.0.0/16 (セカンダリ) |
| |
| +-----------------------------------------------+ |
| | Subnet A (AZ-a) | |
| | - プライマリー範囲: 10.0.1.0/24 | |
| | - セカンダリ範囲: 100.64.1.0/24 | |
| +-----------------------------------------------+ |
+-------------------------------------------------------+
この構成により、サブネット自体のルーティングテーブルやネットワークACL(NACL)を変更することなく、IPアドレスの枯渇問題をシームレスに回避できます。
—
3. 通信フローとルーティングの裏側
「セカンダリCIDRを追加すれば、魔法のようにすべてがうまく動く」わけではありません。パケットのルーティングにおいて、VPC内部のルーターがどのように振る舞うかを理解しておく必要があります。
同一サブネット内の通信(L2/L3の境界)
同一サブネット内に存在するインスタンスA(10.0.1.5)とインスタンスB(100.64.1.10)の間で通信を行う場合、AWSの仮想ルーター(SDN制御プレーン)が介在します。
これらは論理的に同一セグメント(サブネット)に属しているとみなされるため、VPCのメイン(またはカスタム)ルーティングテーブルに明示的なルートを追加しなくても、直接通信が可能です。
異なるサブネット・外部ネットワークとの通信
セカンダリCIDRから割り当てられたIPアドレスを持つリソースからインターネットや外部VPCへ通信する場合、VPCのルートテーブルが鍵となります。
[リソース (100.64.1.10)]
│
▼ (デフォルトゲートウェイへ送信)
[VPCルーター / ルートテーブル評価]
│
├─> 同一VPC内 CIDR (10.0.0.0/16, 100.64.0.0/16) ──> ローカルルーティング (local)
│
└─> 外部宛て (0.0.0.0/0) ─────────────────────────> NATゲートウェイ / インターネットGW
ここで注意すべきなのは、「セカンダリCIDRの範囲に対するルートは、自動的にローカルルート(local)としてVPCのルートテーブルに登録される」という点です。ユーザーが手動で 100.64.0.0/16 に対するルートを追加する必要はありません。
ただし、AWS Transit GatewayやVPCピアリングを介して他のネットワークと接続している場合、リモート側のルーティングテーブルにセカンダリCIDR(例: 100.64.0.0/16)を明示的に伝播(または追加)し忘れるというミスが頻発します。「あれ、セカンダリ側のPodからオンプレミスに繋がらないぞ?」というトラブルの大半はこれが原因です。
—
4. 実践:AWS CLIとTerraformによるセカンダリCIDR付与
それでは、実際に手を動かしてセカンダリCIDRを追加する手順を見ていきましょう。ここでは、代表的なIaCツールであるTerraformと、緊急時に役立つAWS CLIのコードスニペットを紹介します。
TerraformによるセカンダリCIDRとマルチCIDRサブネットの構築例
以下のコードは、既存のVPCに対してセカンダリCIDRを追加し、そのセカンダリ空間からサブネットを切り出す実用的な設定です。
# 1. 既存のVPCに対してセカンダリCIDRブロックを追加する
resource "aws_vpc_ipv4_cidr_block" "secondary" {
vpc_id = aws_vpc.main.id
cidr_block = "100.64.0.0/16" # キャリアグレードNAT等のRFC 6598範囲や追加のプライベート範囲
}
# 2. セカンダリCIDRからサブネットを切り出す
# 依存関係(depends_on)を明示することで、CIDRの付与が完了する前にサブネット作成が走るのを防ぐ
resource "aws_subnet" "secondary_subnet" {
vpc_id = aws_vpc.main.id
cidr_block = "100.64.1.0/24" # セカンダリCIDRに含まれるプレフィックスを指定
availability_zone = "ap-northeast-1a"
tags = {
Name = "app-secondary-subnet-az1a"
Environment = "production"
Description = "IP枯渇対策のためのセカンダリサブネット"
}
depends_on = [aws_vpc_ipv4_cidr_block.secondary]
}
AWS CLIによる即時対応手順
障害対応時やテスト環境で、Terraformを実行する暇がない場合の緊急コマンドです。
# 1. VPCにセカンダリCIDRを追加する
aws ec2 associate-vpc-cidr-block \
--vpc-id vpc-0123456789abcdef0 \
--cidr-block 172.16.0.0/16
# 実行結果から Association ID を控えておく(ステータスが "associated" になるまで待機)
# 2. 追加されたセカンダリCIDRの関連付けIDを確認
aws ec2 describe-vpcs \
--vpc-ids vpc-0123456789abcdef0 \
--query "Vpcs[].Ipv4CidrBlockAssociationSet"
—
5. 現場でハマりがちな罠とトラブルシューティングTips
最後に、数々の修羅場をくぐってきたSREが直面した「セカンダリCIDRあるあるトラブル」と、その回避策を共有します。
トラブル1: セカンダリCIDR追加後にセキュリティグループの挙動がおかしくなった
- 現象: セカンダリCIDRから立ち上げたコンテナ間通信において、セキュリティグループ(SG)で同じVPC内からの通信を許可しているにもかかわらず、パケットがドロップする。
- 原因と対策: セキュリティグループのルールで送信元に
10.0.0.0/16のみを指定しており、セカンダリCIDR(100.64.0.0/16)が漏れていた。セカンダリCIDRを導入した際は、すべてのセキュリティグループ、NACL、さらにはアプリケーション層の許可IPリスト(ホワイトリスト)を総点検する必要があります。
トラブル2: VPCピアリング先のトラフィックが到達しない
- 現象: ピアリング先のVPCから、こちらのセカンダリCIDRに属するインスタンスへアクセスできない。
- 原因と対策: VPCピアリングは、お互いのVPCの「どのCIDRをルーティングするか」を明示的に設定する必要があります。プライマリーCIDRだけでなく、セカンダリCIDR宛てのルートを双方のルートテーブル(およびピアリング接続側のルート)に追加してください。
トラブル3: 既存サブネットのIPが枯渇したからといって、無計画にセカンダリを混ぜない
- 設計のコツ: 同一サブネット内にプライマリーとセカンダリのIPが混在すると、IPAMや監視ツール(DatadogやPrometheusなど)でのリソース管理がカオスになります。「KubernetesのPod用はセカンダリCIDR専用のサブネットを新規に切る」など、用途ごとにサブネットを綺麗に分離するのが、後々の運用負荷を下げる最大の秘訣です。
—
まとめ
VPCのセカンダリCIDR付与とマルチCIDRサブネット設計は、IP枯渇というインフラエンジニアの悪夢を華麗に回避するための強力な武器です。
しかし、それは単にコマンドを叩いてCIDRを広げれば終わり、というものではありません。ルーティングの伝播、セキュリティグループの網羅的な見直し、そして何より「将来を見据えた綺麗なIPAM設計」があって初めて、その真価を発揮します。
皆さんのクラウド環境が、枯渇の恐怖から解放され、健やかでスケーラブルなネットワークであり続けることを願っています。それでは、次の障害対応の現場でお会いしましょう!
コメント