AWSにRails + Nginxな環境をTerraformで構築してみようと思います。
はじめに
本連載で一つずつインフラを構築していきます。
ドメインのhttps化したり、ECSを使用したコンテナオーケストレーションを用いてアプリケーションをデプロイします。
この記事ではネットワーク環境の構築を行います。
環境は以下です。
| OS | Cataline 10.15.6 |
| Terraform | 0.14.4 |
基本構文などこちらにまとめてますので、よかったらみてください!
AWS Terraform 基本コード まとめ
連載一覧
- terraform AWS環境構築 事前準備
- 【ネットワーク環境構築】terraform AWS環境構築 第1回 ←ここ
- 【ドメインhttps化・ACM(SSL)証明書発行】terraform AWS環境構築 第2回
- 【ロードバランサー構築】terraform AWS環境構築 第3回
- 【ECS Fargate(nginx)実行】terraform AWS環境構築 第4回
- 【RDS構築】terraform AWS環境構築 第5回
- 【Docker/ECR作成】terraform AWS環境構築 第6回
- 【ECS Fargate(rails + nginx)実行】terraform AWS環境構築 第7回
- 【CircleCIによるCI/CD】terraform AWS環境構築 番外
やること
以下の定義と作成をします。
ネットワーク環境構築
基本ファイル作成
インフラを構築する、基本インプット変数を定義しておきます。
./variable.tf
variable "aws_region" {
type = string
default = "ap-northeast-1"
}
variable "aws_profile" {
type = string
default = "default"
description = "AWS CLI's profile"
}
variable "app_name" {
type = string
default = "rails_hello"
}
variable "domain" {}
./provider.tf
provider "aws" {
region = var.aws_region
profile = var.aws_profile
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.27"
}
}
}
./terraform.tfvars
domain = "<your domain>"
./backend.tf
terraform {
backend "s3" {}
}
networkモジュールの作成
ネットワーク環境を定義するモジュールを作成します。
terraformフォルダ内にnetworkフォルダを作成しましょう。
networkモジュールを使用できるように./main.tfに以下の記述を追記します。
module "network" {
source = "./network"
app_name = var.app_name
}
networkモジュール内でapp_nameを受け取れるように、variable.tfを用意します。
./network/variable.tf
variable "app_name" {}
ディレクトリ構成は以下のようにしています。
[terraform] $ tree . ├── network │ ├── main.tf │ └── variable.tf ├── env │ └── backend.config ├── main.tf ├── backend.tf ├── provider.tf ├── terraform.tfvars └── variable.tf
用意できたら、terraformの初期化を行いましょう。
[terraform] $ terraform init -backend-config=env/backend.config -upgrade
VPCの作成
まずは、vpcの定義とインプット変数を定義します。
./network/variable.tf に以下を追記します。
variable "app_name" {}
variable "vpc_cidr" {
default = "135.0.0.0/16"
}
./network/main.tf に以下を追記します。
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr
tags = {
Name = var.app_name
}
}
- cidr_block:VPCのCIDRブロック
- tags:タグ
これでvpcの定義は完了です。
terraform plan, apply して作成されるか見てみましょう。

これで、vpcの作成は完了です。
パブリック・プライベートサブネットの作成
次に、パブリック・プライベートサブネットの定義とインプット変数を定義します。
./network/variable.tf に以下を追記します。
variable "public_subnet_cidrs" {
default = ["135.0.0.0/24", "135.0.1.0/24", "135.0.2.0/24"]
}
variable "private_subnet_cidrs" {
default = ["135.0.10.0/24", "135.0.11.0/24", "135.0.12.0/24"]
}
variable "azs_name" {
type = list(string)
default = ["1a", "1c", "1d"]
}
./network/main.tf に以下を追記します。
esource "aws_subnet" "public_subnets" {
# public_subnet_cidrs分、繰り返す
count = length(var.public_subnet_cidrs)
# 先程作成したvpc
vpc_id = aws_vpc.vpc.id
availability_zone = var.azs[count.index]
cidr_block = var.public_subnet_cidrs[count.index]
map_public_ip_on_launch = true # パブリックIP割当
tags = {
Name = "${var.app_name}-public-${var.azs_name[count.index]}"
}
}
resource "aws_subnet" "private_subnets" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.vpc.id
availability_zone = var.azs[count.index]
cidr_block = var.private_subnet_cidrs[count.index]
tags = {
Name = "${var.app_name}-private-${var.azs_name[count.index]}"
}
}
- vpc_id:紐付けるVPCのID
- availability_zone:サブネット配置のアベイラビリティゾーン
- cidr_block:サブネットのCIDRブロック
- map_public_ip_on_launch:当該サブネットで起動したインスタンスにパブリックIPアドレスを割り当の有無
- tags:タグ
terraform plan, apply して作成されるか見てみましょう。

