cidrsubnet / cidrhost — IPアドレス計算関数

1. 概要

  • cidrsubnet — CIDRブロックからサブネットを計算する
  • cidrhost — CIDRブロックから特定のIPアドレスを計算する
  • cidrnetmask — CIDRブロックのネットマスクを取得する
  • 実際のVPC・サブネット設計への応用

TerraformのIPアドレス計算関数を使うと、VPCのCIDRブロックからサブネットのアドレスを動的に計算できます。手動でIP範囲を計算してハードコードする必要がなくなります。


2. cidrsubnet — サブネットを計算する

cidrsubnet(prefix, newbits, netnum)は、CIDRブロックprefixからnewbitsビット拡張したnetnum番目のサブネットを返します。

# terraform consoleで確認
# cidrsubnet(親CIDR, 追加ビット数, サブネット番号)
> cidrsubnet("10.0.0.0/16", 8, 0)
"10.0.0.0/24"   # 16+8=24ビット、0番目

> cidrsubnet("10.0.0.0/16", 8, 1)
"10.0.1.0/24"   # 1番目

> cidrsubnet("10.0.0.0/16", 8, 10)
"10.0.10.0/24"  # 10番目

> cidrsubnet("10.0.0.0/16", 4, 0)
"10.0.0.0/20"   # 16+4=20ビット

3. cidrsubnetでVPC・サブネットを設計する

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

variable "vpc_cidr" {
  description = "VPCのCIDRブロック"
  type        = string
  default     = "10.0.0.0/16"
}

resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr

  tags = {
    Name        = "${var.environment}-vpc"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

locals {
  # /16から/24サブネットを自動計算
  # パブリックサブネット: 0, 1, 2番
  # プライベートサブネット: 10, 11, 12番(間隔を空けて管理しやすく)
  public_subnets = [
    cidrsubnet(var.vpc_cidr, 8, 0),   # 10.0.0.0/24
    cidrsubnet(var.vpc_cidr, 8, 1),   # 10.0.1.0/24
    cidrsubnet(var.vpc_cidr, 8, 2),   # 10.0.2.0/24
  ]
  private_subnets = [
    cidrsubnet(var.vpc_cidr, 8, 10),  # 10.0.10.0/24
    cidrsubnet(var.vpc_cidr, 8, 11),  # 10.0.11.0/24
    cidrsubnet(var.vpc_cidr, 8, 12),  # 10.0.12.0/24
  ]
  availability_zones = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}

resource "aws_subnet" "public" {
  count             = length(local.public_subnets)
  vpc_id            = aws_vpc.main.id
  cidr_block        = local.public_subnets[count.index]
  availability_zone = local.availability_zones[count.index]

  map_public_ip_on_launch = true

  tags = {
    Name        = "${var.environment}-public-${count.index + 1}"
    Environment = var.environment
    ManagedBy   = "terraform"
    Type        = "public"
  }
}

resource "aws_subnet" "private" {
  count             = length(local.private_subnets)
  vpc_id            = aws_vpc.main.id
  cidr_block        = local.private_subnets[count.index]
  availability_zone = local.availability_zones[count.index]

  tags = {
    Name        = "${var.environment}-private-${count.index + 1}"
    Environment = var.environment
    ManagedBy   = "terraform"
    Type        = "private"
  }
}

4. for式と組み合わせて動的にサブネットを生成する

locals {
  az_count = 3

  # for式でサブネットCIDRのリストを動的生成
  public_cidr_blocks  = [for i in range(local.az_count) : cidrsubnet(var.vpc_cidr, 8, i)]
  private_cidr_blocks = [for i in range(local.az_count) : cidrsubnet(var.vpc_cidr, 8, i + 10)]
}

5. cidrhost — 特定のIPアドレスを計算する

cidrhost(prefix, hostnum)は、CIDRブロック内のhostnum番目のホストIPアドレスを返します。

# terraform consoleで確認
> cidrhost("10.0.0.0/24", 1)
"10.0.0.1"   # 最初のホストIP(通常ゲートウェイ)

> cidrhost("10.0.0.0/24", 10)
"10.0.0.10"

> cidrhost("10.0.0.0/24", -1)
"10.0.0.254"  # 最後のホストIP(負のインデックスも使える)

固定IPのEC2インスタンスに使う

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "bastion" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public[0].id
  # サブネットの最初のホストIP(.4)を固定割り当て
  private_ip    = cidrhost(aws_subnet.public[0].cidr_block, 4)

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-bastion"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

6. cidrnetmask — ネットマスクを取得する

# terraform consoleで確認
> cidrnetmask("10.0.0.0/24")
"255.255.255.0"

> cidrnetmask("10.0.0.0/16")
"255.255.0.0"

7. 関連記事


8. まとめ

  • cidrsubnet(prefix, newbits, netnum) — 親CIDRからnewbitsビット拡張したnetnum番目のサブネットを計算
  • cidrhost(prefix, hostnum) — CIDRブロック内の特定ホストIPを計算(負のインデックスで末尾から参照可能)
  • cidrnetmask(prefix) — CIDRのネットマスクを取得
  • range+for式+cidrsubnetの組み合わせで動的なサブネット設計が実現できる
  • VPCのCIDRをvariableで受け取り、cidrsubnetで自動計算するパターンが推奨

動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/cidrsubnet