0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform入門:はじめてのIaCで押さえておきたい10のポイント

0
Posted at

はじめに

クラウドインフラを構築するとき、コンソールをポチポチ操作していくのは再現性がなく、レビューもしづらく、後から「なぜこの設定にしたのか」が分からなくなりがちです。Terraform はインフラを宣言的なコードとして管理できる Infrastructure as Code(IaC)ツールで、AWS / Google Cloud / Azure をはじめとする数百のプロバイダに対応しています。

本記事では、Terraform を業務で使い始める前に知っておくと迷子にならない、基礎知識と実践的なTipsをまとめました。「なんとなく terraform apply は打てるけど、State って何?」というあたりの疑問を解消できる内容にしています。

対象読者

  • クラウドの基本操作はできるが、IaC ツールはこれから触る方
  • Terraform を雰囲気で使っているが、概念を整理したい方
  • チームで Terraform を導入しようとしている方

動作環境

項目 バージョン
Terraform 1.9 系
対象プロバイダ例 AWS Provider 5.x

TL;DR

  • Terraform は「あるべき状態」を HCL で宣言し、差分を計算して適用するツール
  • initplanapply の3コマンドが基本ワークフロー
  • State ファイル(terraform.tfstate)が要。ローカル管理ではなくリモートバックエンドに置く
  • 変数は variable で宣言し、terraform.tfvars や環境変数で値を渡す
  • 同じ構成を再利用するなら Module にまとめる
  • 環境分離は workspace よりもディレクトリ分割が無難
  • terraform fmtterraform validate は CI に組み込む
  • .terraform.lock.hcl は Git で管理する
  • State にはシークレットが平文で入る。State 自体を機密情報として扱う
  • 既存リソースは import ブロックで Terraform 管理下に取り込める

Tip 1: Terraform の基本ワークフローを理解する

Terraform の操作はざっくり以下の流れで進みます。

コマンド 役割
terraform init プロバイダのダウンロードとバックエンド初期化
terraform plan 現状とコードの差分を計算(実環境は変更しない
terraform apply plan で出た差分を実環境に適用
terraform destroy コードで管理している全リソースを削除

terraform apply は対話プロンプトで yes を求められますが、CI などでは -auto-approve を付けます。本番環境ではこのフラグを安易に使わず、必ず plan の結果をレビューしてから適用しましょう。


Tip 2: Provider と Resource の最小構成

Terraform のコードは .tf ファイルに HCL(HashiCorp Configuration Language)で書きます。最小構成は次のとおりです。

main.tf
terraform {
  required_version = ">= 1.9.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_s3_bucket" "example" {
  bucket = "my-terraform-example-bucket-20260501"
}
  • terraform ブロック: Terraform 本体・プロバイダのバージョン制約
  • provider ブロック: プロバイダの設定(リージョンや認証情報)
  • resource ブロック: 作成・管理するリソース

resource "aws_s3_bucket" "example" の最後の exampleTerraform 内部で参照するための名前で、AWS 側のバケット名とは別物です。


Tip 3: 変数は variable で宣言してから使う

ハードコードした値はすぐに散らかります。variable ブロックで宣言し、利用側で var.変数名 として参照します。

variables.tf
variable "region" {
  type        = string
  description = "AWS リージョン"
  default     = "ap-northeast-1"
}

variable "environment" {
  type        = string
  description = "環境名 (dev / stg / prd)"
  validation {
    condition     = contains(["dev", "stg", "prd"], var.environment)
    error_message = "environment は dev / stg / prd のいずれかにしてください。"
  }
}

値の渡し方は複数あり、優先順位が決まっています。

渡し方 優先度
コマンドラインフラグ -var "environment=dev"
*.auto.tfvars ファイル terraform.tfvars
環境変数 TF_VAR_environment=dev
default default = "dev" 最低

シークレットを tfvars に書いて Git にコミットしないこと。環境変数(TF_VAR_*)か、AWS Secrets Manager / Parameter Store などからの取得を推奨します。


Tip 4: State ファイルが Terraform の心臓部

Terraform は「コード」と「実環境」を直接比較しているわけではありません。State ファイル(terraform.tfstate)に記録されたリソースの状態 を介して差分を計算しています。

このため、State が壊れたり、複数人で別々の State を持ったりすると整合性が崩れます。

State 管理のポイント

  • ローカルの terraform.tfstate は本番運用に使わない
  • リモートバックエンド(S3 + DynamoDB ロック、Terraform Cloud など)に置く
  • バージョニングを有効にして、誤操作からのロールバックに備える
backend.tf
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prd/network.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "terraform-state-lock"
    encrypt        = true
  }
}

State ファイルにはリソースの全属性が平文で含まれます。RDS のパスワードや API キーなどシークレットも生の値が入ることがあるため、State 自体を機密情報として扱い、アクセス権限を厳格に絞ってください。


Tip 5: 同じ構成は Module にまとめる

