はじめに
Terraformは、HashiCorpが開発したInfrastructure as Code(IaC)ツールです
HCL(HashiCorp Configuration Language)でインフラ構成をコードとして定義し、コマンド一つでAWSリソースの作成・変更・削除ができます
AWSにはIaCツールとして純正のCloudFormationがありますが、Terraformにはマルチクラウド対応や、HCLによる簡潔な記述、豊富なコミュニティモジュールといった強みがあります
一方、CloudFormationはAWSネイティブのためAWSサポートを受けられる点や、スタックの自動ロールバック機能が魅力です
両者の詳しい比較は記事末尾の比較表にまとめています
この記事では、Terraformのインストールから認証設定、実践的な使い方まで、実際のコマンド例を交えて解説します
この記事でわかること
- Terraformのインストール方法(Windows/Linux/Mac)
- AWS認証の設定方法
- Terraformの基本コマンド(init / plan / apply / destroy)
- VPCの作成
- セキュリティグループの作成
- EC2インスタンスの作成とSSH接続
- tfstateファイルの管理
- 変数とoutputの活用
前提条件
- AWSアカウントを持っている
- AWS CLIがインストール・設定済み(
aws configure完了済み) - 基本的なコマンドライン操作ができる
AWS CLIの設定がまだの方は以下の記事を参考にしてください
AWS CLIのインストールから実践的な使い方まで徹底解説
手順1: Terraformのインストール
Windows
手動インストール
- Terraform公式ダウンロードページからWindows用ZIPをダウンロード
- ZIPを展開し、
terraform.exeを任意のフォルダに配置(例:C:\terraform) - 環境変数のPathに配置先フォルダを追加
Chocolateyを使う場合
choco install terraform
Linux
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
HashiCorpのGPGキーを追加:
wget -O- https://apt.releases.hashicorp.com/gpg | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg > /dev/null
リポジトリを追加:
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-get update && sudo apt-get install terraform
Mac
Homebrewを使用:
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
インストール確認(全OS共通)
terraform version
出力例(Windows):
ヘルプの表示:
terraform -help
手順2: AWS認証の設定
TerraformがAWSリソースを操作するには、AWS認証情報が必要です
方法1: AWS CLIの設定を利用(推奨)
AWS CLIで aws configure を実行済みであれば、Terraformは自動的に ~/.aws/credentials を参照します
aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: ap-northeast-1
Default output format [None]: json
方法2: 環境変数を使用
Windows(PowerShell):
$env:AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
$env:AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
$env:AWS_DEFAULT_REGION="ap-northeast-1"
Mac/Linux:
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="ap-northeast-1"
方法3: AWS CLIのプロファイルを指定
provider "aws" {
region = "ap-northeast-1"
profile = "Administrator"
}
複数のAWSアカウントを使い分ける場合に便利です
認証の確認
設定が正しいか確認するには、以下のコマンドを実行します
aws sts get-caller-identity
出力例:
{
"UserId": "AIDAIOSFODNN7EXAMPLE",
"Account": "123456789012",
"Arn": "arn:aws:iam::123456789012:user/terraform-user"
}
手順3: Terraformの基本構成
Terraformはディレクトリ単位でリソースを管理するため、専用のフォルダを作成し、役割ごとにファイルを分割します
main.tfにインフラの定義、variables.tfに設定値の変数、outputs.tfに作成後の出力情報を定義します
プロジェクトディレクトリの作成
mkdir terraform-ec2-demo
Windows(PowerShell):
New-Item -ItemType Directory -Path terraform-ec2-demo
ファイル構成
Terraformプロジェクトの基本的なファイル構成は以下の通りです
terraform-ec2-demo/
├── main.tf # メインのリソース定義
├── variables.tf # 変数定義
├── outputs.tf # 出力定義
├── terraform.tfvars # 変数の値(Git管理外にすることも可能)
└── .gitignore # Git管理外ファイルの指定
.gitignoreの作成
Terraformプロジェクトでは以下のファイルをGit管理外にします
# Terraform
.terraform/
*.tfstate
*.tfstate.backup
*.tfvars
.terraform.lock.hcl
手順4: VPCとサブネットの作成
AWS のネットワーク基盤(VPC 環境)を Terraform で作成します
VPC、パブリックサブネット、Internet Gateway、ルートテーブルを定義し、インターネットに接続可能なネットワークを構築します
これにより、後で作成する EC2 インスタンスがインターネット通信できる環境を準備しています
main.tfの作成
# プロバイダーの設定
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
# VPCの作成
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.project_name}-vpc"
}
}
# パブリックサブネットの作成
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "${var.aws_region}a"
map_public_ip_on_launch = true
tags = {
Name = "${var.project_name}-public-subnet"
}
}
# Internet Gatewayの作成
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.project_name}-igw"
}
}
# ルートテーブルの作成
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${var.project_name}-public-rt"
}
}
# ルートテーブルとサブネットの関連付け
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
variables.tfの作成
variable "aws_region" {
description = "AWSリージョン"
type = string
default = "ap-northeast-1"
}
variable "project_name" {
description = "プロジェクト名(リソースのタグに使用)"
type = string
default = "terraform-demo"
}
variable "key_name" {
description = "EC2キーペア名"
type = string
default = "test-ec2-key"
}
variable "my_ip" {
description = "SSH接続を許可するIPアドレス(CIDR形式)"
type = string
default = "0.0.0.0/0"
}
outputs.tfの作成
output "vpc_id" {
description = "作成したVPCのID"
value = aws_vpc.main.id
}
output "subnet_id" {
description = "作成したサブネットのID"
value = aws_subnet.public.id
}
手順5: Terraformの基本コマンド
Terraform の基本コマンドを使い、インフラの作成と状態管理を行います
terraform init:Terraform プロジェクトを初期化し、プロバイダー(AWS)をダウンロード
terraform plan:どのリソースが作成・変更・削除されるかを事前確認
terraform apply:実際に AWS にリソースを作成
terraform show:現在 Terraform が管理しているリソースの状態を確認
terraform output:設定した出力値(VPC ID やサブネット ID など)を表示
この手順では Terraform の基本的な操作フロー(init → plan → apply) を学びます。
terraform init(初期化)
プロジェクトディレクトリで最初に実行するコマンドです
terraform init
出力例:
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.80.0...
- Installed hashicorp/aws v5.80.0 (signed by HashiCorp)
Terraform has been successfully initialized!
このコマンドで以下が実行されます:
-
.terraformディレクトリの作成 - プロバイダープラグイン(AWS)のダウンロード
-
.terraform.lock.hcl(依存関係ロックファイル)の作成
terraform plan(実行計画の確認)
実際にリソースを作成する前に、何が作成されるか確認できます
terraform plan
出力例:
Terraform will perform the following actions:
# aws_internet_gateway.main will be created
+ resource "aws_internet_gateway" "main" {
+ id = (known after apply)
+ vpc_id = (known after apply)
+ tags = {
+ "Name" = "terraform-demo-igw"
}
}
# aws_vpc.main will be created
+ resource "aws_vpc" "main" {
+ cidr_block = "10.0.0.0/16"
+ enable_dns_hostnames = true
+ enable_dns_support = true
+ id = (known after apply)
+ tags = {
+ "Name" = "terraform-demo-vpc"
}
}
Plan: 5 to add, 0 to change, 0 to destroy.
+ は新規作成、~ は変更、- は削除を意味します
terraform apply(リソースの作成)
terraform apply
確認プロンプトが表示されます:
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
yes を入力するとリソースが作成されます
確認をスキップする場合:
terraform apply -auto-approve
terraform show(現在の状態確認)
terraform show
作成済みリソースの詳細情報が表示されます
terraform output(出力値の確認)
terraform output
出力例:
vpc_id = "vpc-0a1b2c3d4e5f6g7h8"
subnet_id = "subnet-0a1b2c3d4e5f6g7h8"
特定の値のみ取得:
terraform output vpc_id
手順6: セキュリティグループとEC2インスタンスの追加
ネットワーク内にサーバーを配置し、必要な通信を許可するための設定を行います
ここでは、EC2インスタンスとセキュリティグループのリソースを Terraform に追加し、サーバーを起動できる環境を構築します
主な設定内容は以下の通りです
セキュリティグループを作成し、SSH(22)および HTTP(80)の通信を許可します
Amazon Linux 2023 の最新 AMI を取得します
EC2 インスタンスを作成します
さらに、outputs.tf に EC2 のパブリック IP や SSH 接続コマンドを出力する設定を追加します
これにより、Terraform 実行後に表示される情報を使って、すぐに EC2 インスタンスへ接続できるようになります
main.tfにリソースを追加
手順4で作成した main.tf に以下を追記します
# セキュリティグループの作成
resource "aws_security_group" "ec2_sg" {
name = "${var.project_name}-ec2-sg"
description = "Security group for EC2 instance"
vpc_id = aws_vpc.main.id
# SSH接続を許可
ingress {
description = "SSH"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.my_ip]
}
# HTTP接続を許可
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# アウトバウンド通信を全て許可
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.project_name}-ec2-sg"
}
}
# 最新のAmazon Linux 2023 AMIを取得
data "aws_ami" "amazon_linux_2023" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-2023*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# EC2インスタンスの作成
resource "aws_instance" "ec2_server" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
key_name = var.key_name
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.ec2_sg.id]
tags = {
Name = "${var.project_name}-ec2"
}
}
outputs.tfに追記
output "ec2_instance_id" {
description = "EC2インスタンスID"
value = aws_instance.ec2_server.id
}
output "ec2_public_ip" {
description = "EC2パブリックIPアドレス"
value = aws_instance.ec2_server.public_ip
}
output "ec2_ami_id" {
description = "使用したAMI ID"
value = data.aws_ami.amazon_linux_2023.id
}
output "security_group_id" {
description = "セキュリティグループID"
value = aws_security_group.ec2_sg.id
}
output "ssh_command" {
description = "SSH接続コマンド"
value = "ssh -i ${var.key_name}.pem ec2-user@${aws_instance.ec2_server.public_ip}"
}
変更の適用
差分を確認:
terraform plan
出力例:
Plan: 3 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ ec2_ami_id = (known after apply)
+ ec2_instance_id = (known after apply)
+ ec2_public_ip = (known after apply)
+ security_group_id = (known after apply)
+ ssh_command = (known after apply)
適用:
terraform apply
yes を入力して実行します
SSH接続
outputで表示されたコマンドを使ってSSH接続します
terraform output ssh_command
出力例:
"ssh -i test-ec2-key.pem ec2-user@54.250.245.176"
キーペアの権限設定後、接続:
chmod 400 test-ec2-key.pem
ssh -i test-ec2-key.pem ec2-user@54.250.245.176
手順7: tfstateファイルの管理
Terraform がインフラの状態を管理する terraform.tfstate ファイルの仕組みと管理方法
このファイルには、作成したリソースの情報や属性値などが保存されます
チーム開発では S3 バケットに state ファイルを保存し、DynamoDB を利用してロック管理を行う「リモートバックエンド構成」を使用します
これにより、複数人で Terraform を実行する場合でも安全に状態管理を行うことができます
tfstateとは
Terraformは作成したリソースの状態を terraform.tfstate ファイルに記録します
terraform show
このファイルには以下の情報が含まれます:
- 作成したリソースのID
- リソースの属性値
- リソース間の依存関係
tfstateの注意点
-
terraform.tfstateにはアクセスキーなどの機密情報が含まれる場合があります - Gitリポジトリにコミットしないでください
- チーム開発ではS3バックエンドの利用を推奨します
S3バックエンドの設定(チーム開発向け)
S3バケットを事前に作成しておきます:
aws s3 mb s3://my-terraform-state-bucket --region ap-northeast-1
DynamoDBテーブルを作成(ロック機能用):
aws dynamodb create-table \
--table-name terraform-lock \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--region ap-northeast-1
main.tf の terraform ブロックに追記:
terraform {
required_version = ">= 1.0.0"
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "terraform-ec2-demo/terraform.tfstate"
region = "ap-northeast-1"
dynamodb_table = "terraform-lock"
encrypt = true
}
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
バックエンドの変更後は再初期化が必要です:
terraform init -migrate-state
手順8: リソースの変更と削除
Terraform を使用したインフラの変更や削除には、以下の操作があります
terraform plan で変更内容を確認
terraform apply で変更を適用
terraform destroy でリソースを削除
特定のリソースのみを対象に変更・削除することも可能
ここでは、Terraform を利用して インフラのライフサイクル管理(作成・変更・削除) を行います
リソースの変更
main.tf のインスタンスタイプを変更する例:
resource "aws_instance" "ec2_server" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.small" # t3.micro → t3.small に変更
# ...
}
差分を確認:
terraform plan
出力例:
# aws_instance.ec2_server must be replaced
-/+ resource "aws_instance" "ec2_server" {
~ instance_type = "t3.micro" -> "t3.small"
# ...
}
Plan: 0 to add, 1 to change, 0 to destroy.
適用:
terraform apply
特定リソースのみ操作
特定のリソースだけを対象にする場合:
terraform plan -target=aws_instance.ec2_server
terraform apply -target=aws_instance.ec2_server
リソースの削除
全リソースを削除:
terraform destroy
確認プロンプトが表示されます:
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
確認をスキップする場合:
terraform destroy -auto-approve
特定リソースのみ削除:
terraform destroy -target=aws_instance.ec2_server
よく使うTerraformコマンド集
基本操作
初期化:
terraform init
プロバイダーの再ダウンロード:
terraform init -upgrade
実行計画の確認:
terraform plan
リソースの作成・変更:
terraform apply
確認なしで適用:
terraform apply -auto-approve
リソースの削除:
terraform destroy
状態管理
現在の状態を表示:
terraform show
管理中のリソース一覧:
terraform state list
出力例:
aws_instance.ec2_server
aws_internet_gateway.main
aws_route_table.public
aws_route_table_association.public
aws_security_group.ec2_sg
aws_subnet.public
aws_vpc.main
特定リソースの詳細:
terraform state show aws_instance.ec2_server
リソースを管理対象から除外:
terraform state rm aws_instance.ec2_server
フォーマットとバリデーション
コードのフォーマット:
terraform fmt
再帰的にフォーマット:
terraform fmt -recursive
構文チェック:
terraform validate
出力例:
Success! The configuration is valid.
出力値
全出力値の表示:
terraform output
特定の出力値:
terraform output ec2_public_ip
JSON形式で出力:
terraform output -json
その他
依存関係のグラフ出力:
terraform graph
ワークスペース一覧:
terraform workspace list
ワークスペースの作成:
terraform workspace new dev
ワークスペースの切り替え:
terraform workspace select dev
トラブルシューティング
認証エラーが出る場合
Error: No valid credential sources found
対処法:
-
aws configureが正しく設定されているか確認 - 環境変数
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYが設定されているか確認 -
~/.aws/credentialsファイルが存在するか確認
terraform initが失敗する場合
Error: Failed to install provider
対処法:
- インターネット接続を確認
- プロキシ環境の場合は
HTTPS_PROXY環境変数を設定 -
terraform init -upgradeで再試行
リソースの作成に失敗する場合
Error: creating EC2 Instance: UnauthorizedOperation
対処法:
- IAMユーザーに必要な権限があるか確認
- 必要なポリシー例:
AmazonEC2FullAccess,AmazonVPCFullAccess -
aws sts get-caller-identityで正しいユーザーか確認
stateファイルのロックエラー
Error: Error acquiring the state lock
対処法:
- 他のユーザーが
terraform applyを実行中でないか確認 - 強制的にロックを解除する場合:
terraform force-unlock <LOCK_ID>
terraform planとapplyの差分が出る場合
Note: Objects have changed outside of Terraform
対処法:
- AWSコンソールから手動で変更した場合に発生します
-
terraform refreshで状態を同期:
terraform apply -refresh-only
AWS CLI・Terraform・CloudFormation の使い分け
AWS CLIは「今の状態を確認する」、Terraformは「あるべき状態を定義する」、CloudFormationは「AWSネイティブであるべき状態を定義する」という使い分けが効果的です
| 用途 | AWS CLI | Terraform | CloudFormation |
|---|---|---|---|
| 一時的な確認・調査 | ○ | △ | × |
| リソースの一覧取得 | ○ | △ | △ |
| インフラの構築・管理 | △ | ○ | ○ |
| 環境の再現 | △ | ○ | ○ |
| チーム開発 | △ | ○ | ○ |
| 変更履歴の管理 | × | ○(Git連携) | ○(Git連携) |
| ドリフト検知 | × | ○ | ○ |
| マルチクラウド対応 | × | ○ | × |
| AWS以外のツール不要 | ○ | × | ○ |
| スタックのロールバック | × | △ | ○(自動) |
| AWSサポート対象 | ○ | × | ○ |
まとめ
Terraformを使うことで、AWSインフラをコードとして管理できます
この記事で紹介した内容:
- Terraformのインストール(Windows/Linux/Mac)
- AWS認証の設定方法
- VPC・サブネット・EC2の作成
- 基本コマンド(init / plan / apply / destroy)
- tfstateの管理とS3バックエンド
- 変数とoutputの活用
Terraformに慣れると、インフラの構築・変更・削除がコマンド一つで完結し、環境の再現やチーム開発が格段に効率化されます
