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?

PR: 株式会社フューチャークリエーションファクトリー
F.C.Fでは、一緒に成長していくエンジニアを募集しています 🌱

Terraform入門 第4回:モジュールでTerraform設定を再利用する

0
Posted at

Terraform-module-02.png

はじめに

Terraformをゼロから学びながら、その内容を自分なりに整理して残していく入門連載です。

第3回では、Terraform StateをS3のリモートバックエンドで管理しました。

Terraformの設定が大きくなってくると、同じような設定を何度も書いたり、1つのディレクトリに多くのリソースを詰め込んだりしがちです。そこで今回は、Terraformのモジュールを使って設定を整理し、再利用する方法を試します。

第2回で作成したSSMパラメータの設定をモジュールに切り出します。既に作成したリソースをそのまま管理し続けられるよう、Terraform State上のリソースアドレスも移動します。

この記事は学習の記録を兼ねています。内容に誤りや、よりよい方法があればコメントで教えていただけると助かります。

今回のゴール

以下をできるようにすることが目標です。

  • Terraformモジュールの役割を理解する
  • 設定をローカルモジュールへ切り出す
  • モジュールの入力と出力を定義する
  • 既存リソースのStateアドレスを変更し、作り直しを防ぐ

今回もAWS Systems Manager Parameter StoreのSSMパラメータを管理します。第3回でS3バックエンドへ移行したStateを引き続き利用します。

前提条件

以下の準備ができていることを前提に進めます。

  • 第3回で作成したterraform-aws-learningディレクトリがある
  • S3バックエンドを設定済みで、Terraform StateがS3に保存されている
  • 第2回で作成したSSMパラメータがStateに登録されている
  • AWS CLIとTerraformを利用でき、AWS CLIで認証済みである

環境構築やStateのリモート化がまだの場合は、第1回から順に進めてください。

Terraformのモジュールとは

Terraformでは、.tfファイルが置かれたディレクトリをモジュールとして扱います。これまで作成してきたterraform-aws-learningディレクトリも、ルートモジュールです。

ルートモジュールから別のディレクトリにある設定を呼び出すと、その設定を子モジュールとして利用できます。モジュールに入力値を渡し、モジュール側で定義した出力値を受け取れます。

terraform-aws-learning/
├── main.tf
├── variables.tf
├── outputs.tf
└── modules/
    └── ssm-parameter/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

今回はSSMパラメータを作成する設定をmodules/ssm-parameterに切り出します。モジュールを使うと、同じ構成を別の値で呼び出したり、ルート側の設定とリソースの詳細を分けたりできます。

SSMパラメータの設定をモジュールに切り出す

第2回で作成したディレクトリに移動します。

cd terraform-aws-learning

この時点で、Stateに登録されているリソースアドレスを確認します。

terraform state list

今回の手順では、次のように表示されることを前提にしています。

aws_ssm_parameter.example

子モジュールを作成する

モジュール用のディレクトリを作成します。

mkdir -p modules/ssm-parameter

modules/ssm-parameter/main.tfを作成し、SSMパラメータのリソースを定義します。

resource "aws_ssm_parameter" "this" {
  name  = var.parameter_name
  type  = "String"
  value = var.message
  tier  = "Standard"
}

続けて、modules/ssm-parameter/variables.tfを作成します。

variable "parameter_name" {
  description = "Name of the SSM parameter to create"
  type        = string
}

variable "message" {
  description = "Value to store in the SSM parameter"
  type        = string
}

子モジュールにdefaultを設定せず、呼び出し側から値を受け取る形にしました。これにより、モジュールを使う側が作成するパラメータ名と値を明示できます。

modules/ssm-parameter/outputs.tfを作成し、モジュールの外へ公開する値を定義します。

output "parameter_name" {
  description = "Name of the SSM parameter"
  value       = aws_ssm_parameter.this.name
}

output "parameter_arn" {
  description = "ARN of the SSM parameter"
  value       = aws_ssm_parameter.this.arn
}

output "parameter_version" {
  description = "Current version of the SSM parameter"
  value       = aws_ssm_parameter.this.version
}

aws_ssm_parameter.this.nameのようなリソース属性は、子モジュール内でのみ参照できます。ルートモジュールから値を使うには、このようにoutputで公開します。

ルートモジュールから呼び出す

ルートのmain.tfを次の内容に更新します。required_version、Providerの宣言、aws_region変数はこれまでどおりルート側に残し、SSMパラメータの設定をmoduleブロックから呼び出します。

terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.55"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

module "ssm_parameter" {
  source = "./modules/ssm-parameter"

  parameter_name = var.parameter_name
  message        = var.message
}

sourceにはモジュールの場所を指定します。./modules/ssm-parameterはルートモジュールからの相対パスです。

AWS Providerはルートモジュールで設定しています。今回のようにProviderのエイリアスを使わない構成では、Provider設定が子モジュールへ引き継がれるため、子モジュール内にprovider "aws"ブロックを追加する必要はありません。

