CheatSheet
日本語 icon日本語English iconEnglish
チートシートとはカンニングペーパーのことです。それが転じて、本来覚えることをまとめておいたものです。
要点をすぐに参照できるようにまとめてみました。

Terraform

エンジニアのためのWebチートシート

Terraformは、HashiCorpが開発したIaC(Infrastructure as Code)ツールです。 HCL(HashiCorp Configuration Language)でインフラをコードとして定義し、マルチクラウド環境を宣言的に管理できます。 CLIコマンド、HCL構文、リソース定義、ステート管理、モジュール、関数などをチートシートにまとめました。

CLIコマンド

コアワークフロー

コマンド説明
terraform initワーキングディレクトリを初期化し、プロバイダをダウンロードします。
terraform init -upgradeプロバイダ・モジュールを最新バージョンに更新します。
terraform validate設定ファイルの構文・論理チェックを行います。
terraform fmtHCLコードを標準フォーマットに整形します。
terraform fmt --checkフォーマットチェックのみ行います(CI/CD向け)。
terraform plan実行計画を表示します(ドライラン)。
terraform plan -out=tfplan実行計画をファイルに保存します。
terraform applyインフラを作成・更新します。
terraform apply -auto-approve確認プロンプトなしで適用します。
terraform apply -var="key=value"変数を指定して適用します。
terraform apply -target="resource.name"特定のリソースのみ適用します。
terraform destroy管理下の全インフラを破棄します。
terraform destroy -auto-approve確認プロンプトなしで破棄します。

検査 & デバッグ

コマンド説明
terraform showステートファイルを人間可読形式で表示します。
terraform output定義された出力値を一覧表示します。
terraform output -json出力値をJSON形式で表示します。
terraform console式のテスト・デバッグ用の対話コンソールを起動します。
terraform graphDOT言語で依存関係グラフを生成します。
terraform providers使用しているプロバイダをツリー表示します。
terraform versionTerraformのバージョンを表示します。

HCL構文基礎

terraform & provider ブロック

  • バージョン制約、プロバイダ設定、バックエンド設定の基本です。

    terraform {
      required_version = ">= 1.0"
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = "~> 5.0"
        }
      }
      backend "s3" {
        bucket = "my-tf-state"
        key    = "terraform.tfstate"
        region = "ap-northeast-1"
      }
    }
    
    provider "aws" {
      region = "ap-northeast-1"
    }

入力変数 (variable)

  • モジュールの入力パラメータを定義します。型、デフォルト値、バリデーションを設定できます。

    variable "instance_type" {
      description = "EC2 instance type"
      type        = string
      default     = "t3.micro"
      sensitive   = false
    
      validation {
        condition     = contains(["t3.micro", "t3.small"], var.instance_type)
        error_message = "Must be t3.micro or t3.small."
      }
    }
    # Types: string, number, bool,
    #   list(type), set(type), map(type),
    #   object({...}), tuple([...]), any
    
    # Set variables via:
    #   terraform.tfvars / *.auto.tfvars
    #   -var="key=value" / -var-file="file.tfvars"
    #   TF_VAR_<name> environment variable

出力値 & ローカル値

  • output(外部公開値)とlocals(内部計算値)の定義です。

    output "instance_ip" {
      description = "Public IP of the instance"
      value       = aws_instance.web.public_ip
      sensitive   = false
    }
    locals {
      common_tags = {
        Environment = var.environment
        Project     = "my-project"
        ManagedBy   = "terraform"
      }
      name_prefix = "${var.project}-${var.env}"
    }
    data "aws_ami" "ubuntu" {
      most_recent = true
      owners      = ["099720109477"]
      filter {
        name   = "name"
        values = ["ubuntu/images/hvm-ssd/*"]
      }
    }

リソース定義

リソース & データソース

  • インフラリソースの作成と既存リソースの参照です。

    # Create a resource
    resource "aws_instance" "web" {
      ami           = data.aws_ami.ubuntu.id
      instance_type = var.instance_type
    
      tags = local.common_tags
    
      depends_on = [aws_security_group.web]
    }
    
    # Reference: <type>.<name>.<attribute>
    # aws_instance.web.public_ip
    
    # Data source reference
    # data.<type>.<name>.<attribute>
    # data.aws_ami.ubuntu.id

