🐳

TerraformでModuleを使おう

2024/12/31に公開

Moduleとは

特定のリソースをModuleにすることで、設定の使い回しや共通化を図る事ができます

どんなときに使うか

同一の設定のEC2インスタンスを複数起動する場合、Moduleを使うと簡単です。
workspaceの機能を使わずに、環境ごとにディレクトリを分けている構成をした場合は、Moduleを使用することで複数環境で同一の設定をすることができます。

ここでやること

簡単に試すことを目的にProviderはDockerを指定します。ImageとContainerをModuleにし、異なる環境でImageのタグやコンテナ名、ホストポートへのマッピングを変更する例を上げたいと思います。

実行環境

ツール

Tool Version
Terraform 0.12.8

ディレクトリ構成

以下の構成で考えます。

$ tree .
.
├── env
│   ├── A
│   │   └── main.tf
│   └── B
│       └── main.tf
└── modules
    ├── image
    │   ├── main.tf
    │   ├── output.tf
    │   └── variable.tf
    └── container
        ├── main.tf
        ├── output.tf
        └── variable.tf

Moduleの定義

以下のファイルをそれぞれ定義します。

ファイル 説明
main.tf resourceを定義します
output.tf 他のModuleで利用する値を定義します
variable.tf Moduleへの入力するための変数を定義します

Image

imageはnginxを指定しますが、imageのタグは変更できるようにvariableとして定義します。
container側でimageのIDを利用するためにoutputを定義しています。

resource "docker_image" "nginx" {
  name = "nginx:${var.nginx_image_version}"
}
output "nginx_image_id" {
  value = "${docker_image.nginx.latest}"
}
variable "nginx_image_version" {
  default = "latest"
}

Container

containerではコンテナ名とホストのポートを指定できるようにvariableで定義します。

resource "docker_container" "nginx" {
  image = "${var.nginx_image_id}"
  name  = "${var.nginx_container_name}"
  ports {
    internal = 80
    external = "${var.nginx_host_port}"
  }
}
variable "nginx_image_id" {}
variable "nginx_container_name" {}
variable "nginx_host_port" {
  default = 8080
}

Terraformの実行

Moduleを作成した後は必ず $ terraform initを実行します。
環境ごとに以下の設定になるようにmain.tfファイルを編集します。

環境 nginxのimageタグ コンテナ名 ホストポート
A 1.17 env_A_container 8081
B 1.16 env_B_container 8082
provider "docker" {
}
module "image" {
  source = "../../modules/image"
  nginx_image_version = "1.17"
}
module "container" {
  source               = "../../modules/container"
  nginx_image_id       = "${module.image.nginx_image_id}"
  nginx_container_name = "env_A_container"
  nginx_host_port      = "8081"
}
provider "docker" {
}
module "image" {
  source = "../../modules/image"
  nginx_image_version = "1.16"
}
module "container" {
  source               = "../../modules/container"
  nginx_image_id       = "${module.image.nginx_image_id}"
  nginx_container_name = "env_B_container"
  nginx_host_port      = "8082"
}

env/Aenv/Bのディレクトリで$ terraform applyを実行すると、2つのimageとcontainerが作成されているはずです。

最後に

Moduleへのインプットをvariableでアウトプットをoutputを用いることがわかれば、難しい話ではないはずです。
今回のように環境をディレクトリで分けるときには有効な方法かと思います。

参考

Discussion