LoginSignup
0
0

Terraformのモジュールを試してみた

Posted at

背景・目的

過去に、TerraformのメモTerraform ステートを試してみたTerraformの環境をセットアップしてみた等で、Terraformを試してきました。

今回は、詳解 Terraform 第3版の、「第4章 モジュールで再利用可能なインフラを作る」を元に、モジュール化を学びます。

まとめ

下記に特徴をまとめます。

特徴 説明
概要 モジュールは、本場とステージングのように、共通の環境は同じでスペックが異なる場合がある。Terraformモジュールに入れて、そのモジュールをコード内の複数の場所で使い回す
モジュールの基本 あるフォルダにあるTerraform設定ファイルの集まりを指す。
モジュールの入力 入力パラメータは、variables.tfに定義する
モジュールのローカルな値 他から参照されて上書きされる場合、localsブロックを使用する

概要

本場とステージングのように、共通の環境は同じでスペックが異なる場合がある。
このようなコードは、Terraformモジュールに入れて、そのモジュールをコード内の複数の場所で使い回す

|-modules
  |-services
    |-webserver-cluster
       |- main.tf

モジュールの基本

あるフォルダにあるTerraform設定ファイルの集まりは、モジュールになる。

モジュールの入力

モジュールは、入力パラメータを持てる。入力パラメータを定義するには、variables.tfに定義する。

モジュールのローカルな値

入力変数として定義した場合、他から参照されて上書きされる可能性がある。その場合、localsブロックでローカルな値を使用する。

localブロックにより、ローカルな値を使う場合、その名前をモジュール内で使用できる。この名前は、そのモジュール内でしか利用できないので他のモジュールに影響を与えない。
下記に例を示す。

locals {
  http_port   = 80
}

読み出すには、local.<NAME>のように読み出す

モジュールのバージョン管理

ステージングと本番の両環境が同じモジュールのフォルダを指定しているときに、そのフォルダ内に何らかの変更を加えると、次にデプロイを行うときにすぐに両環境に反映されてしまう。これにより、本番に影響を与えずにテストすることが困難になる。

この問題を解決するために、モジュールのバージョン管理を行う。

実践

呼び出し元 Network

$ pwd
{HOME}/aws_infra_tf/environments/prod
$ tree network 
network
├── backend.hcl
├── backend.tf
├── local.tf
├── main.tf
└── provider.tf

1 directory, 5 files
$

main.tf

module "network" {
  source = "../../../modules/network"

  vpc_cidr        = local.vpc.cidr
  env             = local.vpc.env
  public_subnets  = local.public_subnets
  private_subnets = local.private_subnets
  db_subnets      = local.db_subnets
}

local.tf

locals {
  vpc = {
    cidr = "120.100.0.0/16"
    env  = "prod"
  }
}
locals {
  public_subnets = {
    public01 = {
      name = "public01",
      cidr = "120.100.0.0/24",
      az   = "ap-northeast-1a"
    },
    public02 = {
      name = "public02",
      cidr = "120.100.1.0/24",
      az   = "ap-northeast-1c"
    },
    public03 = {
      name = "public03",
      cidr = "120.100.2.0/24",
      az   = "ap-northeast-1d"
    },
  }
}
locals {
  private_subnets = {
    private01 = {
      name = "private01",
      cidr = "120.100.10.0/24",
      az   = "ap-northeast-1a"
    },
    private02 = {
      name = "private02",
      cidr = "120.100.11.0/24",
      az   = "ap-northeast-1c"
    },
    private03 = {
      name = "private03",
      cidr = "120.100.12.0/24",
      az   = "ap-northeast-1d"
    },
  }
}
locals {
  db_subnets = {
    db01 = {
      name = "db01",
      cidr = "120.100.20.0/24",
      az   = "ap-northeast-1a"
    },
    db02 = {
      name = "db02",
      cidr = "120.100.21.0/24",
      az   = "ap-northeast-1c"
    },
    db03 = {
      name = "db03",
      cidr = "120.100.22.0/24",
      az   = "ap-northeast-1d"
    },
  }
}

Modules Network

$ pwd
{HOME}/aws_infra_tf/aws_infra_tf
$ tree modules 
modules
└── network
    ├── main.tf
    └── variables.tf

2 directories, 2 files
$

main.tf

