Skip to the content.

terraform

インストール

brew install tfenv
tfenv install 0.8.1
tfenv install latest
tfenv install latest:^0.8 # 0.8系で最新インストールされる

# 指定したバージョンを使用する
tfenv use 0.8.1
tfenv use latest:^.0.8

# インストールして使用可能なバージョンを一覧表示
tfenv list

# インストール可能なバージョンを表示
tfenv list-remote

設定

変数

外部から変数を付与する方法は主に以下の3種類

No. 種類 補足 上書例
1 環境変数 TF_VAR_<NAME> msgという変数が定義されているとTF_VAR_msgで定義可能 export TF_VAR_msg="ABC" terraform apply
2 変数ファイル sample.tfvars git管理可能 tfvarsという拡張子で定義されたファイルであれば-var-fileの引数で指定しなくても自動でtfvars拡張子ファイルが適用される
3 コマンド引数 -var = テストや一時的な利用で使える terraform apply -var msg="EFG"

仕様

tfstateとは

# Backend
terraform {
  required_version = "1.5.6"

  required_providers {
    aws = "5.15.0"
  }

  backend "s3" {
    region         = "ap-northeast-1"
    key            = "任意のファイル名.tfstate"
    dynamodb_table = "任意のDynamoDB名" # オプション。状態ロックをDynamodbで管理することが可能
    bucket         = "任意のバケット名"    # オプション
    encrypt        = true              # オプション
  }
}

構文

ブロックタイプ

種類 説明 補足 具体例
locals 変数: 外部から変更不可   ${local.<変数名>}で参照
variables 変数: 外部から変更可能 コマンド実行時にオプション、ファイル指定で上書き可能 ${var.<変数名>}で参照
terraform terraform本体の設定 terraformブロックはterraform本体、providerは各サービスのことで対となるような存在  
provider AWSやAzure,GCPなどの対象サービスのこと    
data terraform管理外のリソース取得    
resource terraform管理内のリソース    
output 外部から参照できるようにする値    
import 手動で作成した既存リソースの取り込み? 最終手段?  
       

リソースのインポート

手動作成したリソースなどをterraform管理下に取り込むことができる。大枠は以下

  1. 手動作成したリソース名に相当するコードを作成(アドレス.取り込み先リソース名)
    • コードの側だけ作成し、中身は後でインポートで取り込むため空でOK
  2. 指定したリソースをインポート(terraform import 取り込み先リソース名 ターゲットID)
  3. インポートしたリソースをterraform state show アドレス.リ対象リソース名で表示し、1のコードに落とし込む
import {
  to = aws_codestarconnections_connection.リソース名
  id = "arn:aws:codestar-connections:us-west-1:0123456789:connection/idididididididididididididididididid"
}

リソースの移動

moved {
  from = aws_codebuild_project.旧リソース名(移動前)
  to   = aws_codebuild_project.新リソース名(移動後)
}

メタ引数

No. 種類 補足 上書例
depends_on        
count        
for_each        
lifecycle        
provider        

拡張機能

vscodeではグラフ化に便利なgraphvizという拡張機能があり依存関係を可視化できる

参考ドキュメント

HCL2とterraformCLI

HCL2とterraformCLI

よく使う事例

terraform console
>length(["a", "b"])
# dataブロックで事前に定義しておくこと
terraform console
>data.aws_ec2_managed_prefix_list.プレフィックスリスト名.entries[*].cidr

lifecycle

# passwordなど変更する余地があるリソースが変更されても更新対象としないように設定する
  lifecycle {
    ignore_changes = [
      master_password
    ]
  }

コマンド

terraform init
# 現在の状態とコードに定義された状態を比較して、変更が必要な場合に変更内容を表示)
terraform plan
# 特定のリソースのみ確認する
terraform plan -target=指定したいリソース名
# 結果を指定ファイル名へ出力する
terraform plan -out=ファイル名
# デバッグログを有効にして詳細な情報を表示
TF_LOG=DEBUG terraform plan
# クラウド上の現状を反映させる
terraform refresh             # こちらはterraform1.0未満の古いコマンドで1.x系では非推奨
terraform apply -refresh-only
# tfstateで管理されているリソースの一覧表示
terraform state list
# tfstateで管理されているリソースの詳細表示。terraform planで差分ない時に詳細確認した場合にも便利
terraform state show アドレス.リソース名
# 注意点としてコードの方も合わせて変更しておくこと
terraform state mv アドレス.変更前リソース名 アドレス.変更後リソース名
# tfstateファイルへリソースのインポートがされるため、コード上は変化なし
terraform import アドレス.リソース名(任意名) ターゲットID 
# y/nのプロンプトで最終確認あり
terraform apply
# 特定のリソースのみデプロイ
terraform apply -target=指定したいリソース名
# プロンプトを表示せずに自動的に承認(確認プロンプトが不要)
terraform apply -auto-approve
terraform apply -destroy
terraform apply -destroy -target=指定したいリソース名
terraform destory -auto-approve # プロンプトを表示せずに自動的に承認(確認プロンプトが不要)

# terraform管理外から外す
terraform state rm アドレス.変更前リソース名 # コード上にリソースが残っていれば再構築されてしまうので注意
### フォーマット(カレントディレクトリ) ※変更したファイル名のみ表示 ###
terraform fmt
# フォーマット(変更されるファイル名を事前検証)
terraform fmt -check
# フォーマット(サブディレクトリ含む)
terraform fmt -recursive
# フォーマット(サブディレクトリ含んでフォーマット内容をdiffで表示して事前検証)
terraform fmt -recursive -diff -check
# 組み込み関数などや変数を試したい時のお試し
terraform console
>local.ターゲット名
ターゲット内容が出力される...
>type(local.default_list)
typeが出力される...

トラブルシューティング

Terraform acquires a state lock to protect the state from being written
by multiple users at the same time. Please resolve the issue above and try
again. For most commands, you can disable locking with the "-lock=false"
flag, but this is not recommended.
# 状態ロック自体を解除
terraform force-unlock xxxxxx(ID)

# 状態ロックを無視してapply
terraform apply -lock=false

コード例

variable "env" {
  default = "dev"
}
// 例 条件 ? true : false
value = var.env == "prod" ? "t2.large" : "t2.micro"
# リスナールールの加重ルーティング例
resource "aws_lb_listener_rule" "ecs_https_1" {
  listener_arn = aws_lb_listener.tmp_https.arn
  priority     = 100

  action {
    type             = "forward"

    forward {
      target_group {
        arn    = ターゲットグループarn1
        weight = 90
      }

      target_group {
        arn    = ターゲットグループarn2
        weight = 10
      }
      stickiness {
        enabled  = true
        duration = 600
      }
    }
  }

  condition {
    host_header {
      values = [
        対象ドメイン名
      ]
    }
  }

  lifecycle {
    ignore_changes = [
      # target_groupはBlue/Greenデプロイで動的に変更される
      action["forward"],
    ]
  }
}

参考