🥅

【ネットワークその1-VPC/IPAM編】Terraform×AWS学習記録

2024/07/11に公開

はじめに

こんにちは。awa(あわ)です。

業務上でterraformを使用してAWSの環境構築をすることになったので、より理解度を深めるため、AWSの各サービスの概要や設定項目の詳細、それに絡めたtarraformコードの書き方についてざざっと覚え書きを残すことにしました。

⚠注意
tarraform、AWSともにアップデートされるサイクルが早いサービスのため、古い情報が混じっていることがあります。
また、自分用に後から見返せるようにまとめたので、分かりにくかったり間違えていたりする部分があるかと思いますがご了承ください。
Terraformのバージョンはv1.7.5になります。

(1) VPCとは

Amazon Virtual Private Cloud (Amazon VPC) とは、リソースの配置、接続性、セキュリティなど、仮想ネットワーク環境をフルで制御できるサービスです。

https://aws.amazon.com/jp/vpc/

AWSリソースを起動する環境のベースとなる仮想ネットワーク。
このVPC上にAWSで利用できる様々なリソースを設置し、組み立てていく。
個別に通信できたり、VPC内に組み込まないAWSリソースもあったりするものの、リソースをグルーピングすることで可用性や拡張性などを得られるメリットがある。

(2) IPAMとは

Amazon VPC IP Address Manager (IPAM)は、AWS ワークロードの IP アドレスを計画、追跡、監視しやすくする VPC 機能です。IPAM の自動ワークフローを使用して、IP アドレスをより効率的に管理できます。

https://docs.aws.amazon.com/ja_jp/vpc/latest/ipam/what-it-is-ipam.html

アドレスを一元管理できるVPC機能のこと。
IPアドレスをグルーピングし、ルールを設定することにより、手動で行ってきたIPアドレスの割当てを自動化したり、これまでのスプレッドシートなどを使用して管理する手間がなくなるといったメリットがある。

【IPAMに関する用語】
・スコープ
IPAMで最上位に位置するネットワークのこと。IPAMで一番大きい単位。
IPAMを作成したら自動的にパブリックスコープとプライベートスコープが作成される。

・プール
スコープの中で区分けされたネットワークのこと。CIDRの集合体であり、このプールに設定した範囲でIPアドレスが割り当てられる。
ある1つのプールの中に開発用と本番用の2つのプールを作成するといった多重構造にも対応。

Amazon VPCではCIDRブロックを設定する際、手動でIPアドレスを入力するか、事前に作成したIPAMプールに割り当てられているCIDRブロックのいずれかを選択することができる。

(3) 関連用語

CIDR/CIDRブロック

Classless Inter-Domain Routing (CIDR) は、インターネット上のデータルーティング効率を向上させる IP アドレス割り当て方法です。インターネットに接続するすべてのマシン、サーバー、およびエンドユーザーデバイスには、IP アドレスと呼ばれる固有の番号が関連付けられています。デバイスは、これらの IP アドレスを使用して相互に検索し、通信します。組織は CIDR を使用して、ネットワークに IP アドレスを柔軟かつ効率的に割り当てます。

https://aws.amazon.com/jp/what-is/cidr/

従来のクラスフルアドレッシングではIPアドレスをx.x.x.xと表記していた。
例)192.168.1.2
また、IPアドレスのグループを「クラス」という単位で定義していた。

【クラスA】
・先頭は0始まり
・IPアドレスの範囲は0.x.x.x~127.x.x.x
・ネットワークの数は128個
・1つのネットワークで使用できるIPアドレスの数は16,777,216個(256³)

【クラスB】
・先頭は10始まり
・IPアドレスの範囲は128.x.x.x~191.x.x.x
・ネットワークの数は16,384個
・1つのネットワークで使用できるIPアドレスの数は65,536個(256²)

【クラスC】
・先頭は110始まり
・IPアドレスの範囲は192.x.x.x~223.x.x.x
・ネットワークの数は2,097,152個
・1つのネットワークで使用できるIPアドレスの数は256個

この方法ではネットワーク部が固定である関係上、1つのネットワークで使用できるIPアドレスの数に差がありすぎるため、IPアドレスを余分に抱えてしまう問題点があった。
例えば、使用したいIPアドレスの数が257個だとしたら、クラスCでは足りないのでクラスBが適切となる。しかし、そうするとほとんどのIPアドレスが使用されず無駄になってしまう。