メタ引数 (count / for_each)

  • count

    resource "aws_instance" "web" {
      count         = 3
      ami           = "ami-12345"
      instance_type = "t3.micro"
      tags = { Name = "web-${count.index}" }
    }
    # Ref: aws_instance.web[0].id
  • for_each

    resource "aws_instance" "web" {
      for_each      = toset(["app", "api", "worker"])
      ami           = "ami-12345"
      instance_type = "t3.micro"
      tags = { Name = each.key }
    }
    # Ref: aws_instance.web["app"].id
  • for_each (map)

    resource "aws_instance" "servers" {
      for_each = {
        app    = "t3.small"
        worker = "t3.medium"
      }
      ami           = "ami-12345"
      instance_type = each.value
      tags = { Name = each.key }
    }

count vs for_each 比較

特性countfor_each
入力型数値map / set
参照方法count.indexeach.key, each.value
削除時の挙動インデックスずれが発生キーベースで安全
推奨用途同一構成のリソース複製異なる構成のリソース群

ステート管理

ステートコマンド

コマンド説明
terraform state list管理しているリソースの一覧を表示します。
terraform state show <resource>特定リソースの詳細情報を表示します。
terraform state mv <src> <dst>リソースのアドレスを変更します(リネーム)。
terraform state rm <resource>ステートからリソースを削除します(実インフラは残る)。
terraform state pullリモートステートを取得して標準出力に表示します。
terraform state pushローカルステートをリモートにプッシュします。
terraform import <resource> <id>既存のインフラリソースをTerraform管理下にインポートします。
terraform force-unlock <lock_id>ステートのロックを強制解除します。

リモートバックエンド

  • ステートファイルをリモートストレージで管理する設定です。

    # S3 backend
    terraform {
      backend "s3" {
        bucket       = "my-terraform-state"
        key          = "prod/terraform.tfstate"
        region       = "ap-northeast-1"
        encrypt      = true
        use_lockfile = true  # v1.10+
      }
    }
    
    # GCS backend
    terraform {
      backend "gcs" {
        bucket = "my-terraform-state"
        prefix = "prod"
      }
    }

import & moved ブロック

  • import (v1.5+)

    import {
      to = aws_instance.example
      id = "i-1234567890abcdef0"
    }
  • moved / removed

    moved {
      from = aws_instance.old_name
      to   = aws_instance.new_name
    }
    
    removed {
      from = aws_instance.example
      lifecycle { destroy = false }
    }

モジュール

モジュールの使用

  • Registry module

    module "vpc" {
      source  = "terraform-aws-modules/vpc/aws"
      version = "~> 5.0"
      name = "my-vpc"
      cidr = "10.0.0.0/16"
      azs  = ["ap-northeast-1a", "ap-northeast-1c"]
    }
  • Local module

    module "app" {
      source        = "./modules/app"
      name          = "my-app"
      instance_type = var.instance_type
      vpc_id        = module.vpc.vpc_id
    }
    # Output ref: module.vpc.vpc_id

ソースの種類

ソース種類
ローカルパス./modules/vpc
Terraform Registryhashicorp/consul/aws
GitHubgithub.com/org/repo
S3バケットs3::https://bucket/module.zip

バージョン制約

演算子意味
= 1.2.3指定バージョンのみ
!= 1.2.3指定バージョン以外
>= 1.0, < 2.0指定範囲内のバージョン
~> 1.2~> 1.2 → >= 1.2, < 2.0

式と関数

式・条件・ループ

  • Conditional / For / Splat

    # Conditional
    instance_type = var.env == "prod" ? "t3.large" : "t3.micro"
    
    # For expression
    upper_names = [for n in var.names : upper(n)]
    adults = [for p in var.people : p.name if p.age >= 18]
    name_map = {for s in var.servers : s.name => s.ip}
    
    # Splat
    instance_ids = aws_instance.web[*].id
  • Dynamic block

    dynamic "ingress" {
      for_each = var.ingress_rules
      content {
        from_port   = ingress.value.from_port
        to_port     = ingress.value.to_port
        protocol    = ingress.value.protocol
        cidr_blocks = ingress.value.cidr_blocks
      }
    }
  • String / Heredoc

    name = "web-${var.environment}"
    
    policy = <<-EOT
      { "Version": "2012-10-17" }
    EOT