# VPC
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc
resource "aws_vpc" "terraform_modules_vpc" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true
  tags = {
    Name = "terraform-modules-vpc-${var.env}"
    Env  = var.env
  }
}
# Public Subnets
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet
resource "aws_subnet" "public_subnets" {
  for_each = var.public_subnets

  vpc_id = aws_vpc.terraform_modules_vpc.id

  cidr_block        = each.value.cidr
  availability_zone = each.value.az

  tags = {
    Name = "terraform-modules-vpc-subnet-${var.env}-${each.value.name}"
    Env  = var.env
  }
}
# Private Subnets
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet
resource "aws_subnet" "private_subnets" {
  for_each = var.private_subnets

  vpc_id = aws_vpc.terraform_modules_vpc.id

  cidr_block        = each.value.cidr
  availability_zone = each.value.az

  tags = {
    Name = "terraform-modules-vpc-subnet-${var.env}-${each.value.name}"
    Env  = var.env
  }
}
# DB Subnets
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet
resource "aws_subnet" "db_subnets" {
  for_each = var.db_subnets

  vpc_id = aws_vpc.terraform_modules_vpc.id

  cidr_block        = each.value.cidr
  availability_zone = each.value.az

  tags = {
    Name = "terraform-modules-vpc-subnet-${var.env}-${each.value.name}"
    Env  = var.env
  }
}

# Internet Gateway
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway
resource "aws_internet_gateway" "terraform_igw" {
  vpc_id = aws_vpc.terraform_modules_vpc.id

  tags = {
    Name = "terraform-modules-vpc-igw-${var.env}"
    Env  = var.env
  }

}

# Elastic IP
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip
resource "aws_eip" "nat_eip" {
  domain = "vpc"

  tags = {
    Name = "terraform-modules-vpc-eip-${var.env}"
    Env  = var.env
  }

}

# NAT Gateway
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway
resource "aws_nat_gateway" "nat_gateway" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = aws_subnet.public_subnets["public01"].id

  tags = {
    Name = "terraform-modules-vpc-nat-${var.env}"
    Env  = var.env
  }
}


# Public Subnet Route Table
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table
resource "aws_route_table" "public_route_table" {
  # for_each = var.public_subnets
  vpc_id = aws_vpc.terraform_modules_vpc.id

  tags = {
    Name = "terraform-modules-vpc-routetable-${var.env}-public"
    Env  = var.env
  }
}

# Public Subnet Route
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route
resource "aws_route" "public_route" {
  for_each               = var.public_subnets
  route_table_id         = aws_route_table.public_route_table.id
  destination_cidr_block = var.any_cidr_block
  gateway_id             = aws_internet_gateway.terraform_igw.id
}

# Associate Route Table
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association
resource "aws_route_table_association" "public_route_table_association" {
  for_each = var.public_subnets

  subnet_id      = aws_subnet.public_subnets[each.key].id
  route_table_id = aws_route_table.public_route_table.id
}

# Private Subnet Route Table
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table
resource "aws_route_table" "private_route_table" {
  for_each = var.private_subnets
  vpc_id   = aws_vpc.terraform_modules_vpc.id

  tags = {
    Name = "terraform-modules-vpc-routetable-${var.env}-${each.key}"
    Env  = var.env
  }
}

# Private Subnet Route
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route
resource "aws_route" "private_route" {
  for_each               = var.private_subnets
  route_table_id         = aws_route_table.private_route_table[each.key].id
  nat_gateway_id         = aws_nat_gateway.nat_gateway.id
  destination_cidr_block = var.any_cidr_block
}

# Associate Route Table
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association
resource "aws_route_table_association" "private_route_table_association" {
  for_each = var.private_subnets

  subnet_id      = aws_subnet.private_subnets[each.key].id
  route_table_id = aws_route_table.private_route_table[each.key].id

}

variables.tf

variable "vpc_cidr" {
  type        = string
  description = "VPC_CIDR"
}

variable "env" {
  type        = string
  description = "Environment。dev,stg,prdを選択すること"
}

variable "public_subnets" {
  type        = map(any)
  description = "Public Subnets"
}
variable "private_subnets" {
  type        = map(any)
  description = "Private Subnets"
}
variable "db_subnets" {
  type        = map(any)
  description = "DB Subnets"
}

variable "any_cidr_block" {
  type        = string
  description = "CIDR"
  default     = "0.0.0.0/0"
}

考察

前回、Terraformのメモで作成したNetworkをモジュール分割してみました。まだまだ、分かっていないことも多いので、少しづづ使って慣れていこうと思います。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0