【大阪 / 横浜 / 徳島】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜 / 徳島】インフラ / サーバーサイドエンジニア募集中!

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【WordPress 専用】クラウドサーバー『ウェブスピード』

【WordPress 専用】クラウドサーバー『ウェブスピード』

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【予約システム開発】EDISONE カスタマイズ開発サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【200ヶ国以上に対応】グローバル eSIM「ビヨンドSIM」

【200ヶ国以上に対応】グローバル eSIM「ビヨンドSIM」

【中国への旅行・出張・駐在なら】中国SIMサービス「チョコSIM」

【中国への旅行・出張・駐在なら】中国SIMサービス「チョコSIM」

【グローバル専用サービス】北米・中国でも、ビヨンドのMSP

【グローバル専用サービス】北米・中国でも、ビヨンドのMSP

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

[terraform] AWSで3層ネットワーク構成を構築するmoduleを書いてみた

インフラエンジニアの寺岡です。

今回はterraformのmoduleについてのお話しです。

AWSのネットワークをPublic/DMZ/Privateの3層に分割する構成を一気に構築できる
かつどの案件でも使いまわせるようなmoduleを自作しましたのでまとめておきますー。

当記事に記載するコードを実行すると以下のような構成をAWS上にデプロイすることが出来ます。

マルチAZかつDMZのsubnetはNATGatewayを経由して外部と通信を行います。

Publicのsubnetは直接InternetGatewayと通信を行い
Privateのsubnetはローカル間通信のみとなっています。

一見複雑そうですが割とよく見る構成ではないでしょうか。

この構成をterraformでモジュール化した結果が以下のようになります。

■moduleに渡す値の変数を定義する

まずはmoduleに渡すための値をvariableで定義しておきます。

variable "vpc_config" {
  default = {
    project           = "tf-moduletest"
    environment       = "stg"
    cidr_block        = "10.10.0.0/16"     
  }
}

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

variable "public_subnets" {
  default = ["10.10.0.0/20","10.10.16.0/20"]
}

variable "dmz_subnets" {
  default = ["10.10.32.0/20","10.10.48.0/20"]
}

variable "private_subnets" {
  default = ["10.10.64.0/20","10.10.80.0/20"]
}

■moduleを記述する

この部分が今回の本題です。

variableで定義した値を元にresourceを構築するだけなので
基本的にどの案件でも使いまわすことが出来ます。

######
# VPC
######
resource "aws_vpc" "vpc" {
  cidr_block  = "${var.vpc_config["cidr_block"]}"

  tags {
    Name = "vpc-${var.vpc_config["project"]}-${var.vpc_config["environment"]}"
  }
}

################
# Public subnet
################
resource "aws_subnet" "public" {
  count                   = "${length(var.public_subnets)}"
  vpc_id                  = "${aws_vpc.vpc.id}"
  cidr_block              = "${element(var.public_subnets, count.index)}"
  availability_zone       = "${element(var.availability_zones, count.index)}"
  map_public_ip_on_launch = "true"

  tags {
    Name = "subnet-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-public-${substr(element(var.availability_zones, count.index),-1,1)}"
  }
}

################
# DMZ subnet
################
resource "aws_subnet" "dmz" {
  count             = "${length(var.dmz_subnets)}"
  vpc_id            = "${aws_vpc.vpc.id}"
  cidr_block        = "${element(var.dmz_subnets, count.index)}"
  availability_zone = "${element(var.availability_zones, count.index)}"

  tags {
    Name = "subnet-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-dmz-${substr(element(var.availability_zones, count.index),-1,1)}"
  }
}

################
# Private subnet
################
resource "aws_subnet" "private" {
  count             = "${length(var.private_subnets)}"
  vpc_id            = "${aws_vpc.vpc.id}"
  cidr_block        = "${element(var.private_subnets, count.index)}"
  availability_zone = "${element(var.availability_zones, count.index)}"

  tags {
    Name = "subnet-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-private-${substr(element(var.availability_zones, count.index),-1,1)}"
  }
}

###############################
# Public routes and association
###############################
resource "aws_route_table" "public" {
  vpc_id = "${aws_vpc.vpc.id}"

  tags {
    Name = "rtb-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-public"
  }
}

