terraform-style-guide について
HashiCorpのスタイル規約に沿ったTerraform設定の作成・保守を支援するガイドです。インフラコードの作成者向けに、ファイル構成、命名、書式、安全性、バージョン制約を扱います。
主な機能
- 01Terraformファイル構成の指針
- 02インデントと引数順序の規則
- 03リソース・変数・出力の命名
- 04変数と出力の説明要件
- 05セキュリティとバージョン制約の指針
- 06コミット前の検証チェックリスト
活用シーン
- 01統一した構成でTerraform設定を作成
- 02変数と出力の説明が揃っているか確認
- 03設定生成時にセキュリティ慣行を適用
- 04コミット前にTerraformコードを整形・検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ pedronauck/ skills --skill terraform-style-guideインストール後、Claude Code で/terraform-style-guideを入力して読み込まれたか確認します。
詳細
Terraform スタイルガイド
HashiCorp の公式スタイル規約とベストプラクティスに従って、Terraform コードを生成・保守します。
参照先: HashiCorp Terraform スタイルガイド
コード生成の方針
Terraform コードを生成する際は、以下の手順に従います。
- プロバイダーの設定とバージョン制約から始めます
- 依存するリソースより先にデータソースを作成します
- 依存関係の順序に従ってリソースを構築します
- 主要なリソース属性の出力を追加します
- 設定可能な値にはすべて変数を使用します
ファイル構成
| ファイル | 目的 |
|---|---|
terraform.tf | Terraform とプロバイダーのバージョン要件 |
providers.tf | プロバイダーの設定 |
main.tf | 主なリソースとデータソース |
variables.tf | 入力変数の宣言(アルファベット順) |
outputs.tf | 出力値の宣言(アルファベット順) |
locals.tf | ローカル値の宣言 |
構成例
# terraform.tf
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# variables.tf
variable "environment" {
description = "Target deployment environment"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
# locals.tf
locals {
common_tags = {
Environment = var.environment
ManagedBy = "Terraform"
}
}
# main.tf
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-vpc"
})
}
# outputs.tf
output "vpc_id" {
description = "ID of the created VPC"
value = aws_vpc.main.id
}
コードのフォーマット
インデントと配置
- ネストの各レベルで半角スペース 2 つを使用します(タブは使用しません)
- 連続する引数では等号の位置をそろえます
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
subnet_id = "subnet-12345678"
tags = {
Name = "web-server"
Environment = "production"
}
}
ブロックの配置
引数はブロックより前に記述し、メタ引数を先に配置します。
resource "aws_instance" "example" {
# Meta-arguments
count = 3
# Arguments
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
# Blocks
root_block_device {
volume_size = 20
}
# Lifecycle last
lifecycle {
create_before_destroy = true
}
}
命名規則
- すべての名前に小文字とアンダースコアを使用します
- リソースタイプを含めず、内容を表す名詞を使用します
- 具体的で意味のある名前にします
- リソース名は複数形ではなく単数形にします
- 具体的で分かりやすい名前が不要または付けられない場合、かつインスタンスが 1 つのみの場合は、リソース名に
mainを使用します
# Bad
resource "aws_instance" "webAPI-aws-instance" {}
resource "aws_instance" "web_apis" {}
variable "name" {}
# Good
resource "aws_instance" "web_api" {}
resource "aws_vpc" "main" {}
variable "application_name" {}
変数
すべての変数に type と description を指定します。
variable "instance_type" {
description = "EC2 instance type for the web server"
type = string
default = "t2.micro"
validation {
condition = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_type)
error_message = "Instance type must be t2.micro, t2.small, or t2.medium."
}
}
variable "database_password" {
description = "Password for the database admin user"
type = string
sensitive = true
}
出力
すべての出力に description を指定します。
output "instance_id" {
description = "ID of the EC2 instance"
value = aws_instance.web.id
}
output "database_password" {
description = "Database administrator password"
value = aws_db_instance.main.password
sensitive = true
}
動的なリソース作成
count より for_each を優先する
# Bad - count for multiple resources
resource "aws_instance" "web" {
count = var.instance_count
tags = { Name = "web-${count.index}" }
}
# Good - for_each with named instances
variable "instance_names" {
type = set(string)
default = ["web-1", "web-2", "web-3"]
}
resource "aws_instance" "web" {
for_each = var.instance_names
tags = { Name = each.key }
}
条件付き作成に count を使用する
resource "aws_cloudwatch_metric_alarm" "cpu" {
count = var.enable_monitoring ? 1 : 0
alarm_name = "high-cpu-usage"
threshold = 80
}
セキュリティのベストプラクティス
コードを生成する際は、セキュリティを強化します。
- デフォルトで保存時の暗号化を有効にします
- 適用可能な場合はプライベートネットワークを設定します
- セキュリティグループには最小権限の原則を適用します
- ログ記録とモニタリングを有効にします
- 認証情報やシークレットをハードコードしません
- 機密性の高い出力には
sensitive = trueを指定します
例:セキュアな S3 バケット
resource "aws_s3_bucket" "data" {
bucket = "${var.project}-${var.environment}-data"
tags = local.common_tags
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.s3.arn
}
}
}
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
バージョンの固定
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # Allow minor updates
}
}
}
バージョン制約の演算子:
= 1.0.0- バージョンを厳密に指定>= 1.0.0- 以上~> 1.0- 右端のコンポーネントの増加を許可>= 1.0, < 2.0- バージョン範囲
プロバイダーの設定
provider "aws" {
region = "us-west-2"
default_tags {
tags = {
ManagedBy = "Terraform"
Project = var.project_name
}
}
}
# Aliased provider for multi-region
provider "aws" {
alias = "east"
region = "us-east-1"
}
バージョン管理
コミットしないファイル:
terraform.tfstate、terraform.tfstate.backup.terraform/ディレクトリ*.tfplan- 機密データを含む
.tfvarsファイル
必ずコミットするファイル:
- すべての
.tf設定ファイル .terraform.lock.hcl(依存関係ロックファイル)
検証ツール
コミット前に実行します。
terraform fmt -recursive
terraform validate
追加ツール:
tflint- リントとベストプラクティスのチェックcheckov/tfsec- セキュリティスキャン
コードレビューのチェックリスト
-
terraform fmtでコードをフォーマットした -
terraform validateで設定を検証した - 標準的な構成に従ってファイルを整理した
- すべての変数に型と説明を指定した
- すべての出力に説明を指定した
- リソース名に内容を表す名詞とアンダースコアを使用した
- バージョン制約を明示的に固定した
- 機密値に
sensitive = trueを指定した - 認証情報やシークレットをハードコードしていない
- セキュリティのベストプラクティスを適用した
コメント
Markdown 対応