サブネット

この問題を解消するために登場した概念がサブネット
ざっくりいうと1つのネットワーク内に存在する更に細かいネットワークのこと。
サブネットを使用するために付随して登場したのがCIDR(Classless Inter-Domain Routing)で、IPアドレスの表記は「x.x.x.x/x」となる。

CIDRは名前にClasslessとあるとおり、ネットワーク部が固定であったクラスフルアドレッシングとは異なり、ネットワーク部とホスト部の範囲を自由に設定できる。
これにより、IPアドレスの浪費を防ぐことが可能になった反面、使用可能なIPアドレスの範囲がパッと見分からなくなる弱点があった。
(例えば、クラスフルアドレッシングの場合、先頭が110だったら「使用可能なIPアドレスの数は256個なんだな〜」と容易に判別できる。クラスという概念が消失したCIDRでは先頭の数字が意味を成さない。)

そこで、IPアドレスの末尾に/(スラッシュ)と数字を付け足し、この情報でどこまでがネットワーク部なのか?どこからがホスト部なのか?を判別できるようにした。この「/【数字】」をプレフィックスと呼ぶ。

プレフィックスは「先頭から指定した数字ぶんのbitがネットワーク部である」という意味で、例えば「192.168.1.2/24」というIPアドレスがある場合、先頭から24bitまでがネットワーク部であることを指し示す。
IPアドレスは8bit×4の合計32bitで構成されているため、先頭から24bitがネットワーク部であるならば、これはクラスフルアドレッシングでいうところのクラスCに相当するということになる。

また、CIDRブロックとは、同じネットワーク部とビット数を共有する IP アドレスの集まりのこと。つまり、大元となるVPCとその中にある複数のサブネットのIPアドレスを1つにグループ化したもの。

Amazon VPCをプロビジョニングする際には、このCIDRブロックの設定が必要となる。
サブネットに関しては作成しなければ不具合を起こすわけではないが、可用性などを確保するためには作成はほぼ必須と言える。(実際に作成するところは次の記事で取り上げる予定)

(4) 設定項目

Terraformコードとマネジメントコンソールで設定する際にどの項目に当たるかを対比しつつ、Terraform公式ドキュメントをベースに設定項目の詳細をメモ。
※日本語表記の部分がマネジメントコンソール上の項目名、()の中の英語表記の部分がterraform上の項目名

IPAMを使用しない場合

■VPC(aws_vpc)の設定項目

 #VPC resource "aws_vpc" "main" {
  cidr_block       = "10.0.0.0/16" #・・・(1)
  instance_tenancy = "default" #・・・(2)

  tags = {
    Name = "main" # ・・・(3)
  }
}

(1) IPv4 CIDR(cidr_block)
必須。IPAMを使用しない場合は「x.x.x.x/x」を手動入力。
(2) テナンシー(instance_tenancy)
オプション。EC2インスタンスのテナンシー属性。detaultの他にdedicated(専有)が選べるが、こちらを選ぶとこのVPC内で起動したインスタンスはすべて専用テナントインスタンスとなる。
(3) 名前タグ(Name)
オプション。タグブロックで設定。
VPC名を識別するために便利なので設定しておくと便利。


IPAMを使用する場合

IPAMを使用する場合はVPCを含めて以下4つのリソース設定を行う必要がある。

  • IPAM
  • IPAMプール
  • IPAMプールのCIDR
  • VPC

■IPAM(aws_vpc_ipam)の設定項目

data "aws_region" "current" {
 name = "ap-northeast-1"
}

#IPAM resource "aws_vpc_ipam" "test" {
 description = "My IPAM" #・・・(4)
 operating_regions {
   region_name = data.aws_region.current.name #・・・(5)
 }
 #cascade = false ・・・(6)

 tags = {
   Test = "Main" #・・・(7)
 }
}

