[Terraform]Module間の値の受け渡しについて

2020.05.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、コンサル部の島川です。

今回はTerraformのModule間の受け渡しについてAWSを例に説明します。コマンド一発で環境が作れるのは幸せを感じます。

Moduleのイメージ

Moduleはパーツのように扱うことができます。組み合わせ無限大です。使いたいものだけを使えばOKです。

また、Moduleで区切ることで依存関係をスッキリさせることもできます。

Module間の値のやり取り

ただし、VPCのModule書いて、EC2のModule書いて起動!と簡単にはいきません。EC2を作成する際にサブネットIDを指定する必要があり、それは一度VPCを作らないと分からないです。自動補完したいですよね。Terraformには出力された値を他のModuleで参照できる方法があります。

出力された値をOutput Valuesとして明示的に書いておくと他のModuleさんも使えるようになります。また、OutputはModuleの中に書いてあげる必要があります。

Outputの宣言例

output "instance_ip_addr" {
  value = aws_instance.server.private_ip
}
  • instance_ip_addrが変数名です。なんでもOKです。
  • valueが変数に格納される値です。例ではサーバのプライベートIPを格納しています。

基本的にはこちらの宣言のみですが、他にもオプションがあります。

オプション 概要
description 概要を書く
sensitive CLIへの出力を抑制する(機密情報をマスクしたいときに使用)
depends_on 値の出力に依存関係の指定がある場合に使用する。最後の手段といわれていて積極的に使うものではない。

全て書くと以下のようになります。

output "instance_ip_addr" {
  value       = aws_instance.server.private_ip
  description = "The private IP address of the main server instance."
  sensitive   = true

  depends_on = [
    # Security group rule must be created before this IP address could
    # actually be used, otherwise the services will be unreachable.
    aws_security_group_rule.local_access,
  ]
}

補足ですが、valueはlist形式でもOKです。

他のModuleの値を参照する

Outputに出力された値を他のModuleが参照するにはmodule..の形式で使用します。Module NAMEが「hogeserver」でOutputの値がinstance_ip_addrならmodule.hogeserver.instance_ip_addrのように書いてあげます。

簡単な例を用いて説明します。

ModuleはVPCとEC2の二つを使います。EC2作成時にVPCのModuleで作られたサブネットIDを指定したいという状況です。

今回使用するModuleはTerraform Registryのものを使用します。Terraform Registory?についてはこちら参照ください。

Terraform Registory

今回使用するTerraform Registoryです。

サンプルコード

1つのファイルにまとめてあります。

main.tf

//----------
//Provider
//----------
provider "aws" {
  region     = var.aws_region
}
variable "aws_region" {
  default = "ap-northeast-1"
}

//----------
//variable
//----------

variable ec2_name {
  default = "hoge-server"
}

//----------
//VPC Config
//----------
module "vpc" {
  source = "../modules/VPC/terraform-aws-vpc"

  name = "hoge-vpc"
  cidr = "10.10.0.0/16"
  env  = "test"

  azs             = ["ap-northeast-1a", "ap-northeast-1c"]
  public_subnets  = ["10.10.0.0/24", "10.10.1.0/24"]
  private_subnets = ["10.10.10.0/24", "10.10.11.0/24"]
  

  enable_nat_gateway  = false
  single_nat_gateway  = false

}

//----------
//EC2 config
//----------
data aws_ssm_parameter amzn2_ami_latest {
  name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}

module "hoge-server" {
  source                 = "terraform-aws-modules/ec2-instance/aws"
  version                = "~> 2.0"

  name                   = var.ec2_name
  instance_count         = 1

  ami                    = data.aws_ssm_parameter.amzn2_ami_latest.value
  instance_type          = "t3.micro"
  key_name               = "ec2testkey"
  monitoring             = false
  subnet_id              = module.vpc.private_subnets[0]
  //private_ip             = ""

  ebs_optimized          = true

  root_block_device = [
    {
      delete_on_termination = true
      encrypted             = true
      iops                  = 60
      kms_key_id            = ""
      volume_size           = 20
      volume_type           = "gp2"
    },
  ]
  tags = {
    Name            = var.ec2_name
  }
}

57行目でVPC Moduleで出力された値を参照しています。今回、PublicSubnet2つとPrivateSubnet2つと複数作成しておりますので、list形式で出力されているため配列番号を指定しております。今回だとCIDR「10.10.10.0/24」のもののIDを指定している形になります。

Outputはどこで指定した?

Terraform RegistoryのModuleはOutputもきちんと書いてくれています。指定できるOutputの値もまとまってあります。

VPCだとここです。private_subnetsで指定できるのが分かります。

さいごに

TerraformのModule間のやり取りを説明しました。依存関係を分離できるので色んなModuleを組み合わせて使っていきたいですね。

Terraform Registoryめっちゃ便利じゃないですか?(これを伝えたかった)

参考

[Terraform] Output Values

Terraform Registory