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

Terraform を使ってみたので、その概要をまとめてみました。Terraform は CloudFormation よりも定義ファイルが簡潔で、習得し易いツールです。しかも CloudFormation と違って AWS から Azure, Google Cloud, Heroku などさまざまな環境を対象にすることができます。

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

Environment

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

Install Terraform

Install Terraform の手順に従い Terraform をインストールします。

Mac 向けのバイナリパッケージがあるので Download Terraform からファイルをダウンロードし、適当なディレクトリで解凍後、パスを通すだけで終わりです。 .bash_profileexport するといいでしょう。

export PATH="/usr/local/terraform/0.7.1/bin:$PATH"

ターミナルから terraform コマンドを実行できればセットアップに問題はありません。

$ terraform
usage: terraform [–version] [–help] <command> [args]
The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply Builds or changes infrastructure
    destroy Destroy Terraform-managed infrastructure
    fmt Rewrites config files to canonical format
    get Download and install modules for the configuration
    graph Create a visual graph of Terraform resources
    import Import existing infrastructure into Terraform
    init Initializes Terraform configuration from a module
    output Read an output from a state file
    plan Generate and show an execution plan
    push Upload this Terraform module to Atlas to run
    refresh Update local state file against real resources
    remote Configure remote state storage
    show Inspect Terraform state or plan
    taint Manually mark a resource for recreation
    untaint Manually unmark a resource as tainted
    validate Validates the Terraform files
    version Prints the Terraform version

All other commands:
    state Advanced state management

Build Infrastructure

Build Infrastructure の手順に従い AWS に EC2 を構築します。 手順では t2.micro と記載されていますが、ここは t2.nano に変えています。

provider "aws" {
  access_key = "ACCESS_KEY_HERE"
  secret_key = "SECRET_KEY_HERE"
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami = "ami-0d729a60"
  instance_type = "t2.nano"
}

terraform plan を実行すると、実行計画を確認できます。

$ terraform plan
Refreshing Terraform state in-memory prior to plan…
The refreshed state will be used to calculate this plan, but
will not be persisted to local or remote state storage.
The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed. Cyan entries are data sources to be read.
Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

+ aws_instance.example
    ami: "ami-0d729a60"
    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: 1 to add, 0 to change, 0 to destroy.

<computed>はリソースを作成してみないとわからない項目です。

というわけで terraform apply を実行してみましょう。

$ terraform apply
aws_instance.example: Creating…
  ami: "" => "ami-0d729a60"
  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

Apply complete! Resources: 1 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

と書いてある通り AWS 上に EC2 が構築されました。

Change Infrastructure

Change Infrastructure の手順に従い AWS 上に構築した EC2 の設定を変えます。 aws.tf を修正したら Build Infrastructure と同様に terraform plan, terraform apply を実行します。

$ terraform plan
+ aws_instance.example
    ami: "ami-0d729a60" => "ami-13be557e" (forces new resource)
    availability_zone: "us-east-1c" => "<computed>"
    ebs_block_device.#: "0" => "<computed>"
    ephemeral_block_device.#: "0" => "<computed>"
    instance_state: "running" => "<computed>"
    instance_type: "t2.nano" => "t2.nano"
    key_name: "" => "<computed>"
    network_interface_id: "eni-b954dda9" => "<computed>"
    placement_group: "" => "<computed>"
    private_dns: "ip-172-31-51-198.ec2.internal" => "<computed>"
    private_ip: "172.31.51.198" => "<computed>"
    public_dns: "ec2-54-164-45-203.compute-1.amazonaws.com" => "<computed>"
    public_ip: "54.164.45.203" => "<computed>"
    root_block_device.#: "1" => "<computed>"
    security_groups.#: "0" => "<computed>"
    source_dest_check: "true" => "true"
    subnet_id: "subnet-6e303a44" => "<computed>"
    tenancy: "default" => "<computed>"
    vpc_security_group_ids.#: "1" => "<computed>"

Plan: 1 to add, 0 to change, 1 to destroy.
$ terraform apply
aws_instance.example: Refreshing state… (ID: i-01c22590)
aws_instance.example: Destroying…
aws_instance.example: Still destroying… (10s elapsed)
aws_instance.example: Still destroying… (20s elapsed)
aws_instance.example: Destruction complete
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… (5s elapsed)
aws_instance.example: Still creating… (30s elapsed)
aws_instance.example: Creation complete

Apply complete! Resources: 1 added, 0 changed, 1 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

インスタンスID が変わっていることからも分かる通り、新規作成->既存破壊という流れになっています。

Destroy Infrastructure

Destroy Infrastructure の手順に従い AWS 上に構築した EC2 を破棄します。 terraform plan -destroy で破棄の実行計画を確認します。

$ terraform plan -destroy
Refreshing Terraform state in-memory prior to plan…
The refreshed state will be used to calculate this plan, but
will not be persisted to local or remote state storage.
aws_instance.example: Refreshing state… (ID: i-72c82fe3)
The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed. Cyan entries are data sources to be read.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

– aws_instance.example

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

続いて terraform destroy で実際に破棄します。

デフォルトは [Enter a value:] で入力待ちになるので [yes] と入力するとそのまま破棄が実行されます。

$ terraform destroy
Do you really want to destroy?
  Terraform will delete all your managed infrastructure.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

aws_instance.example: Refreshing state… (ID: i-72c82fe3)
aws_instance.example: Destroying…
aws_instance.example: Still destroying… (10s elapsed)
aws_instance.example: Still destroying… (20s elapsed)
aws_instance.example: Still destroying… (30s elapsed)
aws_instance.example: Destruction complete

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