これで、パブリック・プライベートサブネットの作成は完了です。
インターネットゲートウェイの作成
vpcがインターネットが接続できるように、インターネットゲートウェイの定義をします。
./terraform/main.tf に以下を追記します。
resource "aws_internet_gateway" "igw" {
# 先程作成したvpc
vpc_id = aws_vpc.vpc.id
tags = {
Name = var.app_name
}
}
- vpc_id:紐付けるVPCのID
terraform plan, apply して作成されるか見てみましょう。

これで、「Attached」されていればインターネットゲートウェイの作成は完了です。
ルートテーブルの作成
通信をルートできるように、ルートテーブルの定義をします。
./terraform/main.tf に以下を追記します。
# インターネットへのルート
resource "aws_route" "public" {
route_table_id = aws_vpc.vpc.default_route_table_id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
# パブリック用のルートテーブルとパブリックサブネットの関連付け
resource "aws_route_table_association" "public" {
count = length(var.public_subnet_cidrs)
# *.idでサブネットIdを配列を取得
# element()で、配列のindexのIdを取得
subnet_id = element(aws_subnet.public_subnets.*.id, count.index)
route_table_id = aws_vpc.vpc.default_route_table_id
}
# プライベート用のルートテーブル作成
resource "aws_route_table" "private" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.app_name}-private-rtb"
}
}
# プライベート用のルートテーブルとプライベートサブネットの関連付け
resource "aws_route_table_association" "private" {
count = length(var.private_subnet_cidrs)
# *.idでプライベートIdを配列を取得
# element()で、配列のindexのIdを取得
subnet_id = element(aws_subnet.private_subnets.*.id, count.index)
route_table_id = aws_route_table.private.id
}
- aws_route
- route_table_id:ルート設定するルートテーブルID
- destination_cidr_block:ルートの送信先
- gateway_id:インターネットゲートウェイのID
- aws_route_table_association
- subnet_id:紐付けるサブネットID
- route_table_id:紐付け対象のルートテーブルID
- aws_route_table
- vpc_id:VPCのID
terraform plan, apply して作成されるか見てみましょう。
パブリック用ルートテーブル


プライベート用ルートテーブル


これで、ルートテーブルの定義と作成は完了です。
まとめ
vpc・サブネットのidはロードバランサー構築等で使用するので、アウトプット変数を定義しておきましょう。
./network/output.tf
output "vpc_id" {
value = aws_vpc.vpc.id
}
output "public_subnet_ids" {
value = aws_subnet.public_subnets.*.id
}
output "private_subnet_ids" {
value = aws_subnet.private_subnets.*.id
}
./output.tf
output "vpc_id" {
value = module.network.vpc_id
}
output "public_subnet_ids" {
value = module.network.public_subnet_ids
}
output "private_subnet_ids" {
value = module.network.private_subnet_ids
}
今回、作成したコードとディレクトリ構成は以下になります。
[terraform] $ tree . ├── network │ ├── main.tf │ ├── output.tf │ └── variable.tf ├── env │ └── backend.config ├── main.tf ├── output.tf ├── backend.tf ├── provider.tf ├── terraform.tfvars └── variable.tf
.network/main.tf
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr
tags = {
Name = var.app_name
}
}
resource "aws_subnet" "public_subnets" {
count = length(var.public_subnet_cidrs)
vpc_id = aws_vpc.vpc.id
availability_zone = var.azs[count.index]
cidr_block = var.public_subnet_cidrs[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.app_name}-public-${var.azs_name[count.index]}"
}
}
resource "aws_subnet" "private_subnets" {
count = length(var.private_subnet_cidrs)
vpc_id = aws_vpc.vpc.id
availability_zone = var.azs[count.index]
cidr_block = var.private_subnet_cidrs[count.index]
tags = {
Name = "${var.app_name}-private-${var.azs_name[count.index]}"
}
}
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = var.app_name
}
}
resource "aws_route" "public" {
route_table_id = aws_vpc.vpc.default_route_table_id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
resource "aws_route_table_association" "public" {
count = length(var.public_subnet_cidrs)
subnet_id = element(aws_subnet.public_subnets.*.id, count.index)
route_table_id = aws_vpc.vpc.default_route_table_id
}
resource "aws_route_table" "private" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = "${var.app_name}-private-rtb"
}
}
resource "aws_route_table_association" "private" {
count = length(var.private_subnet_cidrs)
subnet_id = element(aws_subnet.private_subnets.*.id, count.index)
route_table_id = aws_route_table.private.id
}
./network/variable.tf
variable "app_name" {}
variable "azs" {
type = list(string)
default = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}
variable "azs_name" {
type = list(string)
default = ["1a", "1c", "1d"]
}
variable "vpc_cidr" {
default = "135.0.0.0/16"
}
variable "public_subnet_cidrs" {
default = ["135.0.0.0/24", "135.0.1.0/24", "135.0.2.0/24"]
}
variable "private_subnet_cidrs" {
default = ["135.0.10.0/24", "135.0.11.0/24", "135.0.12.0/24"]
}
おわり
これで、ネットワーク環境の構築は完了しました。お疲れさまでした!
何か疑問に思うことがあれば、何でもコメントしてください!
次回は、ドメインのhttps化・ACM(SSL)証明書のリクエストを行います。

コメント