目次
Terraformのセットアップ
前回のパート1では、Infrastructure as Codeの重要性とTerraformが業界標準になった理由を解説しました。今回は、実際に手を動かしてインストールから始めていきます。
この記事を読み終えるころには、あなたのマシン上でTerraformが動作し、クラウドの認証情報も正しく設定され、はじめてのプロジェクトの初期化まで完了しているはずです。理論の話は終わり。さあ、実際に構築していきましょう。
📦 コード例
このチュートリアルシリーズで使用するコード例は、すべてGitHubリポジトリで公開しています:
リポジトリ: terraform-hcl-tutorial-series 今回のパート: Part 2 - Provider Setup Examples
実際に試してみるには、以下のコマンドを実行してください:
git clone https://github.com/khuongdo/terraform-hcl-tutorial-series.git
cd terraform-hcl-tutorial-series
git checkout part-02
# AWSの例を試す
cd examples/part-02-setup/aws/
terraform init
terraform plan
# またはGCPの例を試す
cd ../gcp/
terraform init
terraform plan
# またはAzureの例を試す
cd ../azure/
terraform init
terraform plan
各サンプルは、実際のリソースを作成せずにプロバイダー設定の検証だけを行うので、料金は一切かかりません。
なぜセットアップが重要なのか
「早く実際のインフラをデプロイしたい!」という気持ちはよくわかります。でも、ここで20分かけて正しくセットアップしておけば、のちのち何時間ものデバッグ作業を回避できます。
セットアップを適当にやると、こんなトラブルに見舞われます:
プロジェクトAはTerraform 1.4が必要なのに、プロジェクトBは1.7を要求してバージョン競合が発生。設定ファイルに認証情報をベタ書きして、セキュリティ監査で一発アウト。認証エラーで午後まるまる潰して調査した結果、原因は単なるPATHの設定ミス。チームメンバーの環境設定が違うせいで、あなたのコードが動かない。
最初に基盤をしっかり作っておけば、再現可能な環境、安全な認証情報管理、プロジェクトごとのバージョン分離、明確な監査証跡が手に入ります。単に「Terraformを動かす」だけでなく、「今後3年間、確実に動き続ける」ことが目標です。
Terraformのインストール
朗報です。Terraformは単一のバイナリファイルで動作します。ランタイムも依存関係も複雑なセットアップも一切不要。ダウンロードしてPATHに配置するだけ。以上です。
macOS
macOSをお使いなら、Homebrewでインストールするのが一番簡単です。
# Terraformをインストール
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
# 動作確認
terraform version
# 期待される出力: Terraform v1.9.0 (またはそれ以降のバージョン)
なぜHomebrewを使うのか?アップデートが brew upgrade terraform 一発で終わるからです。シンプルですね。
もしHomebrewを使いたくない場合は、手動でインストールすることもできます:
# https://releases.hashicorp.com/terraform/ から最新版をダウンロード
wget https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_darwin_amd64.zip
# 解凍してPATHに移動
unzip terraform_1.9.0_darwin_amd64.zip
sudo mv terraform /usr/local/bin/
# 確認
terraform version
Linux
UbuntuまたはDebianをお使いの場合は、HashiCorpの公式リポジトリを追加してインストールします:
# GPGキーとリポジトリを追加
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
# インストール
sudo apt update && sudo apt install terraform
# 確認
terraform version
手動でインストールする場合は、以下のようにします:
wget https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_linux_amd64.zip
unzip terraform_1.9.0_linux_amd64.zip
sudo mv terraform /usr/local/bin/
terraform version
Windows
Chocolateyを使用している場合:
choco install terraform
terraform version
それ以外の場合は、HashiCorpのリリースページからZIPをダウンロードし、C:\Program Files\Terraform\に解凍し、そのディレクトリをシステムのPATHに追加します。
PATHに追加するには: スタートメニューで「環境変数」を検索 → システムのプロパティを開く → 環境変数をクリック → Path変数を編集 → Terraformディレクトリを追加 → 保存してターミナルを再起動します。
再起動後、動作確認をします:
terraform version
動作確認
インストールが完了したら、以下を実行してバージョンを確認します:
terraform version
バージョン1.7.0以降が表示されればOKです。タブ補完機能を有効にすると作業効率が上がるので、設定しておきましょう:
terraform -install-autocomplete
設定後は、シェルをリロードするか新しいターミナルウィンドウを開いてください。これでTerraformコマンドがタブ補完できるようになります。
トラブルシューティング:
terraform versionが失敗する場合、PATHの設定を確認してください- macOS/Linuxでは
which terraformでインストール場所を確認できます - Windowsでは、PATH変更後に必ずターミナルを再起動してください
- Linuxで「permission denied」エラーが出る場合は
chmod +x /usr/local/bin/terraformを実行します
クラウド認証の仕組み
Terraformがクラウド上にリソースを作成するには、適切な権限が必要です。各クラウドプロバイダーで認証方法は異なりますが、基本原則は共通です。ローカル環境で認証を設定し、Terraformがその認証情報を自動的に利用する仕組みです。
絶対にやってはいけないこと:
# ❌ これはやらないでください
provider "aws" {
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
なぜこれがダメなのか?
この認証情報をGitにコミットすると、履歴に永久に残ります。後のコミットで削除しても、Git履歴からは消えません。さらに、Terraformのステートファイルやプラン出力にも含まれてしまいます。もし公開リポジトリに誤ってプッシュしてしまったら、見知らぬ誰かの暗号通貨マイニングの電気代を負担することになるかもしれません。
正しい方法は、クラウドプロバイダーの公式CLIツールを使って認証することです。Terraformは環境変数や設定ファイルから認証情報を自動的に読み取ります。この方が安全で、管理もしやすくなります。
AWSのセットアップ
AWSには主に3つの認証方法があります。基本的にこの順番で検討するのがおすすめです。
方法1: AWS CLI (まずはこれから)
AWS CLIをまだインストールしていない場合は、以下の手順でインストールしましょう:
# macOS
brew install awscli
# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Windows: https://aws.amazon.com/cli/ からMSIインストーラーをダウンロード
インストールできたら、認証情報を設定します:
aws configure
以下の4つの項目を順番に入力していきます:
- AWS Access Key ID - AWSコンソールの「Security Credentials」→「Access Keys」から取得
- AWS Secret Access Key - キー作成時に一度だけ表示されます(今コピーしないと二度と見られません!)
- Default region - 例:
us-west-2やap-northeast-1など - Output format -
jsonと入力しておけばOKです
設定が完了したら、動作確認をしてみましょう:
aws sts get-caller-identity
あなたのAWSアカウントIDとユーザーARNが表示されればOKです。これでTerraformは自動的にこの認証情報を使えるようになります。
方法2: 環境変数 (CI/CD向け)
CI/CDパイプラインでTerraformを実行する場合は、環境変数で認証情報を渡すことができます:
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="us-west-2"
GitHub ActionsやGitLab CIなどのCI/CDツールでは、通常この方法で認証情報を渡します。
方法3: IAMロール (本番環境推奨)
EC2インスタンスやAWS CodeBuild上でTerraformを実行する場合は、アクセスキーではなくIAMロールを使いましょう。長期的な認証情報を持たず、自動的にローテーションされ、必要な権限だけを細かく設定できるため、セキュリティ面で優れています。
Terraformは自動的にIAMロールを検出して使用します:
provider "aws" {
region = "us-west-2"
# 認証情報ブロックは不要 - インスタンスメタデータから自動取得
}
これが本番環境におけるゴールドスタンダードです。キーの漏洩リスクがゼロになります。
GCPのセットアップ
Google Cloudでは、gcloud CLIを使ってApplication Default Credentials(ADC)で認証します。
gcloudのインストール
# macOS
brew install --cask google-cloud-sdk
# Linux (Debian/Ubuntu)
sudo apt-get install apt-transport-https ca-certificates gnupg
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get update && sudo apt-get install google-cloud-sdk
# Windows: https://cloud.google.com/sdk/docs/install からダウンロード
認証
gcloud init
gcloud config set project YOUR_PROJECT_ID
gcloud auth application-default login
最後のコマンドを実行すると、ブラウザが開いてOAuth認証が始まります。認証が完了すると、認証情報が~/.config/gcloud/application_default_credentials.jsonに保存されます。Terraformはこのファイルを自動的に読み取って使用します。
動作確認をしてみましょう:
gcloud projects list
あなたのGCPプロジェクト一覧が表示されればOKです。
サービスアカウントキー (CI/CD専用)
ローカル開発では前述のApplication Default Credentialsを使いましょう。ただし、CI/CD環境でサービスアカウントキーが必要な場合は、以下のようにします:
gcloud iam service-accounts create terraform-sa --display-name "Terraform Service Account"
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:terraform-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/editor"
gcloud iam service-accounts keys create ~/terraform-key.json \
--iam-account=terraform-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
export GOOGLE_APPLICATION_CREDENTIALS="$HOME/terraform-key.json"
重要な注意点: サービスアカウントキーは長期的な認証情報です。このJSONファイルを誰かに取得されると、あなたのGCPプロジェクトへのフルアクセスを許してしまいます。パスワードと同じくらい慎重に扱い、絶対にGitにコミットしないでください。本当に必要な場合のみ使用しましょう。
Azureのセットアップ
Azureでは、Azure CLIを使って認証を行います。
Azure CLIのインストール
# macOS
brew install azure-cli
# Linux (Ubuntu/Debian)
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# Windows: https://aka.ms/installazurecliwindows からダウンロード
ログイン
az login
このコマンドを実行するとブラウザが開きます。そこでログインすると、CLIが認証情報を自動的に保存してくれます。
複数のサブスクリプションを持っている場合は、使用するものを選択します:
az account list --output table
az account set --subscription "YOUR_SUBSCRIPTION_ID"
現在アクティブなサブスクリプションを確認するには:
az account show
サブスクリプションIDとメールアドレスが表示されればOKです。
サービスプリンシパル (CI/CD向け)
CI/CDパイプラインで使う場合は、サービスプリンシパルを作成します:
az ad sp create-for-rbac --name "terraform-sp" --role Contributor
このコマンドを実行すると、appId、password、tenant IDが出力されます。これらを安全な場所に保存し、環境変数として設定してください:
export ARM_CLIENT_ID="出力されたappId"
export ARM_CLIENT_SECRET="出力されたpassword"
export ARM_SUBSCRIPTION_ID="あなたのサブスクリプションID"
export ARM_TENANT_ID="出力されたtenant"
プロバイダーとは何か
認証の設定が終わったので、次はプロバイダーについて理解しましょう。
プロバイダーは、Terraformの設定をクラウドプロバイダーのAPI呼び出しに変換するプラグインです。たとえばresource "aws_s3_bucket"と書くと、AWSプロバイダーがそれをAWS SDKの呼び出しに変換します。GCPやAzureでも同じ仕組みです。
イメージとしては、データベースドライバーに似ています。PostgreSQLと直接やり取りするのではなく、プロトコルを理解するドライバーを経由しますよね。プロバイダーもクラウドAPIに対して同じ役割を果たします。
プロバイダーの設定は以下のようになります:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
それぞれの要素を見ていきましょう。
terraformブロックでは、必要なプロバイダーを宣言します。sourceはダウンロード元を指定しており、hashicorp/awsはregistry.terraform.io/hashicorp/awsに解決されます。version制約では、バージョン5.x系を使用しますが、6.0にはアップグレードしないように指定しています。
なぜバージョン制約が重要なのでしょうか?半年後にAWSプロバイダー8.0が破壊的変更を含んでリリースされるかもしれないからです。バージョン制約がないと、意図せずコードが動かなくなるリスクがあります。~> 5.0を使えば、明示的にアップグレードするまで5.x系に留まります。
バージョン制約の書き方:
~> 5.0→ 「5.x系の任意のバージョン、ただし6.0以降は除く」(推奨)= 5.31.0→ 「このバージョンのみ」(厳しすぎる場合が多い)>= 5.0, < 6.0→ 「範囲を明示的に指定」(これも良い選択肢)
providerブロックでは、プロバイダーの具体的な設定を行います。AWSの場合、通常はリージョンだけ指定すればOKです。認証情報は環境(AWS CLI、環境変数、IAMロール)から自動的に取得されるため、ここで記述する必要はありません。
ひとつのプロジェクトで複数のプロバイダーを同時に使うこともできます:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
provider "google" {
project = "my-gcp-project"
region = "us-central1"
}
こうすることで、同じTerraformコードからAWSとGCPの両方にリソースを作成できるようになります。
はじめてのTerraformプロジェクト
それでは、実際にプロジェクトを初期化していきましょう。
プロジェクト構造
まず、作業用のディレクトリを作成します:
mkdir ~/terraform-getting-started
cd ~/terraform-getting-started
推奨するファイル構成は以下の通りです:
terraform-getting-started/
├── main.tf # リソース定義
├── variables.tf # 入力変数の定義
├── outputs.tf # 出力値の定義
└── terraform.tfvars # 変数の値 (シークレット情報はコミットしないこと!)
今すぐすべて揃える必要はありませんが、最終的にはこの構造を目指していきます。
はじめての設定ファイルを書く (AWS)
main.tfを作成しましょう:
terraform {
required_version = ">= 1.7.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
resource "aws_s3_bucket" "learning_bucket" {
bucket = "terraform-learning-${var.environment}-${random_id.bucket_suffix.hex}"
tags = {
Name = "Terraform Learning Bucket"
Environment = var.environment
ManagedBy = "Terraform"
}
}
resource "random_id" "bucket_suffix" {
byte_length = 4
}
variables.tfを作成:
variable "aws_region" {
description = "AWS region for resources"
type = string
default = "us-west-2"
}
variable "environment" {
description = "Environment name (dev, staging, prod)"
type = string
default = "dev"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
outputs.tfを作成:
output "bucket_name" {
description = "Name of the created S3 bucket"
value = aws_s3_bucket.learning_bucket.id
}
output "bucket_arn" {
description = "ARN of the S3 bucket"
value = aws_s3_bucket.learning_bucket.arn
}
GCPを使う場合
Google Cloudをお使いの方は、main.tfを以下のように書き換えてください:
terraform {
required_version = ">= 1.7.0"
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "google" {
project = var.gcp_project_id
region = var.gcp_region
}
resource "google_storage_bucket" "learning_bucket" {
name = "terraform-learning-${var.environment}-${random_id.bucket_suffix.hex}"
location = var.gcp_region
labels = {
environment = var.environment
managed_by = "terraform"
}
}
resource "random_id" "bucket_suffix" {
byte_length = 4
}
それに合わせてvariables.tfも更新します:
variable "gcp_project_id" {
description = "GCP project ID"
type = string
}
variable "gcp_region" {
description = "GCP region for resources"
type = string
default = "us-central1"
}
variable "environment" {
description = "Environment name"
type = string
default = "dev"
}
Azureを使う場合
Azureの場合は以下のようになります:
terraform {
required_version = ">= 1.7.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "learning" {
name = "rg-terraform-learning-${var.environment}"
location = var.azure_region
}
resource "azurerm_storage_account" "learning" {
name = "tflearn${var.environment}${random_id.suffix.hex}"
resource_group_name = azurerm_resource_group.learning.name
location = azurerm_resource_group.learning.location
account_tier = "Standard"
account_replication_type = "LRS"
tags = {
environment = var.environment
managed_by = "terraform"
}
}
resource "random_id" "suffix" {
byte_length = 4
}
variables.tfも合わせて作成します:
variable "azure_region" {
description = "Azure region for resources"
type = string
default = "East US"
}
variable "environment" {
description = "Environment name"
type = string
default = "dev"
}
terraform initを実行する
いよいよ本番です。以下のコマンドを実行しましょう。
terraform init
このコマンドは、以下の4つの処理を実行します:
- 指定したプロバイダープラグイン(AWS、GCP、またはAzure)のダウンロード
- バックエンドの初期化(デフォルトはローカル、本番ではリモートを使用)
- プロバイダーバイナリを格納する
.terraform/ディレクトリの作成 - プロバイダーバージョンを固定する
.terraform.lock.hclの生成
実行すると、以下のような出力が表示されます:
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.31.0...
- Installed hashicorp/aws v5.31.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform has been successfully initialized!
作成されたファイルを確認してみましょう:
ls -la
以下のファイルやディレクトリが見えるはずです:
.terraform/- プロバイダーバイナリが入っています(Gitにコミットしないこと).terraform.lock.hcl- バージョンロックファイル(これはコミットすること)main.tf、variables.tf、outputs.tf- あなたが作成した設定ファイル
ロックファイルについて
.terraform.lock.hclを開いてみると、以下のような内容になっています:
provider "registry.terraform.io/hashicorp/aws" {
version = "5.31.0"
constraints = "~> 5.0"
hashes = [
"h1:...",
"zh:...",
]
}
このファイルは、プロバイダーの正確なバージョンを固定します。~> 5.0と指定していても、Terraformはバージョン5.31.0を選択し、ここに記録しました。次回あなたやチームメンバーがterraform initを実行すると、同じバージョンが使われます。
ハッシュは、プロバイダーの整合性を検証するためのものです。つまり、Terraformはダウンロードしたプロバイダーが改ざんされていないことを確認しています。
このファイルをコミットすべきか? はい、必ずGitに追加してください。チーム全員が同じプロバイダーバージョンを使えるようになります。
初期化エラーのトラブルシューティング
「Failed to query available provider packages」が出る場合: インターネット接続を確認してください。Terraformはregistry.terraform.ioからプロバイダーをダウンロードします。
「Required version constraint not satisfied」が表示される場合: Terraformのバージョンが古すぎます。terraform versionで確認し、HomebrewでアップグレードするかHashiCorpから最新版をダウンロードしてください。
「Error configuring the backend」が出る場合: main.tfの構文を確認してください。terraform validateを実行すると構文エラーを検出できます。
Gitで管理すべきファイル
プロジェクトルートに.gitignoreを作成しましょう:
# ローカルの.terraformディレクトリ
**/.terraform/*
# ステートファイル (リソースIDを含み、時々シークレットも含む)
*.tfstate
*.tfstate.*
# クラッシュログ
crash.log
crash.*.log
# シークレットを含む変数ファイル
*.tfvars
!example.tfvars
# CLI設定 (認証情報を含む可能性がある)
.terraformrc
terraform.rc
# オーバーライドファイル
override.tf
override.tf.json
*_override.tf
*_override.tf.json
コミットすべきファイル:
*.tfファイル - すべてのTerraformコード.terraform.lock.hcl- プロバイダーバージョンの固定README.md- ドキュメントexample.tfvars- 実際の値を含まないテンプレート
絶対にコミットしてはいけないもの:
*.tfstate- リソースIDが含まれ、シークレット情報が入っている可能性あり.terraform/- プロバイダーバイナリ(再ダウンロード可能)terraform.tfvars- 認証情報やAPIキーが含まれる場合
理解度チェック
パート3に進む前に、以下の質問に答えられるか確認してみましょう:
1. AWSの3つの認証方法は? → AWS CLI認証情報、環境変数、IAMロール
2. terraform initは何をする? → プロバイダーのダウンロード、バックエンドの初期化、.terraform/ディレクトリの作成、ロックファイルの生成
3. なぜ~> 5.0のようなバージョン制約を使うのか? → マイナーアップデートは許可しつつ、意図しない破壊的変更を含むメジャーアップグレードを防ぐため
4. .terraform.lock.hclはコミットすべきか? → はい。チーム全員が同じプロバイダーバージョンを使うことを保証するため
5. なぜプロバイダーブロックに認証情報をハードコードしてはいけないのか? → Git履歴、Terraformステート、プラン出力に残ってしまうため。CLIツールまたは環境変数を使うべき
これらに答えられたら、パート3に進む準備は万全です!
次のステップ
パート3では、実際にリソースをデプロイしていきます。terraform planで変更内容をプレビューし、terraform applyで実際のクラウドリソースを作成し、terraform destroyでクリーンアップする手順を学びます。
ここからTerraformが抽象的な概念から具体的なツールに変わります。AWS、GCP、またはAzure上で本物のインフラを構築し、Terraformがどのように状態を管理するのかを体験し、既存のリソースを安全に変更する方法を習得します。
準備はできましたか?パート3へ進む → (近日公開予定)
リソース
公式ドキュメント:
認証ガイド:
連載ナビゲーション:
- 第1回: Infrastructure as Codeとは?
- 第2回: Terraformのセットアップ (今ここ)
- 第3回: 初めてのクラウドリソース
- 第4回: HCL基礎
- 第5回: Variables, Outputs & State
- 第6回: Terraformの基本ワークフロー
- 第7回: モジュールで整理する (近日公開)
- 第8回: マルチクラウドパターン (近日公開)
- 第9回: State管理 & チームワークフロー (近日公開)
- 第10回: テスト & 検証 (近日公開)
- 第11回: セキュリティ & シークレット管理 (近日公開)
- 第12回: 本番環境パターン & DevSecOps (近日公開)
質問や感想があればコメント欄でお気軽にどうぞ。すべてのコメントに目を通し、今後の記事に反映していきます。
このシリーズ「Terraform from Fundamentals to Production」では、Infrastructure as Codeを基礎から実践まで学べます。