0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Terraformにおけるmoduleの使い所

Last updated at Posted at 2020-10-20

対象読者

Terraformは触ったことがあるが、moduleがあまりわからない。または、moduleをつかったことがない人が対象になります。
またAWSをTerraform化する場合を例に出すので、AWSの知識も少し必要です。

はじめに

私はTerraformを触って2年近くになりますが、moduleを使った設計は行わずに基本的に以下のフューチャーアーキテクトさんの記事で書かれている 環境毎にディレクトリで分離派 に則ってTerraformを作成しておりました。
参考資料: https://future-architect.github.io/articles/20190903/

ただ、やはり環境ごとで同様の設定を書くことがあり、冗長に感じたので、DRYの法則に則りmoduleを使ってみました。
moduleの使い方と設計の勘所のメモとしてこの記事を書きます。

moduleとは

アプリケーションで使う場合のmoduleと同じく、terraformでも共通で使いたい部分をテンプレートとして使うためのものです。

既存のコードをmodule化する

このようなterraformのコードが存在するとします。
この場合、 vpc.tf が共通化できる設定であると仮定してmodule化していきます。

├── prod
│   ├── main.tf
│   ├── variables.tf
│   └── vpc.tf
└── stag
    ├── main.tf
    ├── variables.tf
    └── vpc.tf

module作成

terraformではmodule化をしたものを読み込む時にmoduleを宣言して扱います。
例えば、terraformのルートディレクトリにmodulesディレクトリを掘って、その中に共通化したい resourceを定義します。
この場合は、 vpc.tf を共通化したいので、vpcのresourceを定義します。

modules/vpc/main.tf
resource "aws_vpc" "this" {
  cidr_block           = "192.168.0.0/20"
  instance_tenancy     = "default"

  tags = {
    "Name" = "this"
  }
}

このmodules/vpc/main.tfを呼び出してstag環境を作ろうとするならば、
相対パスで指定してmodule化したディレクトリ指定します。

stag/vpc.tf
module "vpc" {
  source = "../modules/vpc"
}

moduleの値を参照する

moduleで定義した内容を別で定義したresourceで参照したい場合は、outputを定義して使えるようにします。
逆にmoduleに値を渡したい時はvariableを使います。
言い換えると、moduleから出力されたものを定義するのがoutputで、moduleに入力するものを定義するのがvariableです。

これを使ってmoduleを直していきます。
stag環境以外に本番環境も使えるmoduleにしたい場合はこのように修正しましょう。

modules/vpc/main.tf
variable "vpc_cidr" {}

resource "aws_vpc" "this" {
  cidr_block           = "${var.vpc_cidr}/20"
  instance_tenancy     = "default"

  tags = {
    "Name" = "this"
  }
}

vpc_cidrが空なのはmodule参照時に定義される値を読み込むためです。
先ほど定義したstag/vpc.tfでmoduleのvariableで定義したvpc_cidrに値を渡してあげましょう。

stag/vpc.tf
module "vpc" {
  source   = "../modules/vpc"
  vpc_cidr = "192.168.0.0"
}

このようにするとmodules/vpc/main.tfvpc_cidr192.168.0.0が定義されて、
variable定義前と同じ設定内容になります。

prod環境でvpcを作りたい場合もmoduleを呼び出して作れます。

prod/vpc.tf
module "vpc" {
  source   = "../modules/vpc"
  vpc_cidr = "172.16.0.0"
}

またmoduleで定義した内容を他のresourceでも参照したい時には outputを使います。
先ほど設定したmodules/vpc/main.tfoutputで別のresourceに参照される値を定義します。

modules/vpc/main.tf
~省略~
output "this_vpc_id" {
  value = aws_vpc.this.id
}

ここでは、stag環境で新たにigw.tfを作りインターネットゲートウェイの設定を定義します。
moduleで定義した内容を読み込む場合はmodule.<module名>.<outputの定義名>で値を参照します。

stag/igw.tf
resource "aws_internet_gateway" "this" {
  vpc_id = module.vpc.this_vpc_id

  tags = {
    "Name" = "this"
  }
}

module化したあとのコード

全体のディレクトリ構成はこのようになります。
現在はprod/stagでmoduleを読み込むtfファイルとmoduleのディレクトリ名を1対1に作ってますが、
modulesにEC2やVPCを全部いれたmoduleを作り、それをprod/stagで読むこともできます。

├── modules
│   └── vpc
│       └── main.tf
├── prod
│   ├── main.tf
│   ├── variables.tf
│   └── vpc.tf
└── stag
    ├── igw.tf
    ├── main.tf
    ├── variables.tf
    └── vpc.tf

この記事の内容はこちらにサンプルコードとして載せて置くので、
完成したコードを読みたい方がいればご覧ください。

所感

moduleは大変便利だと感じた一方、値の参照が多いネットワーク系(AWSでいうとvpcやsecurity groupなど)で使う場合は、何をどこで参照させるかを考える必要が出てくると感じました。

ただ、ECRなどの他のリソースとの依存関係がほぼなくサービス単体で成り立つものに関してはmodule化をすると見通しがよいコードになると感じます。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?