後ろを向いて後退します

これって前に進んでいることになりませんか?

Terraformコマンド紹介

一人Terraform Advent Calendar

この記事は一人Terraform Advent Calendarの3日目の記事です。

adventar.org

Terraformコマンド紹介

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
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    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               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    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
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

この記事では、主によく使うものや便利なものについて紹介します。

紹介するサブコマンド

  • init
  • apply
  • destroy
  • plan
  • refresh
  • import

サブコマンド紹介・解説

init

www.terraform.io

e.g.)
$ terraform init

initコマンドを実行すると * Backendコンフィグの初期化 * モジュールの初期化 * プラグインのインストール が必要に応じて行われます。モジュールの初期化、プラグインのインストールは、新しくリソースを定義した後にレシピを適用する前に必ず実行しなければエラーになってしまいます。CI/CDにTerraformを組み込む場合や運用スクリプトを整備する場合はinitコマンドを必ず実行するように書いておくと良いでしょう。

www.terraform.io

Backendコンフィグの初期化時には、tfstateの保存パスが以前のコンフィグのものと異なる場合に「既存のstateを使いまわすかどうか」を問う旨のメッセージが表示されます。単純に保存先のパスを変更したい場合には使いまわしても大丈夫ですが、例えば保存パスを外部から注入して構築した環境ごとに別々のstateで管理したいようなケースでは、使いまわした後にレシピを適用すると既存の環境が全て破壊されて再作成されてしまう点に注意してください。

stateの保存パスの変更時に常に既存のstateを使い回さないようにするには、以下のように-reconfigureオプションをつけて実行してください。

$ terraform init -reconfigure

apply

www.terraform.io

e.g.)
$ terraform apply

applyコマンドは手元にあるレシピをクラウド上のリソースに反映して、リソースの作成・削除・変更を行います。実行の前にはrefreshコマンドとdry-run(planコマンド)が暗黙的に実行されます。

既存リソースのargumentの一部を変更した場合でも、リソースの変更にとどまらずリソースの削除→再作成が走ることがあります。これは。クラウドプロバイダ側がリソース作成後に変更することを許していないargumentを変更しようとした場合に発生します。

また、デフォルトではコマンドを実行した直下のプロジェクトで管理されるリソースが全てレシピ実行の対象となりますが、-targetオプションで特定のリソースのみを対象としてレシピを実行することができます。リソースの指定には、TerraformのResourceAddressingの戦略に基づいて決められたリソースのパスを使用します。

www.terraform.io

applyコマンドの実行時には、リソースやモジュールの依存関係は自動的に解決されて適切な順序で作成が行われますが、例えばモジュールA.リソースa1モジュールB.リソースb1に依存し、モジュールB.リソースb2モジュールA.リソースa2に依存しているような形でレシピを定義してしまった場合は、依存関係のデッドロックが発生してリソースが作成されません。デッドロックが発生しないようなモジュール設計を心がける必要があります。

destroy

www.terraform.io

e.g.)
$ terraform destroy

リソースの削除自体はapplyコマンドでも行われますが、destroyコマンドはstateで管理されているすべてのリソースを削除します。S3バケットやその他複雑な依存関係を持つリソースによっては特定の条件下でないと削除できないものもあるので、-targetオプションで特定のリソースのみを削除したい場合には注意が必要です。デフォルトで実行する場合にはTerraformが削除の順序を自動的に判断してくれます。

learn.hashicorp.com

Just like with apply, Terraform determines the order in which things must be destroyed. In this case there was only one resource, so no ordering was necessary. In more complicated cases with multiple resources, Terraform will destroy them in a suitable order to respect dependencies, as we'll see later in this guide.

applyコマンドと同様に、Terraformはどういう順序でリソースを削除されるべきかを判断してくれます。この場合リソースが一つしか無ければ、特に順序付けは必要ありません。より複雑な依存関係がある場合は、Terraformは依存関係に従って最適な順序でリソースを削除します。

plan

www.terraform.io

e.g.)
$ terraform plan

planコマンドは、レシピを適用した場合にどのリソースが作成・削除・変更されるのかを一覧で表示してくれるdry-runの機能を担っています。基本的なオプションはapplyコマンドと同様です。

refresh

www.terraform.io

e.g.)
$ terraform refresh

2日目の記事の「事始め」でも書いた通り、Terraformはリソースに対してどのような変更を加えるかをレシピとstateとの差分を見て適切に判断しています。前回のレシピの適用移行、Terraformの見えない範囲で(例えばGUI上から手動で)変更が加えられた場合、クラウド上にあるリソースとstateとの間に差分ができてしまいます。

refreshコマンドは、クラウド上にあるリソースの実体の状態をstateに反映するコマンドです。applyコマンドはデフォルトでrefreshコマンドを事前に実行するようになっています。

github.com

import

www.terraform.io

e.g.)
$ terraform import module.my-s3-buckets.aws_s3_bucket.my-bucket my-bucket-id

第一引数には、クラウドからimportしたリソースをレシピ中のどのリソースに対応付けるかを指定します。第二引数では、そのリソースを参照するための一意な値を指定します。この値はリソースのタイプによって異なります。

上の例では、AWS上にあるmy-bucket-idというIDを持つS3バケットmy-s3-bucketsモジュール下のmy-bucketというS3バケットのレシピに対応づけてimportしています。importコマンドを使うのは大体が既存のインフラをTerraformで管理できるようにしたいようなニーズだと思いますが、残念ながらTerraformはimportしたリソースに対応するレシピを自動的に生成する機能をまだ持っていません。import後のstateに完全に一致するようなレシピはユーザーが手作りする必要があります。

まとめ

  • initは毎回実行したほうがいい
  • applyはレシピを適用する
  • destroyは全てを破壊する
  • planはdry-run
  • refreshは同期
  • importは取り込み