ルートのvariables.tfは第2回で作成したものをそのまま使います。既定値が設定されているため、今回の操作で変数値を入力し直す必要はありません。

ルートのoutputs.tfは、モジュールの出力値を参照するように更新します。

output "parameter_name" {
  description = "Name of the SSM parameter"
  value       = module.ssm_parameter.parameter_name
}

output "parameter_arn" {
  description = "ARN of the SSM parameter"
  value       = module.ssm_parameter.parameter_arn
}

output "parameter_version" {
  description = "Current version of the SSM parameter"
  value       = module.ssm_parameter.parameter_version
}

モジュールの出力値はmodule.<モジュール名>.<出力名>の形式で参照します。今回はmodule.ssm_parameter.parameter_arnのように記述します。

Terraform-module-01.png

設定を初期化・検証する

設定ファイルを整形し、ローカルモジュールを読み込むために初期化します。

terraform fmt -recursive
terraform init
terraform validate

terraform initは、ルートモジュールが利用するProviderや子モジュールを準備します。今回はS3バックエンドの接続先を変更していないため、Stateの移行オプションは付けません。

Stateのリソースアドレスを変更する

リソースをルートモジュールから子モジュールへ移したため、Terraform上のリソースアドレスも変わります。

変更前: aws_ssm_parameter.example
変更後: module.ssm_parameter.aws_ssm_parameter.this

このままterraform planを実行すると、Terraformは変更前のリソースを削除し、変更後のリソースを新規作成するものとして扱う可能性があります。実際のSSMパラメータを作り直さず、同じリソースを管理し続けるために、terraform state mvでState内のアドレスを変更します。

terraform state mv \
  aws_ssm_parameter.example \
  module.ssm_parameter.aws_ssm_parameter.this

この操作はTerraform State上のアドレスを変更するもので、AWS上のSSMパラメータ自体は変更しません。S3バックエンドを利用している場合、Stateの更新はS3上のStateに反映されます。

移動後のアドレスを確認します。

terraform state list

次のように表示されれば、Stateの移動は完了です。

module.ssm_parameter.aws_ssm_parameter.this

Stateに対象リソースがない場合

上記のterraform state mvは、移動元のリソースがStateに登録済みの場合に実行します。既にSSMパラメータを削除していて、Stateにも対象がない場合は、このコマンドを実行しないでください。その場合はterraform planを実行し、新しいリソースの作成として表示されることを確認します。

実行計画を確認する

Stateのアドレスを変更したあと、実行計画を確認します。

terraform plan

既存のリソースをStateに登録した状態でモジュールへ移動できていれば、次のように変更なしの計画が表示されます。

No changes. Your infrastructure matches the configuration.

Plan: 1 to add, 0 to change, 1 to destroy.のように作成や削除が表示された場合は、terraform applyを実行せず、Stateのアドレスやモジュールの引数が以前の設定と一致しているか確認してください。

出力値も確認します。

terraform output

パラメータ名、ARN、バージョンが以前と同じ値で表示されれば、モジュール化後もリソースの情報を参照できています。

同じモジュールを複数回使う

同じモジュールを別の値で呼び出せば、同じ構成のリソースを追加できます。例えば、ルートのmain.tfに次のmoduleブロックを追加すると、別のSSMパラメータを管理できます。

module "another_ssm_parameter" {
  source = "./modules/ssm-parameter"

  parameter_name = "/sandbox/another-message"
  message        = "hello-from-another-module"
}

同じモジュールを複数回使う場合は、SSMパラメータ名のようにAWS側で一意である必要がある値を重複させないようにします。追加後は、terraform planで新しいリソースだけが作成対象になっていることを確認してから適用します。

リソースを削除する

今回は第2回から管理しているSSMパラメータを削除します。

terraform destroy

確認画面に表示された削除対象がSSMパラメータであることを確認してから、yesを入力します。State用S3バケットは別のbootstrap構成で管理しているため、このコマンドでは削除されません。

前の例の追加モジュールも実際に設定した場合は、そのSSMパラメータも削除対象になります。yesを入力する前に、表示された対象を確認してください。

まとめ

今回は、SSMパラメータの設定をローカルモジュールへ切り出しました。

  • Terraformでは、ディレクトリをモジュールとして扱う
  • ルートモジュールからmoduleブロックを使って子モジュールを呼び出す
  • 入力変数でモジュールへ値を渡し、出力値で必要な情報を受け取る
  • Providerはルートモジュールで設定し、今回の構成では子モジュールへ引き継いだ
  • 既存リソースのアドレスを変更するときは、terraform state mvでStateを移動する
  • terraform planで意図しない作成・削除がないことを確認してから適用する

モジュールへ切り出すことで、リソースの詳細とルート側の構成を分けられました。同じモジュールを別の入力値で呼び出せば、同じパターンの設定も再利用できます。

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?