(4) 説明(description)
オプション。IPAMについての簡単な説明を記載する。
(5)運用リージョン(operating_regions)
必須。IPAMプールを割り当てるリージョン。マネジメントコンソールではデフォルトで現在のリージョンが選択されている。
複数のリージョンを指定することもできるが、現在のリージョンは必ず含める必要がある。
(6)カスケード(cascade)
オプション。IPAMを削除する際に使用する。
有効にすると、IPAMの削除と同時にプライベートスコープ、プライベートスコープ内のプール、およびプライベートスコープ内のプールのすべての割り振りを削除する。パブリックスコープにプールがある場合、このオプションを使用して IPAM を削除することはできない。
(7) 名前タグ(Name)
オプション。タグブロックで設定。
VPC名を識別するために便利なので設定しておくと便利。


■IPAMプール(aws_vpc_ipam_pool)の設定項目

#IPAMプール
resource "aws_vpc_ipam_pool" "test" {
  address_family                    = "ipv4" #・・・(8)
  ipam_scope_id                     = aws_vpc_ipam.test.private_default_scope_id #・・・(9)
  locale                            = data.aws_region.current.name #・・・(10)
  allocation_default_netmask_length = 16 #・・・(11)
  #allocation_max_netmask_length     = 20 #・・・(12)
  #allocation_min_netmask_length     = 10 #・・・(13)
  allocation_resource_tags          = ["testpool"] #・・・(14)
  auto_import                       = false #・・・(15)
  #aws_service                       = "ec2" #・・・(16)
  #cascade                           = true #・・・(17)
  description                       = "This is private pool for test" #・・・(18)
  #public_ip_source                  = "byoip" #・・・(19)
  #publicly_advertisable             = false #・・・(20)
  #source_ipam_pool_id               = "xxxx" #・・・(21)
}

(8) アドレスファミリー(address_family)
必須。プールに割り当てるIPプロトコル。IPv4 または IPv6 プロトコルのいずれかを選択。
(9) IPAM スコープ(ipam_scope_id)
必須。プールを作成するスコープのID。
(10) ロケール(locale)
オプション。プールが作成されるリージョン。IPAMで設定した運用リージョンの中から選択。
(11) デフォルトのネットマスク長(allocation_default_netmask_length)
オプション。プールに割り当てられるデフォルトのCIDRのネットマスク長(=サブネット部の数字を指定)
(12) ネットマスクの最大長(allocation_max_netmask_length)
オプション。プールに割り当てられるCIDRの最大のネットマスク長。
(13) ネットマスクの最小長(allocation_min_netmask_length)
オプション。プールに割り当てられるCIDRの最小のネットマスク長。
(14) タグコンプライアンス(allocation_resource_tags)
オプション。この IPAM プールの CIDR を使用するリソースに必要なタグ。自動的にインポートされたリソースのうち、これらのタグを持たないリソースは、非準拠としてマークされる。
(15) 自動インポート(auto_import)
オプション。自動インポートを許可した場合、プール内のCIDR範囲内にあるスコープ内のすべてのVPCなどのリソースを自動的にインポートする。
(16) サービス(aws_service)
オプション。パブリックスコープのみで使用可能。
プールを使用できるAWSサービスを制限できる。"ec2"のみ設定可。
(17) カスケード(cascade)
オプション。IPAMを削除する際に使用する。
(18) 説明(description)
オプション。IPAMプールについての簡単な説明を記載する。
(19) パブリック IP ソース(public_ip_source)
パブリック スコープ内のプールの IP アドレス ソース。パブリック スコープ内のプールに IP アドレス CIDR をプロビジョニングする場合にのみ使用される。"byoip"か"amazon"から選択可能(デフォルトはbyoip)
(20) アドバタイザビリティ(publicly_advertisable)
オプション。(8)アドレスファミリーを IPv6にし、(19)パブリック IP ソースを"byoip"にした場合のみ使用可能。このプール内の CIDR が Amazon Web Services のサービスからのアドバタイズの対象となるかどうかを選択する。
(21) ソース(source_ipam_pool_id)
オプション。このプールを指定したプールの中にある子プールとする際に使用。ソースプール(最上位のソース)の場合は選択不可。


■IPAMプールのCIDR(aws_vpc_ipam_pool_cidr)の設定項目

