CLOVER🍀

That was when it all began.

TerraformのData Sourceを試す

これは、なにをしたくて書いたもの?

TerraformのData Sourceを使ってみよう、ということで。

Data Source

Terraformには、Data Sourceというものがあります。Data Sourceは、外部データを参照できる仕組みです。

Data Sources - Configuration Language - Terraform by HashiCorp

Data Sourceを使用することで、Terraform外部で定義されたデータを取得して、Terraformの構成ファイル内で利用することが
できます。

定義したData Sourceは、同じTerraformモジュール内から参照することができます。

Using Data Sources

また、Data Sourceは引数を取ることができ、データを取得する際のクエリとして使うこともできます。

Data Source Arguments

Data Sourceの値は、Planを実行する際にリフレッシュされるので、「terraform plan」を実行した際に実際の値が確認できるようです。

Data Resource Behavior

実行時にしかわからないような値の場合は、構成情報を適用する際に読み取ることになります。

その他、依存関係やProvider、ライフサイクルに関する話も記載してあるので、適宜見ていきましょう…。

Data Resource Dependencies

Multiple Resource Instances

Meta-Arguments

今回は、簡単にData Sourceを使ってみましょう。

環境

今回の環境は、こちら。

$ terraform version
Terraform v0.12.24

今回は、Consul ProviderとDocker Providerを使って、Data Sourceを試してみます。

Consul Providerを使って、ノードの情報を取得する

最初は、Consul Providerを使って、Consulクラスタに参加しているノードの情報を取得してみましょう。

Provider: Consul - Terraform by HashiCorp

Consulは、1.7.2を使います。また、ノードを3つ用意して、クラスタを構成します。

ノードは172.17.0.2〜4のIPアドレスの範囲で、以下のコマンドで起動します。

$ ./consul agent -servui -client=0.0.0.0 -bootstrap-expect=3 -data-dir=/var/lib/consul/data -datacenter=mydc -join=172.17.0.2

ConsulのWeb UIで、クラスタが構成されていることを確認します。

f:id:Kazuhira:20200429211156p:plain

では、main.tfを作成します。

最初に、Consul Providerの定義。

terraform {
  required_version = ">= 0.12.24"
}

provider "consul" {
  address = "172.17.0.2:8500"
  datacenter = "mydc"
  
  version = "2.7.0"
}

Consulのアドレスは、クラスタ内のノードのひとつを指定。

Data Sourceを定義します。利用するのは、「consul_nodes」。

Consul: consul_nodes - Terraform by HashiCorp

今回は、特に引数は指定せずに定義。

data "consul_nodes" "nodes" { }

で、取得したData Sourceをどう使うかというところですが…とりあえず、Outputしてみましょう。

output "nodes_all_attributes" {
  value = data.consul_nodes.nodes
}

terraform initして

$ terraform init
$ terraform version
Terraform v0.12.24
+ provider.consul v2.7.0

フォーマット確認とバリデーションして

$ terraform fmt -recursive -check
$ terraform validate

apply。

$ terraform apply -auto-approve

結果は、こんな感じです。

Outputs:

nodes_all_attributes = {
  "datacenter" = ""
  "id" = "catalog-nodes-"
  "node_ids" = [
    "69cb9a96-7c3e-779d-2d78-6279f30ab5d9",
    "f5cd1afb-4624-a76a-fc11-a3350f321eb6",
    "f189f808-229e-bc42-b9b8-0463950c4526",
  ]
  "node_names" = [
    "consul-server1",
    "consul-server2",
    "consul-server3",
  ]
  "nodes" = [
    {
      "address" = "172.17.0.2"
      "id" = "69cb9a96-7c3e-779d-2d78-6279f30ab5d9"
      "meta" = {
        "consul-network-segment" = ""
      }
      "name" = "consul-server1"
      "tagged_addresses" = {
        "lan" = "172.17.0.2"
        "lan_ipv4" = "172.17.0.2"
        "wan" = "172.17.0.2"
        "wan_ipv4" = "172.17.0.2"
      }
    },
    {
      "address" = "172.17.0.3"
      "id" = "f5cd1afb-4624-a76a-fc11-a3350f321eb6"
      "meta" = {
        "consul-network-segment" = ""
      }
      "name" = "consul-server2"
      "tagged_addresses" = {
        "lan" = "172.17.0.3"
        "lan_ipv4" = "172.17.0.3"
        "wan" = "172.17.0.3"
        "wan_ipv4" = "172.17.0.3"
      }
    },
    {
      "address" = "172.17.0.4"
      "id" = "f189f808-229e-bc42-b9b8-0463950c4526"
      "meta" = {
        "consul-network-segment" = ""
      }
      "name" = "consul-server3"
      "tagged_addresses" = {
        "lan" = "172.17.0.4"
        "lan_ipv4" = "172.17.0.4"
        "wan" = "172.17.0.4"
        "wan_ipv4" = "172.17.0.4"
      }
    },
  ]
}

ノードの情報が、取得できましたね。

Outputで表示する結果を、少し絞ってみましょう。

output "nodes_addresses" {
  value = data.consul_nodes.nodes.nodes[*].address
}

結果。

Outputs:

nodes_addresses = [
  "172.17.0.2",
  "172.17.0.3",
  "172.17.0.4",
]

IPアドレスのみを表示。クラスタに参加しているノードの、IPアドレスが取得できたことがわかりました。

フォーマットして出力。

output "nodes_addresses" {
  value = "${join(", ", formatlist("%s", data.consul_nodes.nodes.node_names))}"
}

結果。

nodes_addresses = consul-server1, consul-server2, consul-server3

最後の方はData Sourceとは直接関係なかったですが、Terraform外の環境からデータが取得できたことはわかりましたね。

Docker Providerを使って、Dockerイメージのダイジェスト値を取得する

Consulの例では、取得対象を指定してる感じがしなかったので、もうひとつ別のお題をやってみたいと思います。

Docker Providerを使って、Docker Hubにあるイメージのダイジェスト値を取得してみましょう。

Provider: Docker - Terraform by HashiCorp

こちらですね。

Docker: docker_registry_image - Terraform by HashiCorp

main.tf

terraform {
  required_version = ">= 0.12.24"
}

provider "docker" {
  host = "unix:///var/run/docker.sock"

  version = "2.7.0"
}

data "docker_registry_image" "ubuntu" {
  name = "ubuntu:18.04"
}

output "ubuntu_docker_registry_image_name_digest" {
  value = "${data.docker_registry_image.ubuntu.name}'sha256 digest -> ${data.docker_registry_image.ubuntu.sha256_digest}"
}

こんな感じで、「ubuntu:18.04」のDockerイメージをData Sourceで参照して、SHA-256ダイジェスト値を表示してみます。

data "docker_registry_image" "ubuntu" {
  name = "ubuntu:18.04"
}

initして、Docker Providerをインストール。

$ terraform init
$ terraform version
Terraform v0.12.24
+ provider.docker v2.7.0

apply。

$ terraform apply -auto-approve

実行結果。

Outputs:

ubuntu_docker_registry_image_name_digest = ubuntu:18.04'sha256 digest -> sha256:b58746c8a89938b8c9f5b77de3b8cf1fe78210c696ab03a1442e235eea65d84f

本エントリ記載時の、「ubuntu:18.04」のSHA-256ダイジェスト値です。

ubuntu

f:id:Kazuhira:20200429214027p:plain

OKですね。

まずは簡単に使ってみるところでは、こんな感じでしょう。