TerraformでAWSにIPv6サブネットを作る方法

おはようございます、加藤です。TerraformでIPv6サブネットを作る方法をご紹介します。

環境

ソフトウェア バージョン
macOS 10.13.4(17E199)
Terraform v0.11.6

説明

まずは、公式ドキュメントを確認します。

AWS: aws_subnet - Terraform by HashiCorp

ドキュメントにはIPv4の場合のサンプルコードが記載されていますね。

resource "aws_subnet" "main" {
    vpc_id = "${aws_vpc.main.id}"
    cidr_block = "10.0.1.0/24"

    tags {
        Name = "Main"
    }
}

残念ながら、IPv6ではこの方法は使用できません。

AWS VPCでネットワーク範囲を決める時、IPv4はユーザーが指定しますが、IPv6は自動的に割り当てられます。

これを解決する為に、Terraformのcidrsubnetを使用します。

cidrsubnet(iprange, newbits, netnum)

cidrsubnetは3つの引数を持つ関数です。IP範囲をサブネット分割した場合の、任意のIP範囲を返してくれます。

上記コードと対応させるとこのような言い方になります。

"iprange"を"newbits"でサブネット分割した場合の、先頭から"netnum"個目のIP範囲を返してくれます。

TerraformのREPLを使って実際に確認するとわかりやすいです。

terraform console
> cidrsubnet("172.16.0.0/16", 8, 0)
172.16.0.0/24
> cidrsubnet("172.16.0.0/16", 8, 1)
172.16.1.0/24
> cidrsubnet("172.16.0.0/16", 8, 2)
172.16.2.0/24
> cidrsubnet("172.16.0.0/16", 8, 3)
172.16.3.0/24

> cidrsubnet("172.16.0.0/16", 10, 0)
172.16.0.0/26
> cidrsubnet("172.16.0.0/16", 10, 1)
172.16.0.64/26
> cidrsubnet("172.16.0.0/16", 10, 2)
172.16.0.128/26
> cidrsubnet("172.16.0.0/16", 10, 3)
172.16.0.192/26
terraform console
> cidrsubnet("2001:db8::/56", 8, 0)
2001:db8::/64
> cidrsubnet("2001:db8::/56", 8, 1)
2001:db8:0:1::/64
> cidrsubnet("2001:db8::/56", 8, 2)
2001:db8:0:2::/64
> cidrsubnet("2001:db8::/56", 8, 3)
2001:db8:0:3::/64

> cidrsubnet("2001:db8::/56", 10, 0)
2001:db8::/66
> cidrsubnet("2001:db8::/56", 10, 1)
2001:db8:0:0:4000::/66
> cidrsubnet("2001:db8::/56", 10, 2)
2001:db8:0:0:8000::/66
> cidrsubnet("2001:db8::/56", 10, 3)
2001:db8:0:0:c000::/66

実践

1つのサブネットを作成するコードを書いてみました。

resource "aws_vpc" "main" {
    cidr_block = "10.0.0.0/16"
    assign_generated_ipv6_cidr_block = true

    enable_dns_support = true
    enable_dns_hostnames = true
    tags {
        Name = "Main"
    }
}


resource "aws_subnet" "main" {
    vpc_id = "${aws_vpc.main.id}"
    
    cidr_block = "${cidrsubnet(aws_vpc.main.cidr_block, 8, 0)}"
    ipv6_cidr_block = "${cidrsubnet(aws_vpc.main.ipv6_cidr_block, 8, 0)}"
    
    map_public_ip_on_launch = true
    assign_ipv6_address_on_creation = true

    tags {
        Name = "Main"
    }
}

このコードで作成すると以下のようなサブネットが1つ作成されます。

実際にネットワークを作成する場合は、各アベイラビリティーゾーンにサブネットを作成する場合が多いですね。

cidrsubnetを使用していれば、countを使って複数のサブネットを簡単に作成できます。

resource "aws_vpc" "main" {
    cidr_block = "10.0.0.0/16"
    assign_generated_ipv6_cidr_block = true

    enable_dns_support = true
    enable_dns_hostnames = true
    tags {
        Name = "Main"
    }
}

resource "aws_subnet" "main" {
      count = 3

      vpc_id = "${aws_vpc.main.id}"
      availability_zone = "${var.availability_zones[count.index]}"
      cidr_block = "${cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)}"
      map_public_ip_on_launch = true
      ipv6_cidr_block = "${cidrsubnet(aws_vpc.main.ipv6_cidr_block, 8, count.index)}"
      assign_ipv6_address_on_creation = true

    tags {
        Name = "Main-${count.index}"
    }
}


variable "availability_zones" {
  type = "list"
  default = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}

このコードで作成すると以下のようなサブネットが作成されます。

あとがき

知ってしまえば簡単ですが、始めてIPv6なサブネットを作るのに苦労した記憶があったのでブログにまとめてみました。IPv4のみの場合でもサブネットの計算から開放されるというメリットがありますよ!