#IPAMプールに割り当てるCIDR
resource "aws_vpc_ipam_pool_cidr" "test" {
  ipam_pool_id   = aws_vpc_ipam_pool.test.id #・・・(22)
  cidr           = "172.20.0.0/16" #・・・(23)
# netmask_length = 16 #・・・(24)
#  cidr_authorization_context {
#    message   = "message" #・・・(25)
#    signature = "signiture"  #・・・(26)
#  }
}

(22) IPAMプールID(ipam_pool_id)
必須。CIDRを割り当てるプールのID。
(23) CIDR(cidr)
オプション。プールに割り当てるCIDR。ネットワーク長と競合するので、どちらか1つを設定すればOK。
(24) ネットマスク長(netmask_length)
オプション。このプールに割り当てられるCIDRが指定された長さのネットマスク長を持つようになる。
(25) メッセージ(message)
オプション。プレフィックスとアカウントのプレーンテキスト認証メッセージ。cidr_authorization_contextブロックの中に記述。
(26) 署名(signiture)
オプション。プレフィックスとアカウントの署名された承認メッセージ。cidr_authorization_contextブロックの中に記述。


■VPC(aws_vpc)の設定項目

 #VPC resource "aws_vpc" "test" {
  ipv4_ipam_pool_id                    = aws_vpc_ipam_pool.test.id #・・・(27)
  ipv4_netmask_length                  = 28 #・・・(28)
#  ipv6_cidr_block                      = "x.x.x.x/x" #・・・(29)
#  ipv6_ipam_pool_id                    = aws_vpc_ipam_pool.test.id #・・・(30)
#  ipv6_netmask_length                  = 56 #・・・(31)
#  pv6_cidr_block_network_border_group  = "us-east-1" #・・・(32)
#  enable_dns_support                   = true #・・・(33)
#  enable_network_address_usage_metrics = true #・・・(34)
#  enable_dns_hostnames                 = true #・・・(35)
#  assign_generated_ipv6_cidr_block     = false #・・・(36)
  depends_on                           = [
    aws_vpc_ipam_pool_cidr.test
  ]
}

(27) IPv4 IPAM プール(ipv4_ipam_pool_id)
オプション。このVPCに対してCIDRを割り当てるために使用するIPv4IPAMプールのID。IPAM割当のIPv4CIDRブロックからCIDRブロックの割当てをする際のみ使用可能。
(28) IPv4ネットマスク(ipv4_netmask_length)
オプション。このVPCに対して割り当てるIPv4CIDRのネットマスクの長さ。
IPAM割当のIPv4CIDRブロックからCIDRブロックの割当てをする際のみ使用可能。
(31) IPv6CIDRブロック(ipv6_cidr_block)
オプション。IPAMプールから要求するCIDRブロック。
IPv6ネットマスクで指定してもOK。
(30) IPv6 IPAM プール(ipv6_ipam_pool_id)
オプション。このVPCに対してCIDRを割り当てるために使用するIPv6IPAMプールのID。IPAM割当のIPv6CIDRブロックからCIDRブロックの割当てをする際のみ使用可能。
(31) IPv6ネットマスク(ipv6_netmask_length)
オプション。このVPCに対して割り当てるIPv6CIDRのネットマスクの長さ。
IPAM割当のIPv6CIDRブロックからCIDRブロックの割当てをする際のみ使用可能。有効な値は"56"で、IPAMプールで設定した(11) デフォルトのネットマスク長(allocation_default_netmask_length)があれば省略可能。
(32) ネットワークボーダーグループ(ipv6_cidr_block_network_border_group)
オプション。指定するとパブリック アドレスのアドバタイズを LocalZones などの特定のネットワーク境界グループに制限することができる。Amazon 提供の IPv6 CIDR ブロック(assign_generated_ipv6_cidr_block)を選択したときのみ使用可能。
(33) DNS 解決(enable_dns_support)
オプション。DNS 解決を有効/無効にするブールフラグ。デフォルトは true。VPCと同時にサブネットやルートテーブルなどのリソースも作成する場合のみ選択可能。
(34) Network Address Usage メトリクス(enable_network_address_usage_metrics)
オプション。VPC でネットワーク アドレス使用状況メトリック(仮想ネットワーク内のリソースに適用されるメトリクスで、VPC のサイズを計画および監視するのに役立つ)が有効になっているかどうかを示す。デフォルトは false。マネジメントコンソールでは初期設定のときにはこの項目は表示されないので、作成済みのVPCを編集して追加する必要がある。
(35) DNS ホスト名(enable_dns_hostnames)
オプション。VPC 内の DNS ホスト名を有効/無効にするブールフラグ。デフォルトは false。VPCと同時にサブネットやルートテーブルなどのリソースも作成する場合のみ選択可能。
(36) Amazon 提供の IPv6 CIDR ブロック(assign_generated_ipv6_cidr_block)
VPC の /56 プレフィックス長を持つ Amazon 提供の IPv6 CIDR ブロックをリクエストする。IP アドレスの範囲や CIDR ブロックのサイズを指定することはできない。デフォルトはfalse。