resource "aws_internet_gateway" "internet_gateway" {
  vpc_id = "${aws_vpc.vpc.id}"

  tags {
    Name = "igw-${var.vpc_config["project"]}-${var.vpc_config["environment"]}"
  }
}

resource "aws_route" "public_internet_gateway" {
  route_table_id         = "${aws_route_table.public.id}"
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = "${aws_internet_gateway.internet_gateway.id}"
}

resource "aws_route_table_association" "public" {
  count          = "${length(var.public_subnets)}"
  subnet_id      = "${element(aws_subnet.public.*.id, count.index)}"
  route_table_id = "${aws_route_table.public.id}"
}

############################
# DMZ routes and association
############################
resource "aws_route_table" "dmz" {
  count  = "${length(var.dmz_subnets)}"
  vpc_id = "${aws_vpc.vpc.id}"

  tags {
    Name = "rtb-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-dmz-${substr(element(var.availability_zones, count.index),-1,1)}"
  }
}

resource "aws_eip" "nat" {
  count = "${length(var.dmz_subnets)}"
  vpc   = true
}

resource "aws_nat_gateway" "nat_gateway" {
  count         = "${length(var.dmz_subnets)}"
  allocation_id = "${element(aws_eip.nat.*.id, count.index)}"
  subnet_id     = "${element(aws_subnet.public.*.id, count.index)}"

  tags {
    Name = "nat-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-public-${substr(element(var.availability_zones, count.index),-1,1)}"
  }
}

resource "aws_route" "dmz_nat_gateway" {
  count                  = "${length(var.dmz_subnets)}"
  route_table_id         = "${element(aws_route_table.dmz.*.id, count.index)}"
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = "${element(aws_nat_gateway.nat_gateway.*.id, count.index)}"
}

resource "aws_route_table_association" "dmz" {
  count          = "${length(var.dmz_subnets)}"
  subnet_id      = "${element(aws_subnet.dmz.*.id, count.index)}"
  route_table_id = "${element(aws_route_table.dmz.*.id, count.index)}"
}

################################
# Private routes and association
################################
resource "aws_route_table" "private" {
  vpc_id = "${aws_vpc.vpc.id}"

  tags {
    Name = "rtb-${var.vpc_config["project"]}-${var.vpc_config["environment"]}-private"
  }
}

resource "aws_route_table_association" "private" {
  count = "${length(var.private_subnets)}"
  subnet_id      = "${element(aws_subnet.private.*.id, count.index)}"
  route_table_id = "${aws_route_table.private.id}"
}

■記述したmoduleを呼び出す

terraformでmoduleを呼びだす場合は以下のような記述をします。

sourceでmoduleを記述した.tfファイルを格納しているディレクトリを指定して
variableで指定したmoduleを実行するために必要な変数を渡すだけです。

module "vpc" {
  source             = "../modules/network/vpc/"
  vpc_config         = "${var.vpc_config}"
  availability_zones = "${var.availability_zones}"
  public_subnets     = "${var.public_subnets}"
  dmz_subnets        = "${var.dmz_subnets}"
  private_subnets    = "${var.private_subnets}"
}

たったこれだけです、後は必殺のterraform applyを決めてあげてください。

。。。。以上です。

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
0
読み込み中...
0 票, 平均: 0.00 / 10
3,539
X facebook はてなブックマーク pocket
【2025.6.30 Amazon Linux 2 サポート終了】Amazon Linux サーバー移行ソリューション

【2025.6.30 Amazon Linux 2 サポート終了】Amazon Linux サーバー移行ソリューション

この記事をかいた人

About the author

寺岡佑樹

2016年ビヨンド入社、現在6年目のインフラエンジニア
MSPの中の人として障害対応時のトラブルシューティングを行いながら
AWSなどのパブリッククラウドを用いたインフラの設計/構築も行っている。
最近はDockerやKubernetesなどのコンテナ基盤の構築や
運用自動化の一環としてTerraformやPackerなどのHashicorpツールを扱うことが多く
外部の勉強会やセミナーで登壇するEvangelistの役割も担っている。

・GitHub
https://github.com/nezumisannn

・登壇経歴
https://github.com/nezumisannn/my-profile

・発表資料(SpeakerDeck)
https://speakerdeck.com/nezumisannn

・所有資格
AWS Certified Solutions Architect - Associate
Google Cloud Professional Cloud Architect