【実務・中級編】 CIDR(Classless Inter-Domain Routing)とIPアドレス設計 – クラウド&コンテナネットワーク実践ガイド

【クラウドネットワーク設計の極意】IP枯渇の悪夢を防ぐ!CIDRとプレフィックス長選定のリアルプラクティス

こんにちは、シニアSREの私です。

深夜3時、突然鳴り響くPagerDutyのアラート。「EKSクラスターの Pod に IP が割り当てられません」「RDSの新規作成に失敗しました。VPC内のIPアドレスが不足しています」。

クラウドネイティブなインフラの現場において、IPアドレスの枯渇ほど不毛で、かつ致命的な障害はありません。アプリケーションのマイクロサービス化が進み、コンテナがオートスケーリングで増殖する現代のシステムにおいて、VPCやサブネットのIP設計は、もはや単なる「初期のインフラ準備作業」ではなく、ビジネスの拡張性を左右する最重要アーキテクチャそのものです。

今回は、AWS(Amazon VPC)やGCP(VPCネットワーク)などのメガクラウド環境を前提に、CIDR(Classless Inter-Domain Routing)の基礎から、現場で絶対に失敗しないサブネットの切り方、そしてコンテナ環境を見据えたプレフィックス長選定の勘所を、泥臭い実体験を交えながら徹底解説します。

—

1. CIDRとプレフィックス長の基本:なぜ /16 や /28 なのか?

まずは基本の復習から入りましょう。私たちは普段、10.0.0.0/16 や 192.168.1.0/24 といったCIDR表記を当たり前のように使っています。このスラッシュ(/)の後に続く数字、すなわち「プレフィックス長」が、ネットワークの運命を決めます。

IPv4アドレスは合計32ビットの空間です。プレフィックス長が /16 であれば、上位16ビットがネットワーク部、残りの16ビットがホスト部(そのネットワーク内で使えるIPアドレスの数)になります。

  • /16:ホスト部 16ビット = $2^{16} = 65,536$ 個のIP
  • /24:ホスト部 8ビット = $2^8 = 256$ 個のIP
  • /28:ホスト部 4ビット = $2^4 = 16$ 個のIP

ただし、クラウドのVPCでは、プロバイダー側(AWSなら先頭の4つとブロードキャスト、GCPなら先頭の2つと末尾の1つなど)が予約済みIPとして内部利用するため、実際にユーザーが使えるIP数は公式の計算より少し少なくなります。この「見えない予約分」を計算に入れ忘れるのが、若手エンジニアが最初に踏む地雷です。

—

2. クラウドインフラにおけるVPCとサブネット設計の黄金律

「とりあえず一番大きな /16 をVPCに割り当てておけば安心だろ」
……半分正解で、半分は危険な思想です。

マルチクラウドやオンプレミスとのハイブリッド接続を考慮する場合、社内ニッチなネットワーク(社内LANや他のVPC、VPN接続先)とIPアドレス帯が重複(CIDRオーバーラップ)すると、ルーティングが崩壊します。RFC 1918で定められたプライベートIPアドレス空間(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)から、適切に設計する必要があります。

現場でよく使うサブネット分割パターン

本番環境(Production)を構築する際、以下のような階層構造でサブネットを分割するのが標準的なプラクティスです。

| 用途 | 推奨プレフィックス長 | 利用可能なIP数(目安) | 設計意図・ユースケース |
| :— | :— | :— | :— |
| VPC全体 | /16 | 約 65,536 | システム全体の基盤となる広大なアドレス空間 |
| パブリックサブネット | /24 | 約 251 | ALB(Application Load Balancer)やNATゲートウェイ用 |
| プライベート(App) | /20 | 約 4,091 | EC2、ECS、Lambda(VPC内)などのアプリケーション層 |
| プライベート(DB) | /24 | 約 251 | RDS、ElastiCacheなどのマネージドデータベース層 |

データベース層に /24(256個)は多すぎるように感じるかもしれませんが、マルチAZ配置(例えば3つのアベイラビリティゾーンに分散)を考慮すると、1AZあたり約80IPとなり、リードレプリカや将来のスケールアウトを考えると /24 あたりが妥当なサイズ感です。

—

3. コンテナ(Kubernetes / EKS)環境におけるIPアドレスの爆発的消費

ここからが本番です。DockerやKubernetesが登場して以来、従来の「EC2インスタンス1台にIP1つ」という常識は崩壊しました。

Kubernetes(AWSのEKSなど)のCNI(Container Network Interface)プラグイン(Amazon VPC CNIなど)では、ノード(EC2)に割り当てられたIPとは別に、実行されるPodごとにVPC内のプライベートIPが直接割り当てられます。

恐ろしい計算のシミュレーション

例えば、c6i.xlarge のインスタンスタイプを考えてみましょう。このインスタンスは最大で11個のネットワークインターフェイス(ENI)を持て、1ENIあたり最大15個のIPアドレスを割り当てられます。つまり、1台のノードだけで最大 $11 \times 15 = 165$ 個のPodが動きます。

もし、このノードがオートスケーリングで最大20台までスケールアウトするとどうなるでしょうか?
$165 \text{ Pods} \times 20 \text{ Nodes} = 3,300 \text{ IPアドレス}$

