どんな事でもお気軽にお問い合わせください
0120-803-656
24時間受付いたします

[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を決めてあげてください。

。。。。以上です。


お問い合わせ 採用情報 エンジニアブログ
ISO27001認証
Contact PageTop
株式会社ビヨンド

© beyond Co., Ltd. All rights reserved.