「VPC + サブネット + ルートテーブル」のような繰り返し使う構成は Module にまとめると見通しが良くなります。

modules/network/main.tf
variable "cidr_block" {
  type = string
}

resource "aws_vpc" "this" {
  cidr_block = var.cidr_block
}

output "vpc_id" {
  value = aws_vpc.this.id
}

呼び出し側はこう書きます。

envs/dev/main.tf
module "network" {
  source     = "../../modules/network"
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "app" {
  vpc_id     = module.network.vpc_id
  cidr_block = "10.0.1.0/24"
}

最初から無理に Module 化する必要はありません。2回以上同じ構成を書きそうになったら切り出すくらいの温度感が、過剰な抽象化を避けられて良いです。


Tip 6: 環境分離は workspace よりディレクトリ分割

terraform workspace は同じコードで複数の State を持てる機能ですが、環境(dev/stg/prd)の分離には不向きです。

観点 workspace ディレクトリ分割
環境ごとの設定差分 表現しづらい 自然に書ける
State の保存先 同じバックエンド 環境ごとに分けられる
誤適用のリスク 高(workspace の切り替え忘れ)
コードレビューしやすさ

推奨ディレクトリ構成

.
├── modules/
│   ├── network/
│   └── compute/
└── envs/
    ├── dev/
    │   ├── main.tf
    │   └── backend.tf
    ├── stg/
    └── prd/

workspace は「短期的な検証用 State を増やしたい」「機能ブランチごとに環境を立てたい」といった用途に絞るのが安全です。


Tip 7: 既存リソースは import ブロックで取り込む

コンソールで作ってしまった既存リソースも Terraform 管理下に取り込めます。Terraform 1.5 以降は import ブロック が使えて、コードでインポートを宣言できます。

import.tf
import {
  to = aws_s3_bucket.legacy
  id = "existing-bucket-name"
}

resource "aws_s3_bucket" "legacy" {
  bucket = "existing-bucket-name"
}

terraform plan -generate-config-out=generated.tf を使うと、既存リソースの設定を .tf として書き出してくれます。

インポート後の最初の plan で大量の差分が出ることがよくあります。慌てて apply せず、差分が「コードの不足」なのか「実環境の意図しない設定」なのかを確認してから進めましょう。


Tip 8: data ブロックで既存リソースを参照する

「他チームが管理している VPC の ID を取得したい」など、Terraform 管理外のリソースを読み取り専用で参照したいときは data ブロックを使います。

data.tf
data "aws_vpc" "shared" {
  tags = {
    Name = "shared-vpc"
  }
}

resource "aws_subnet" "app" {
  vpc_id     = data.aws_vpc.shared.id
  cidr_block = "10.0.10.0/24"
}

resource は「作成・管理する」、data は「読み取るだけ」と覚えておくと混乱しません。


Tip 9: fmtvalidate を CI に組み込む

Terraform には標準でフォーマッタと構文チェッカが付属しています。

terraform fmt -recursive
terraform validate

CI では次のように差分検出までやると、プルリクで「なぜか動かない」を防げます。

.github/workflows/terraform.yml
name: Terraform CI

on: [pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.9.0
      - run: terraform fmt -check -recursive
      - run: terraform init -backend=false
      - run: terraform validate

加えて、セキュリティチェックには tfsec や Checkov を入れておくと、典型的な設定ミス(公開バケット、暗号化忘れなど)を早期に検出できます。


Tip 10: .terraform.lock.hcl を Git で管理する

terraform init 実行時に生成される .terraform.lock.hcl は、プロバイダのバージョンとハッシュを固定するファイルです。

  • node_modules における package-lock.json のような立ち位置
  • 必ず Git にコミットする
  • プロバイダのバージョンを上げたいときは terraform init -upgrade で更新
  .terraform/
- .terraform.lock.hcl
  *.tfstate
  *.tfstate.backup

.gitignore でコミット対象から外すと、開発者ごとにプロバイダのバージョンが変わってしまい再現性が崩れます。

逆に、.terraform/ ディレクトリ(プロバイダのバイナリが入る場所)と *.tfstateGit にコミットしない のが鉄則です。


まとめ

本記事では、Terraform を本格的に使い始める前に押さえておきたい10個のポイントを紹介しました。

特に重要なのは:

  • State ファイルの取り扱い: リモートバックエンド + ロック + 機密情報として保護
  • 環境分離は workspace ではなくディレクトリ分割
  • .terraform.lock.hcl のコミット で再現性を担保

Terraform は「宣言的に書ける」というシンプルな魅力の裏に、State 管理という独特の概念があります。最初にここを理解しておけば、複雑な構成にスケールしても破綻しにくくなります。

次のステップとしては、実際に小さなリソース(S3 バケットや Lambda 関数など)を Terraform で作って壊してみるのがおすすめです。手を動かすほど plan の差分の読み方が分かるようになります。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?