はじめに
現在CloudformationとTerraformを学習しています。
先日以下記事を書きました。
CloudFormationでVPC、サブネット、インターネットゲートウェイを作成する
これと同じようなこと(=全く同じではない)をTerraformで作成しました。
まだどちらもそこまで試してないですが、Terraformの方が良い感触です。
% terraform --version
Terraform v0.12.26
ディレクトリ構造
Terraformではディレクトリを役割、環境毎に分けた方が良いとのことです。
今回は役割ごと分割にします。結果以下のようなディレクトリ構造としました。
% tree
.
├── README.md
├── main.tf
├── modules
│ ├── alb
│ │ ├── Create-alb.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── ec2
│ │ ├── Create-ec2.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── rds
│ │ ├── Create-rds.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── security_group
│ │ ├── Create-securitygroup.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── vpc #本記事で作成
│ ├── Create-vpc.tf
│ ├── outputs.tf
│ └── variables.tf
├── outputs.tf
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf
コード
main.tfの作成
Terraformルートディレクトリに設置したmain.tf
には使用するモジュールをメインで書いておきます。
この後作成するvpcモジュールと、プロバイダー情報(今回はAWS)を記載します。(ec2,rds,albなどは別記事で書きます)
vpc_config
内は環境に合わせて書いてください。必要に応じて変数の追加も出来ます。
provider "aws" {
region = "ap-northeast-1"
}
module vpc {
source = "./modules/vpc"
vpc_config = {
NameTag = "Terraform"
cidr_block = "10.2.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
subnet_count = 2
}
}
変数の作成
vpcに関する変数なので、modules/vpc
ディレクトリ内にvariables.tf
を作成し、module vpc
で定義した変数をinputします。
string
やbool
などの型を定義してますが、分からなければany
でも大丈夫です。
variable "vpc_config" {
type = object({
NameTag = string
cidr_block = string
enable_dns_support = bool
enable_dns_hostnames = bool
subnet_count = number
})
}
vpcを作成するコード本体の作成
サブネットなど同一構成の場合は作成したい数分count = int
を定義する。
ただcount
だと一部だけ削除が出来ないのでfor_each
にした方がいいかもしれない。
# アベイラリティゾーンの取得
data "aws_availability_zones" "available" {
state = "available"
}
# Cretae VPC
resource "aws_vpc" "MyFirstVPC" {
cidr_block = var.vpc_config.cidr_block
enable_dns_hostnames = var.vpc_config.enable_dns_hostnames
enable_dns_support = var.vpc_config.enable_dns_support
tags = {
Name = "${var.vpc_config.NameTag}-VPC"
}
}
# Cretae IGW
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.MyFirstVPC.id
tags = {
Name = "${var.vpc_config.NameTag}-IGW"
}
}
# Cretae Subnets
resource "aws_subnet" "public" {
count = var.vpc_config.subnet_count
vpc_id = aws_vpc.MyFirstVPC.id
cidr_block = cidrsubnet(aws_vpc.MyFirstVPC.cidr_block, 8, count.index) #10.2.0.0/24,10.2.1.0/24
map_public_ip_on_launch = true
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${var.vpc_config.NameTag}-PublicSubnet${count.index}"
}
}
resource "aws_subnet" "private" {
count = var.vpc_config.subnet_count
vpc_id = aws_vpc.MyFirstVPC.id
cidr_block = cidrsubnet(aws_vpc.MyFirstVPC.cidr_block, 8, count.index + var.vpc_config.subnet_count) #10.2.2.0/24,10.2.3.0/24
map_public_ip_on_launch = false
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${var.vpc_config.NameTag}-PrivateSubnet${count.index}"
}
}
# Cretae RouteTables
resource "aws_route_table" "public" {
vpc_id = aws_vpc.MyFirstVPC.id
tags = {
Name = "${var.vpc_config.NameTag}-PublicRT"
}
}
resource "aws_route_table" "private" {
vpc_id = aws_vpc.MyFirstVPC.id
tags = {
Name = "${var.vpc_config.NameTag}-PrivateRT"
}
}
# Cretae Route
resource "aws_route" "public" {
route_table_id = aws_route_table.public.id
gateway_id = aws_internet_gateway.igw.id
destination_cidr_block = "0.0.0.0/0"
}
# Association RouteTables
resource "aws_route_table_association" "public" {
count = var.vpc_config.subnet_count
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "private" {
count = var.vpc_config.subnet_count
subnet_id = aws_subnet.private[count.index].id
route_table_id = aws_route_table.private.id
}
outputの作成
他のモジュールでIDや値を使うために必要な情報をoutputします。
output "vpc_id" {
value = aws_vpc.MyFirstVPC.id
}
output "vpc_cidr" {
value = aws_vpc.MyFirstVPC.cidr_block
}
output "public_subnet_id" {
value = aws_subnet.public[*].id
}
output "private_subnet_id" {
value = aws_subnet.private[*].id
}
コードの実行
% terraform plan
% terraform apply
PS:変数やループで固めておくと単純構成なら楽なんですが、一部だけ変えたい時にやりにくいかもですね。。