Terraformのoutputとは何か


Terraformにはoutputというものがあります。
ただ、Terraformでは簡単な構成で構築するくらいしかしたことがない私は、今までoutputを使わなくてもいけていたので、どういう時にoutputを使えば良いのかよく分かっていませんでした。

そこで今回Terraformのoutputについて調べてまとめてみました。

Terraformは初心者なので、間違っていることなどがあったらコメントいただけると嬉しいです。

Output について

Terraformのドキュメントを見るとユースケースとして以下の3点が挙げられています。

  • A child module can use outputs to expose a subset of its resource attributes to a parent module.
  • A root module can use outputs to print certain values in the CLI output after running terraform apply.
  • When using remote state, root module outputs can be accessed by other configurations via a terraform_remote_state data source.

1. terraform applyを実行後にCLIにプリントされる

一番最初に思い浮かぶのはこれかと思います。
ルートモジュールでoutputをすると、outputで宣言した値が出力されます。

Learnのサンプルを一部引用すると、

output "vpc_id" {
  description = "ID of project VPC"
  value       = aws_vpc.vpc.id
}

のように宣言しておくと、

$ terraform apply

...()

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

vpc_id = "vpc-004c2d1ba7394b3d6"

のようにapply後に分かる値についても出力することができます。

ただ、これだけだとそうなんだ?くらいにしか思っていなかったのですが、terraform outputコマンドを使うことで、自動化などの利用の幅が広がりそうということが分かりました。

terraform output

上記の例でoutputに指定したものは以下のように出力することができます。

$ terraform output -json
{
  "vpc_id": {
    "sensitive": false,
    "type": "string",
    "value": "vpc-004c2d1ba7394b3d6"
  }
}

そして個別の値も取得することができるので、apply後にその値を使ってオペレーションを自動化したい時に使えそうです。

$ terraform output vpc_id
vpc-004c2d1ba7394b3d6

2. 子モジュールの属性を親モジュールに公開できる

moduleは構成を論理コンポーネントに整理するだけでなく、カプセル化をすることができます。

これによって、あるmoduleで作られたresourceの出力値は、ルートモジュール以外のモジュールでは直接参照することができません。

そのため、子モジュールのresourceの出力値を他のmoduleで参照したい場合は、子モジュールでoutputを定義して、ルートモジュールが別のmoduleを呼び出す時にvariableとして渡すという使い道があります。

例えばnetworkというモジュールのvpc_idを、別のmoduleで使いたい場合、使いたいanotherモジュールでは以下のようにvariableを定義します。

modules/another/variables.tf
variable "vpc_id" {}

そして先程のように出力するモジュールにてvpc_idを出力したあと、以下のようにルートモジュールでanother_moduleにoutputした値をvariableとして渡してあげることで、

module "another_module" {
  source = "./modules/another"
  vpc_id = module.network.vpc_id
}

anotherモジュールのresourceで以下のように使うことができるようになります。

modules/another/main.tf
resource "..." "..." {
  vpc_id = var.vpc_id
}

3. terraform_remote_stateを使うことで他の構成からアクセスできる

terraform_remote_stateデータソースについてのドキュメントはこちらです。

terraform_remote_stateを使うことで、ルートモジュールで出力した値を、別のTerraformプロジェクトから読み込むことができるようです。

あるTerraformプロジェクトで以下のようにstateのbackendをS3に設定していて、そのルートモジュールで何らかの値をoutputしていた場合、1

プロジェクトA
terraform {
  backend "s3" {
    bucket = "mybucket"
    key    = "network/terraform.tfstate"
    region = "us-east-1"
  }
}

呼び出しをしたい別のプロジェクトから対象のS3にアクセスできる権限を付与した上で、以下のようなデータソースを設定することで、

プロジェクトB
data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "mybucket"
    key    = "network/terraform.tfstate"
    region = "us-east-1"
  }
}

プロジェクトAでoutputをした出力をプロジェクトBのリソースで参照することができるようです。

プロジェクトB
resource "..." "..." {
  vpc_id = data.terraform_remote_state.network.vpc_id
}

まとめ

Terraformのoutputのユースケースとしては主に以下の3点があります。

  1. terraform applyを実行後にCLIにプリントする
  2. 子モジュールの属性を親モジュールに公開する
  3. terraform_remote_stateを使い、他の構成からアクセスする

Terraformで管理しているリソースが増え、適切にコンポーネント分割、stateの分割をしようとした時に必要になってきそうなので、知ることができてよかったです。

もし誤りや他のユースケース等がありましたらご教示いただけるととても嬉しいです。

参考

  1. https://www.terraform.io/language/settings/backends/s3 の例を参考