Terraformでインフラを構築する方法 part.2

このブログをご覧のみなさん、こんにちは。

前回に引き続き、Terraformを使ったので、その概要をまとめてみました。

以下は、HashiCorpの公式サイトにあるTerraformのGetting Startedを実践した内容になります。

Environment

  • Mac Book Pro
    • OS X Yosemite 10.10.5
  • Terraform 0.7.1

Terraform Remote

Terraformはインフラを構築・破壊(terraform apply, destroy)するとその状態をterraform.tfstateというファイルに書き出します。
Aという環境でterraform applyを2回実行しても、terraform apply によってインフラが構築されるのは1回だけですが、
このファイルを共有しないまま、Aという環境でterraform applyをし、同様にBという環境でterraform applyを行うとインフラが2回構築されてしまいます。
それを避けるために、terraform.tfstateをリモートで管理し、A、B双方で共有するための仕組みが、Terraform Remoteになります。

しかし、Terraform Remoteの手順に従って、これを実行すると…。

$ terraform remote config -backend-config="name=changeworld/getting-started"
Remote configuration updated
Error while performing the initial pull. The error message is shown
below. Note that remote state was properly configured, so you don't
need to reconfigure. You can now use `push` and `pull` directly.

Error reloading remote state: Unexpected HTTP response code: 400

Body: {"errors":["This feature requires Terraform Enterprise. Please contact sales@hashicorp.com to start or extend your trial."],"success":false}

となります。以前はGetting StartedのTerraform Remoteで説明されている Atlas が無料で使えたようなのですが、現在は有料でしか使えないためです。Terraform Enterpriseを使わない方法は調べたので、別途記載します。

Resource Dependencies

ここまでは1つのリソースの作成・変更・削除でしたが、複数のリソースを指定した場合は、適用順序を制御する必要があります。
というわけで、Resource Dependenciesの手順に従って、AWSのインスタンスにElastic IP紐付ける構築をします。

記載の通りに修正して、<code>terraform plan</code>を実行すると、実行計画を確認できます。

$ terraform plan
:
+ aws_eip.ip
    allocation_id:     "<computed>"
    association_id:    "<computed>"
    domain:            "<computed>"
    instance:          "${aws_instance.example.id}"
    network_interface: "<computed>"
    private_ip:        "<computed>"
    public_ip:         "<computed>"

+ aws_instance.example
    ami:                      "ami-13be557e"
    availability_zone:        "<computed>"
    ebs_block_device.#:       "<computed>"
    ephemeral_block_device.#: "<computed>"
    instance_state:           "<computed>"
    instance_type:            "t2.nano"
    key_name:                 "<computed>"
    network_interface_id:     "<computed>"
    placement_group:          "<computed>"
    private_dns:              "<computed>"
    private_ip:               "<computed>"
    public_dns:               "<computed>"
    public_ip:                "<computed>"
    root_block_device.#:      "<computed>"
    security_groups.#:        "<computed>"
    source_dest_check:        "true"
    subnet_id:                "<computed>"
    tenancy:                  "<computed>"
    vpc_security_group_ids.#: "<computed>"


Plan: 2 to add, 0 to change, 0 to destroy.

構築時に、Elastic IPリソースに指定されているEC2インスタンスIDを検出し、EC2インスタンスを先に作成しています。

$ terraform apply
aws_instance.example: Creating...
  ami:                      "" => "ami-13be557e"
  availability_zone:        "" => "<computed>"
  ebs_block_device.#:       "" => "<computed>"
  ephemeral_block_device.#: "" => "<computed>"
  instance_state:           "" => "<computed>"
  instance_type:            "" => "t2.nano"
  key_name:                 "" => "<computed>"
  network_interface_id:     "" => "<computed>"
  placement_group:          "" => "<computed>"
  private_dns:              "" => "<computed>"
  private_ip:               "" => "<computed>"
  public_dns:               "" => "<computed>"
  public_ip:                "" => "<computed>"
  root_block_device.#:      "" => "<computed>"
  security_groups.#:        "" => "<computed>"
  source_dest_check:        "" => "true"
  subnet_id:                "" => "<computed>"
  tenancy:                  "" => "<computed>"
  vpc_security_group_ids.#: "" => "<computed>"
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Still creating... (20s elapsed)
aws_instance.example: Creation complete
aws_eip.ip: Creating...
  allocation_id:     "" => "<computed>"
  association_id:    "" => "<computed>"
  domain:            "" => "<computed>"
  instance:          "" => "i-452dcad4"
  network_interface: "" => "<computed>"
  private_ip:        "" => "<computed>"
  public_ip:         "" => "<computed>"
aws_eip.ip: Creation complete

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

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

Provision

Provisionはインスタンスを構築後に実行する処理を指定します。
Provisionの手順に従って、インスタンスを構築後にサーバー上でIPアドレスをファイル出力させます。

$ terraform apply
aws_instance.example: Creating...
  ami:                      "" => "ami-13be557e"
  availability_zone:        "" => "<computed>"
  ebs_block_device.#:       "" => "<computed>"
  ephemeral_block_device.#: "" => "<computed>"
  instance_state:           "" => "<computed>"
  instance_type:            "" => "t2.nano"
  key_name:                 "" => "<computed>"
  network_interface_id:     "" => "<computed>"
  placement_group:          "" => "<computed>"
  private_dns:              "" => "<computed>"
  private_ip:               "" => "<computed>"
  public_dns:               "" => "<computed>"
  public_ip:                "" => "<computed>"
  root_block_device.#:      "" => "<computed>"
  security_groups.#:        "" => "<computed>"
  source_dest_check:        "" => "true"
  subnet_id:                "" => "<computed>"
  tenancy:                  "" => "<computed>"
  vpc_security_group_ids.#: "" => "<computed>"
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Still creating... (20s elapsed)
aws_instance.example: Still creating... (30s elapsed)
aws_instance.example: Provisioning with 'local-exec'...
aws_instance.example (local-exec): Executing: /bin/sh -c "echo 54.167.38.210 > file.txt"
aws_instance.example: Creation complete
aws_eip.ip: Creating...
  allocation_id:     "" => "<computed>"
  association_id:    "" => "<computed>"
  domain:            "" => "<computed>"
  instance:          "" => "i-5934d3c8"
  network_interface: "" => "<computed>"
  private_ip:        "" => "<computed>"
  public_ip:         "" => "<computed>"
aws_eip.ip: Creation complete

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

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

$ cat file.txt
54.167.38.210

Input Variables

ここまでの例では、AWSのアクセスキーやシークレットキーなどをexample.tfに直接設定していました。
これは実運用では著しく問題があります。
Terraformには別ファイルやコマンド実行時の変数、環境変数から変数を渡すことができます。

Input Variablesの手順に従って、実行してみましょう。

上記に記載の方法以外に

  • 変数ファイルterraform.tfvarsという名前のファイル内変数は、変数として自動参照
  • 環境変数TF_VAR_<変数名>の環境変数は、変数として自動参照

です。

これ以外にOutput Variables, Modulesもありますが、ちょっと使う程度であれば見る必要はありません。