【AWS】TerraformでSubnetをモジュール化する
Terraformでは、コードの再利用性を高めるために、モジュールを活用することが推奨されています。
ここでは、Subnetをモジュール化する方法について説明します。
モジュールの作成
まず、00_modules/subnets
ディレクトリを作成し、その中に以下のファイルを作成します。
main.tf
variables.tf
outputs.tf
main.tf
main.tf
では、Subnetのリソースを定義します。
resource "aws_subnet" "rds_private_subnet_1" {
count = var.create_rds_private_subnets ? 1 : 0
availability_zone = "${var.region}a"
cidr_block = cidrsubnet(var.vpc_cidr, 8, 0)
vpc_id = var.vpc_id
tags = {
Name = "${var.environment}-rds-private-subnet-1"
}
}
resource "aws_subnet" "rds_private_subnet_2" {
count = var.create_rds_private_subnets ? 1 : 0
availability_zone = "${var.region}c"
cidr_block = cidrsubnet(var.vpc_cidr, 8, 1)
vpc_id = var.vpc_id
tags = {
Name = "${var.environment}-rds-private-subnet-2"
}
}
resource "aws_subnet" "rds_private_subnet_3" {
count = var.create_rds_private_subnets ? 1 : 0
availability_zone = "${var.region}d"
cidr_block = cidrsubnet(var.vpc_cidr, 8, 2)
vpc_id = var.vpc_id
tags = {
Name = "${var.environment}-rds-private-subnet-3"
}
}
resource "aws_subnet" "public_subnet_1" {
availability_zone = "${var.region}a"
cidr_block = cidrsubnet(var.vpc_cidr, 8, 3)
vpc_id = var.vpc_id
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public-subnet-1"
}
}
ここで注目すべきは、以下の2点です。
-
count
を使用した条件分岐 -
cidrsubnet
関数の使用
countを使用した条件分岐
count
は、リソースを複数作成する際に使用します。ここでは、var.create_rds_private_subnets
の値によって、RDS用のプライベートサブネットを作成するかどうかを制御しています。
count = var.create_rds_private_subnets ? 1 : 0
var.create_rds_private_subnets
がtrueの場合、count
は1となり、サブネットが1つ作成されます。falseの場合、count
は0となり、サブネットは作成されません。
cidrsubnet関数の使用
cidrsubnet
関数は、VPCのCIDRブロックを分割して、サブネットのCIDRブロックを計算するために使用します。
cidr_block = cidrsubnet(var.vpc_cidr, 8, 1)
この例では、var.vpc_cidr
で指定されたVPCのCIDRブロックを、8ビットのサブネットマスクで分割し、1番目のサブネットのCIDRブロックを計算しています。
例えば、var.vpc_cidr
が"10.0.0.0/16"の場合、以下のようなサブネットのCIDRブロックが計算されます。
- rds_private_subnet_1: "10.0.0.0/24" (8ビット分割, 0番目)
- rds_private_subnet_2: "10.0.1.0/24" (8ビット分割, 1番目)
- rds_private_subnet_3: "10.0.2.0/24" (8ビット分割, 2番目)
- public_subnet_1: "10.0.3.0/24" (8ビット分割, 3番目)
このように、cidrsubnet
関数を使用することで、VPCのCIDRブロックを柔軟に分割し、サブネットのCIDRブロックを自動的に計算することができます。
variables.tf
variables.tf
では、モジュールで使用する変数を定義します。
variable "environment" {
description = "環境名 (dev, stg, prd)"
type = string
}
variable "vpc_id" {
description = "VPC ID"
type = string
}
variable "region" {
description = "AWSリージョン"
type = string
default = "ap-northeast-1"
}
variable "vpc_cidr" {
description = "VPCのCIDRブロック"
type = string
default = "172.31.0.0/16"
}
variable "create_rds_private_subnets" {
description = "RDS用のプライベートサブネットを作成するかどうか"
type = bool
default = true
}
outputs.tf
outputs.tf
では、モジュールの出力値を定義します。
output "rds_subnet_ids" {
value = [
aws_subnet.rds_private_subnet_1[0].id,
aws_subnet.rds_private_subnet_2[0].id,
aws_subnet.rds_private_subnet_3[0].id
]
}
output "public_subnet_1_id" {
value = aws_subnet.public_subnet_1.id
}
モジュールの使用
作成したSubnetモジュールを使用するには、main.tf
で以下のように記述します。
module "subnets" {
source = "./00_modules/subnets"
environment = var.environment
vpc_id = module.vpc.vpc_id
}
これにより、各環境に応じたSubnetを柔軟に作成することができます。
まとめ
Subnetをモジュール化することで、コードの再利用性が高まり、管理がしやすくなります。
環境ごとに異なる設定を適用する場合でも、モジュールを活用することで、コードの重複を避けることができます。
また、count
を使用した条件分岐やcidrsubnet
関数の使用により、より柔軟かつ自動化されたサブネットの作成が可能になります。
Discussion
記事を否定する意図はないけど、公式モジュールがあるものは公式モジュールを使いましょう
ちなみに、ぱっと見でしかないですが、サブネットを配置するazを決め打ちしているので、リージョンが変わるとazの記号は変わってしまって役に立ちません(例えばパリ{eu-west-3}はa,b,cです)