主要な組み込み関数

カテゴリ主要関数
文字列format, join, split, replace, upper, lower, trimspace
数値abs, ceil, floor, max, min, parseint
コレクションlength, merge, concat, flatten, keys, values, lookup, contains, distinct, sort, one
型変換tostring, tonumber, tobool, tolist, toset, tomap
エンコーディングjsonencode, jsondecode, yamlencode, yamldecode, base64encode, base64decode
ファイルfile, fileexists, templatefile, abspath, basename
ネットワークcidrhost, cidrnetmask, cidrsubnet, cidrsubnets

ライフサイクル & プロビジョナ

ライフサイクルルール

  • lifecycle

    lifecycle {
      create_before_destroy = true
      prevent_destroy       = true
      ignore_changes        = [tags]  # or = all
      replace_triggered_by  = [aws_security_group.web.id]
    }
  • precondition / postcondition

    precondition {
      condition     = var.env != ""
      error_message = "env must not be empty."
    }
    
    postcondition {
      condition     = self.public_ip != ""
      error_message = "Must have a public IP."
    }

プロビジョナ

  • local-exec / file

    provisioner "local-exec" {
      command = "echo ${self.private_ip}"
    }
    
    provisioner "file" {
      source      = "conf/app.conf"
      destination = "/etc/app.conf"
    }
  • remote-exec

    provisioner "remote-exec" {
      inline = [
        "sudo apt-get update",
        "sudo apt-get install -y nginx"
      ]
      connection {
        type        = "ssh"
        user        = "ubuntu"
        private_key = file("~/.ssh/id_rsa")
        host        = self.public_ip
      }
    }
  • terraform_data

    resource "terraform_data" "run" {
      triggers_replace = [aws_instance.web.id]
      provisioner "local-exec" {
        command = "echo 'Instance recreated'"
      }
    }

ワークスペース

ワークスペースコマンド

コマンド説明
terraform workspace listワークスペースの一覧を表示します。
terraform workspace show現在のワークスペース名を表示します。
terraform workspace new <name>新しいワークスペースを作成して切り替えます。
terraform workspace select <name>指定したワークスペースに切り替えます。
terraform workspace delete <name>ワークスペースを削除します。

ワークスペースの活用

  • terraform.workspace で環境を切り替える使用例です。

    resource "aws_instance" "example" {
      instance_type = (
        terraform.workspace == "prod" ? "t3.large" : "t3.micro"
      )
      tags = { Environment = terraform.workspace }
    }
    locals {
      env_config = {
        dev  = { count = 1, type = "t3.micro" }
        stg  = { count = 2, type = "t3.small" }
        prod = { count = 3, type = "t3.large" }
      }
      config = local.env_config[terraform.workspace]
    }

プロジェクト構成

推奨ディレクトリ構成

  • Terraformプロジェクトの標準的なファイル構成です。

    project/
      main.tf            # Main resources
      variables.tf       # Input variables
      outputs.tf         # Output values
      providers.tf       # Provider config
      terraform.tf       # terraform block
      terraform.tfvars   # Variable values
      modules/
        app/
          main.tf
          variables.tf
          outputs.tf
        network/
          main.tf
          variables.tf
          outputs.tf

.gitignore 推奨設定

  • Terraformプロジェクトでバージョン管理から除外すべきファイルです。

    # .gitignore
    .terraform/
    *.tfstate
    *.tfstate.*
    crash.log
    override.tf
    override.tf.json
    
    # Keep lock file in Git
    # .terraform.lock.hcl

ベストプラクティス

プラクティス
リモートバックエンドを使用し、暗号化とバージョニングを有効化する
.terraform.lock.hcl をGitにコミットする
terraform.tfstate は絶対にGitにコミットしない
変数には description, type, validation を設定する
モジュールにはバージョン制約を指定する(~> 推奨)
terraform plan を常に apply 前に実行する
センシティブな値には sensitive = true を使用する
count よりも for_each を推奨する(安全な削除)
ステートロックを必ず有効化する