😸

Terraformを突如見ることになったときのメモ

に公開

ファイルの種類

設定ファイル( .tf )

一番基本的なファイル。HCLという独自言語か、JSONで記述される。
Terraformは現在のディレクトリにある、.tf で終わるすべてのファイルを読みこんでくれるので、役割に応じた名前をつけることが可能。
mainとかvariablesとかファイルが別れてることが多いけど気にすることはない。

変数定義ファイル(.tfvars)

.tfで宣言されている変数に対して値を設定するためのファイル。
terraform.tfvars というファイル名にすると、Terraformが自動的に読み込む。
*.auto.tfvarsのようにautoを接尾辞としてつけた場合もTerraformは自動的に読み込む。
その他ファイル名で作った場合、明示的に指定する必要がある。

状態ファイル(terraform.tfstate および terraform.tfstate.backup)

Terraformが管理しているインフラの状態を保存しているJSONファイル。これがないと現在のインフラの状況がわからなくなってしまうので反映でエラーになったりする。
terraform.tfstateは最新の状態を保存しており、terraform.tfstate.backupは前回の状態をバックアップとして保存しています。
デフォルトでは、ローカルに保存されるものの、共同作業をする場合などもあるので基本的にはTerraform CloudやAWS S3上に保存するのが一般的。

ロックファイル(.terraform.lock.hcl)

いわゆるバージョン管理用のロックファイル。terraform initを実行した際に意図しないプロバイダのバージョンがインストールされることを防ぎます。
初回のterraform initの際に自動生成されるので自分自身で作成することはない。

オーバーライドファイル (override.tfまたは*_override.tf)

既存の設定ファイルの一部を上書きするためのファイル。このファイルはTerraformが最後に読み込むようになっている。

各種記述ブロック

tfファイルに記載される項目に関しての解説。

terraform ブロック

terraformブロックは、名前の通りTerraform自体の動作設定や、必要なプロバイダーのバージョンなどを定義するブロックになっている。

terraform {
  # Terraform CLIのバージョンの制約
  required_version = ">= 1.0"

  # 使用するプロバイダーとそのバージョンの制約
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  
  # backendは状態ファイルの保存先指定
  backend "s3" {
    bucket = "my-terraform-state-bucket"
    key    = "global/s3/terraform.tfstate"
    region = "ap-northeast-1"
  }
}

provider ブロック

各種プロバイダーの設定を行うのに利用します。

provider "aws" {
  region  = "ap-northeast-1"
  profile = "my-aws-profile" # これはオプション
}

このプロバイダーブロックは、プロバイダーごとのDocumentationにかかれているので確認しましょう。
例としてAWSのドキュメント
https://registry.terraform.io/providers/hashicorp/aws/latest/docs

resource ブロック

Terraformで管理したいインフラストラクチャリソースを定義するブロック。(例えばEC2インスタンス、S3、VPCの設定など)
このブロックはproviderのドキュメントに記載があります。

resource "aws_instance" "example_server" {
  ami           = "ami-xxxxxxxxxxxxxxxxx"
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleServer"
  }
}

data ブロック

dataブロックはTerraformの外に既に存在しているリソースの内容や、特定の計算結果などを読み込んで利用できるようにするブロックです。例えば、既存のAMI IDやVPCの情報を取得したりします。

data "aws_ami" "latest_amazon_linux" {
  most_recent = true # 複数存在する場合は最新を選ぶか
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-default-x86_64"]
  }
}

上記の例だと、最新のAmazon Linux 2023の最新カーネルでx86_64アーキテクチャのAMIを取得しようとします。
フィルターは複数記述することができるので、このあたりはプロバイダーのドキュメントを見つつ調整をしましょう。

variable ブロック

Terraformコードへの入力値を定義します。これはコードを再利用しやすくして環境ごとの設定変更を楽にします。

variable "instance_type" {
  description = "The type of EC2 instance to launch."
  type        = string
  default     = "t2.micro"
}

typeにはstringnumberboolが基本として選ぶことができ、型コンストラクタを利用するとコレクションなどの複数の型を指定できる。(list(<TYPE>), set(<TYPE>), map(<TYPE>), object({<ATTR_NAME> = <TYPE>, ...}), tuple([<TYPE>, ...]))
一応、anyも存在しているが、まあ使わないほうが良いでしょう。
利用時は、var.変数名 で記述すると利用できます。

詳しい記述は公式を見たほうがわかるかと思います。
https://developer.hashicorp.com/terraform/language/values/variables

output ブロック

Terraformが作成したリソースを実行後に出力したり、出力情報を他のTerraform設定で利用(子モジュールから親モジュールで利用する用途)したりできるようにします。

output "instance_public_ip" {
  description = "Public IP address of the example_server instance."
  value       = aws_instance.example_server.public_ip
}

locals ブロック

複雑な式や値をローカル変数として定義し、同じモジュール内で何度も参照可能にします。

locals {
  common_tags = {
    Environment = "production"
    Project     = "MyWebApp"
  }
  instance_name = "${local.common_tags.Project}-${local.common_tags.Environment}-server"
}

module ブロック

他のTerraform設定(モジュール)を呼び出して利用します。これで共通のインフラ構成を再利用可能な部品として管理できるようになります。
モジュールもサイト上に公開されています。
https://registry.terraform.io/browse/modules

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.21.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"
  // ... その他の入力変数 ...
}

moduleブロックの名前は自分で決めることができるので、わかりやすい名前をつけたほうが良いでしょう。

Discussion