たった20台の小さなクラスターであっても、あっという間に数千個のIPが吹き飛びます。もしサブネットを /28(16個)や /24(256個)で切っていたら、瞬く間に InsufficientCidrBlocks エラーに見舞われ、Podの起動が失敗する「Pod Pending地獄」に陥ります。

コンテナ基盤を置くサブネットは、最低でも /20(約4,000IP)、大規模なシステムであれば /18(約16,000IP)以上の余裕を持たせるのが鉄則です。

—

4. 実践:Terraformによる安全なVPC/サブネット構築コード

口で言うだけでなく、実際にコードで正しいサブネット分割を表現してみましょう。以下は、Terraformを用いて、CIDRブロックを美しく計算・分割してVPCを構築するサンプルコードです。

# ==========================================
# 変数定義:VPC全体のCIDR
# ==========================================
variable "vpc_cidr" {
  type        = string
  description = "VPC全体で使用するCIDRブロック"
  default     = "10.100.0.0/16"
}

# ==========================================
# VPCの作成
# ==========================================
resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "production-vpc"
  }
}

# ==========================================
# サブネットの動的分割(cidrsubnet関数を使用)
# cidrsubnet(prefix, newbits, netnum)
# ==========================================

# 1. パブリックサブネット(ALB用): /16 から /24 を切り出し
resource "aws_subnet" "public" {
  count             = 3
  vpc_id            = aws_vpc.main.id
  # 10.100.0.0/24, 10.100.1.0/24, 10.100.2.0/24 を生成
  cidr_block        = cidrsubnet(var.vpc_cidr, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = {
    Name = "public-subnet-${count.index + 1}"
  }
}

# 2. プライベートサブネット(EKS/コンテナ用): /16 から /20 を切り出し
resource "aws_subnet" "private_eks" {
  count             = 3
  vpc_id            = aws_vpc.main.id
  # /16 に 4bit(2^4=16) を足すと /20。
  # netnumとして 16, 17, 18 を指定することで、パブリックと被らない領域を確保
  cidr_block        = cidrsubnet(var.vpc_cidr, 4, count.index + 16)
  availability_zone = data.aws_availability_zones.available.names[count.index]

  tags = {
    Name = "private-eks-subnet-${count.index + 1}"
  }
}

Terraformの cidrsubnet 関数を使うことで、手動で計算ミスをするリスクを排除し、論理的かつ綺麗にCIDRを分割できます。

—

5. トラブルシューティング:IP枯渇の兆候とデバッグ手順

もし、あなたの運用するシステムで突然IPアドレスが枯渇し始めたら、どのような手順で調査すべきでしょうか。現場で使える実践的なデバッグフローを共有します。

ステップ1: クラウド側のメトリック・ログを確認する

AWSであれば、CloudWatchの VPC メトリックや、Amazon VPC IP Address Manager (IPAM) を使って、各サブネットのIP使用率を可視化します。どのサブネットで枯渇しているのかを特定するのが最初のステップです。

ステップ2: CLIで稼働リソースとIPの紐付けを暴く

AWS CLIを使って、特定のサブネット内でどのリソースがIPを占有しているのかをあぶり出します。

# 特定のサブネット(例: subnet-0123456789abcdef0)に紐づいているENIを一覧化し、所有者を確認する
aws ec2 describe-network-interfaces \
    --filters "Name=subnet-id,Values=subnet-0123456789abcdef0" \
    --query "NetworkInterfaces[*].{ID:NetworkInterfaceId,Description:Description,OwnerId:OwnerId,PrivateIP:PrivateIpAddress}" \
    --output table

多くの場合、古いKubernetesの古いPodの残留(ゴーストENI)や、LambdaのENI過剰作成が犯人です。

ステップ3: 根本的な対策(VPC CIDRの拡張)

もしプレフィックス長が小さすぎて本当にIPが足りなくなった場合、クラウドではVPCにセカンダリCIDRブロックを追加するという奥の手があります。

# 既存のVPCにセカンダリCIDR(例: 100.64.0.0/16)を追加する
aws ec2 associate-vpc-cidr-block \
    --vpc-id vpc-0123456789abcdef0 \
    --cidr-block 100.64.0.0/16

※注意: セカンダリCIDRを追加する場合も、ルーティングテーブルやセキュリティグループの設計、さらには将来的なDirect ConnectやVPNでの経路広告に影響がないか、慎重に検証する必要があります。

—

まとめ

VPCのCIDR設計とサブネット切り分けは、インフラ構築の最初の数分で終わる地味な作業に見えますが、システムが成長した後に最も牙をむく技術負債になりやすいポイントです。

  • コンテナ(EKS等)を使う環境では、予想の3倍以上のIPが必要になることを前提にプレフィックス長(/20 や /18 など)を大きく取る。
  • Terraform等のIaCツールを活用し、cidrsubnet 関数などでヒューマンエラーを防ぐ。
  • 将来の拡張性や他のネットワークとの接続(ピアリング、VPN)を見据えたRFC 1918の計画的な割り当てを行う。

この3つを頭に叩き込んでおけば、深夜のIP枯渇アラートに怯える夜とはお別れできるはずです。あなたのクラウドネットワークが、美しく、そして無限の拡張性を持ったものでありますように。

コメント

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