(5)実際にプロビジョニングしてみた

上記のterraformコードをベースに少し手を加えて簡単なVPCとIPAMをプロビジョニングしてみた。
今回は1つのVPCと、プライベートスコープの中に1つのIPv4CIDRを割り当てたプールをもつIPAMをプロビジョニングする。

terraform plan実行結果

Terraform will perform the following actions:

  # aws_vpc.test will be created
  + resource "aws_vpc" "test" {
      + arn                                  = (known after apply)
      + cidr_block                           = (known after apply)
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_dns_hostnames                 = (known after apply)
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv4_ipam_pool_id                    = (known after apply)
      + ipv4_netmask_length                  = 28
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags                                 = {
          + "Name" = "test"
        }
      + tags_all                             = {
          + "Name" = "test"
        }
    }

  # aws_vpc_ipam.test will be created
  + resource "aws_vpc_ipam" "test" {
      + arn                                       = (known after apply)
      + default_resource_discovery_association_id = (known after apply)
      + default_resource_discovery_id             = (known after apply)
      + description                               = "My IPAM"
      + id                                        = (known after apply)
      + private_default_scope_id                  = (known after apply)
      + public_default_scope_id                   = (known after apply)
      + scope_count                               = (known after apply)
      + tags                                      = {
          + "Test" = "Main"
        }
      + tags_all                                  = {
          + "Test" = "Main"
        }
      + tier                                      = "advanced"

      + operating_regions {
          + region_name = "ap-northeast-1"
        }
    }

  # aws_vpc_ipam_pool.test will be created
  + resource "aws_vpc_ipam_pool" "test" {
      + address_family                    = "ipv4"
      + allocation_default_netmask_length = 16
      + arn                               = (known after apply)
      + auto_import                       = false
      + description                       = "This is private pool for test"
      + id                                = (known after apply)
      + ipam_scope_id                     = (known after apply)
      + ipam_scope_type                   = (known after apply)
      + locale                            = "ap-northeast-1"
      + pool_depth                        = (known after apply)
      + state                             = (known after apply)
      + tags_all                          = (known after apply)
    }

  # aws_vpc_ipam_pool_cidr.test will be created
  + resource "aws_vpc_ipam_pool_cidr" "test" {
      + cidr              = "172.20.0.0/16"
      + id                = (known after apply)
      + ipam_pool_cidr_id = (known after apply)
      + ipam_pool_id      = (known after apply)
    }

Plan: 4 to add, 0 to change, 0 to destroy.

terraform apply実行結果

■VPC

■IPAM


プライベートとパブリック2つのスコープが作成されている

■スコープ


プライベートスコープ内に1つプールが作成されている

■プール

おわりに

基本情報を勉強していたときからネットワーク周りは苦手意識がある。。。
このあたりは経験と勘がものを言う気がする。
まだ完全に飲み込めていない部分もちらほらあるけど、一通りAWSの学習を終えてまた復習したら新しく分かることも多いのかもしれない。

次回↓
ネットワーク編の続き
サブネット、Elastic IPアドレス、インターネット・NATゲートウェイに触れてみる編
https://zenn.dev/awa4989/articles/6501b02b2ab412

参考リンク

■VPCの概要

https://qiita.com/c60evaporator/items/2f24d4796202e8b06a77

■tarraform公式ドキュメント(VPC)

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc

■CIDRについて

https://envader.plus/article/52

■IPAMについて

https://docs.aws.amazon.com/ja_jp/vpc/latest/ipam/how-it-works-ipam.html

Discussion