resource-naming について
AWS インフラを管理するチーム向けに、リソース命名規則をまとめたリファレンススキルです。プロジェクト・リソース・環境の形式を定め、サービス別の例と指針を示します。
主な機能
- 01プロジェクト・リソース・環境の形式
- 02環境サフィックスの指針
- 03AWS リソース別の命名パターン
- 04S3 名の衝突時にサフィックスを追加
- 05CDK の実装例
活用シーン
- 01開発・本番環境のリソース命名
- 02プロジェクト間の名称衝突の抑制
- 03CDK でのリソース名の統一
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ loxosceles-dev/ dev-skills --skill resource-namingインストール後、Claude Code で/resource-namingを入力して読み込まれたか確認します。
詳細
AWS リソースの命名規則
これは参照用のパターンです。 アプローチを参考にし、状況に合わせて調整してください。そのままコピーしないでください。
ステータス:🔴 重大なパターン
カテゴリ:インフラストラクチャ
適用対象:すべてのプロジェクトにおけるすべての AWS リソース
概要
このドキュメントでは、AWS リソースの標準的な命名規則を定義します。これらのパターンに従うことで、次のことを実現できます。
- プロジェクトの所有者を明確にする
- 環境を分離し、安全性を確保する
- リソースを一貫して識別する
- AWS コンソールでのフィルタリングと管理を容易にする
- リソースの競合やデータ破損を防ぐ
標準的な命名パターン
基本形式
{project}-{resource-name}-{environment}
構成要素
-
プロジェクトプレフィックス(必須)
- プロジェクトを示す短い識別子(2~4 文字)
- 小文字のみ
- 例:
cme、aip、app - リソースを所有するプロジェクトを識別します
-
リソース名(必須)
- リソースの用途を表します
- 小文字とハイフンを使用します
- 例:
job-extractor、opportunities、website
-
環境サフィックス(必須)
dev- 開発環境prod- 本番環境staging- ステージング環境(任意)local- ローカル開発(設定にのみ使用し、デプロイはしません)- 一貫性を保つため、必ず最後に配置します
このパターンを使う理由
- ✅ プロジェクトの所有者が明確:プレフィックスで所有するプロジェクトを識別できます
- ✅ 環境の位置が一貫:常に末尾に配置します
- ✅ 短い名前:一意性のために必要な場合を除き、アカウントやリージョンは含めません
- ✅ AWS のベストプラクティス:小文字とハイフンを使用します
- ✅ フィルタリングが容易:AWS コンソールでプレフィックスを使ってフィルタリングできます
- ✅ 複数プロジェクトに対応:複数のプロジェクトで 1 つのアカウントを共有する場合も、明確に分離できます
- ✅ 競合を防止:環境サフィックスによって、開発環境と本番環境の上書きを防ぎます
アカウント戦略:単一アカウントと複数アカウント
2 つのデプロイ方法
オプション 1:単一アカウント(開発環境と本番環境を同じ AWS アカウントで運用)
- コストが低い(アカウント間の複雑さがありません)
- IAM とネットワークの設定がシンプルです
- 競合を防ぐため、環境サフィックスが必要です
オプション 2:複数アカウント(開発環境と本番環境に別々の AWS アカウントを使用)
- 分離性とセキュリティが向上します
- 請求とコスト追跡を分けられます
- 安全性のため、環境サフィックスは引き続き必要です
環境サフィックスが常に必要な理由
AWS アカウントを分けている場合でも、環境サフィックスは重要な安全対策となります。
-
ヒューマンエラーの防止:作業中の環境をすぐに確認できます
# Without environment suffix aws lambda list-functions → job-extractor # Which environment is this? # With environment suffix aws lambda list-functions → job-extractor-prod # Clear: this is production! -
アカウントの取り違え防止:アカウントを切り替える際のミスを防ぎます
# You think you're in dev account, but you're actually in prod # Without suffix: You might delete "job-extractor" thinking it's dev # With suffix: You see "job-extractor-prod" and stop immediately -
将来への備え:アカウント戦略が変わる可能性があります
- 単一アカウントで開始し、後から複数アカウントに分割する
- コスト最適化のためにアカウントを統合する
- 既存のアカウントにステージング環境を追加する
-
一貫性:どの環境でも同じ命名パターンを使用できます
- ローカル開発
- CI/CD パイプライン
- AWS コンソール
- CloudFormation/CDK コード
実際のシナリオ
# You're debugging an issue and need to check Lambda logs
# You have AWS CLI configured with multiple profiles
# Scenario 1: Without environment suffix
aws lambda get-function --function-name job-extractor --profile prod-account
# ⚠️ Is this the right function? Hard to tell from name alone
# Scenario 2: With environment suffix
aws lambda get-function --function-name job-extractor-prod --profile prod-account
# ✅ Name confirms you're looking at production resource
# ✅ Immediate visual confirmation prevents mistakes
ルール:アカウント戦略にかかわらず、常に環境サフィックスを含めてください。追加コストのない安全対策であり、高くつくミスを防げます。
重要:環境サフィックスが重要な理由
問題
リソース名に環境を示す識別子がないと、同じ AWS アカウントにデプロイした際に開発環境と本番環境のリソースが競合し、上書きやデータ破損が発生します。
実際の影響
Lambda 関数(名前に環境が含まれない場合):
// ❌ WRONG
functionName: 'job-data-extractor'
// GitHub Actions deploys dev
ENVIRONMENT=dev → Lambda: job-data-extractor
// GitHub Actions deploys prod
ENVIRONMENT=prod → Lambda: job-data-extractor // OVERWRITES dev!
DynamoDB テーブル(名前に環境が含まれない場合):
// ❌ WRONG
tableName: `opportunities-${account}-${region}`
// Both environments use SAME table
// Result: Dev and prod data MIXED!
解決策
必ずリソース名に環境を含めてください:
// ✅ CORRECT
functionName: `job-data-extractor-${environment}`
tableName: `opportunities-${environment}`
// Results:
// dev: job-data-extractor-dev, opportunities-dev
// prod: job-data-extractor-prod, opportunities-prod
リソース別のパターン
Lambda 関数
パターン:{project}-{function-name}-{environment}
例:
// ✅ CORRECT
functionName: `cme-job-extractor-${environment}`
functionName: `aip-data-sync-${environment}`
// Results:
// cme-job-extractor-dev
// cme-job-extractor-prod
// aip-data-sync-dev
理由:Lambda 名はアカウントごとに一意である必要があります。環境サフィックスにより、開発環境と本番環境の競合を防げます。
DynamoDB テーブル
パターン:{project}-{table-name}-{environment}
例:
// ✅ CORRECT
tableName: `cme-opportunities-${environment}`
tableName: `aip-user-sessions-${environment}`
// Results:
// cme-opportunities-dev
// cme-opportunities-prod
拡張パターン(任意)(一意性が必要な場合):
tableName: `{project}-{table-name}-${environment}-${account}-${region}`
// Example:
// cme-opportunities-dev-123456-us-east-1
理由:テーブル名はアカウントごとに一意である必要があります。データの混在を防ぐには、環境サフィックスが重要です。
S3 バケット
パターン:{project}-{bucket-purpose}-{environment}(名前が重複する場合はランダムなサフィックスを追加)
例:
// ✅ CORRECT
bucketName: `cme-website-${environment}`
bucketName: `aip-assets-${environment}`
// Results:
// cme-website-dev
// cme-website-prod
名前が重複する場合(バケット名がグローバルにすでに使用されている場合):
bucketName: `cme-website-${environment}-x7k2m`
// Results:
// cme-website-dev-x7k2m
// cme-website-prod-p9n4q
重要な注意事項:
- バケット名はすべての AWS アカウント間でグローバルに一意である必要があります
- 使用できるのは小文字、数字、ハイフンのみです(アンダースコアは使用できません)
- 「BucketAlreadyExists」エラーでデプロイに失敗した場合は、ランダムなサフィックスを追加します
- サフィックスの形式:ランダムな英小文字と数字を組み合わせた5文字
理由:バケット名はグローバルに一意である必要があります。まずはシンプルなパターンを使用し、必要な場合にのみサフィックスを追加します。
API Gateway
パターン:{PROJECT} API - {environment}(表示名。プロジェクト名は大文字)
例:
// ✅ CORRECT
restApiName: `CME API - ${environment}`
restApiName: `AIP API - ${environment}`
// Results:
// CME API - dev
// CME API - prod
理由:人が確認するための表示名です。AWS コンソールで読みやすいように大文字を使用します。
CloudFront ディストリビューション
パターン:コメント欄:{Project Name} - {environment}
例:
Career Match Engine - dev
AI Portfolio - prod
タグ:Environment: dev または Environment: prod
理由:CloudFront の ID は自動生成されます。識別にはコメントとタグを使用します。
Lambda レイヤー
パターン:{project}-{layer-name} または {project}-{layer-name}-{environment}
例:
// Shared across environments
layerName: 'cme-common-layer'
layerName: 'aip-utils-layer'
// Environment-specific
layerName: `cme-config-layer-${environment}`
注:レイヤーは複数の環境で共有されることがよくあります。環境サフィックスは任意です。
理由:レイヤーにはバージョンが付与されます。環境間で共有すると重複を減らせます。
Lambda レイヤーのコード構成
目標:コードの重複を避けながら、各 Lambda に必要なものだけを提供します。これはデプロイサイズとコードの再利用性のトレードオフであり、ケースごとに評価してください。
レイヤー構造:適用範囲と再利用性に基づいて整理します
layers/
common/ # Truly shared utilities (3+ consumers)
nodejs/
logger.mjs
response-builder.mjs
config-loader.mjs
validation.mjs
feature-utils/ # Feature-specific utilities
nodejs/
feature-operations.mjs
feature-schemas.mjs
external-sdks/ # Third-party integrations
nodejs/
package.json # npm dependencies
sdk-wrapper.mjs
共有コードの整理:
共通レイヤー - 広く使用されるユーティリティ向け:
- 汎用ヘルパー(ログ記録、検証、レスポンス形式の整形)
- 3つ以上の異なる機能で使用
- 特定の機能に固有のロジックを含まない
機能レイヤー - 特定の機能で共有されるコード向け:
- 特定のドメインに関する操作とスキーマ
- その機能内の2つ以上の関数で使用
- 機能固有のロジックを含む
統合レイヤー - 外部依存関係向け:
- サードパーティ SDK パッケージ
- 外部サービスのラッパー
- バージョン管理を分離
複数のレイヤーの使用:
// Function can reference multiple layers
const myFunction = new Function({
layers: [
commonLayer, // Generic utilities
featureALayer, // Feature A utilities
featureBLayer // Feature B utilities (if needed)
]
});
判断ガイド:
- 汎用ユーティリティ →
commonレイヤー - 機能固有のコード → 機能レイヤー
- 外部パッケージ → 統合レイヤー
- 複数機能にまたがる要件 → 複数のレイヤーを参照
トレードオフ:
- レイヤーが多いほど、個々の Lambda は軽量になりますが、複雑さが増します
- レイヤーが少ないほど、設定はシンプルになりますが、デプロイサイズが大きくなります
- プロジェクトのニーズに応じてバランスを取ってください
シナリオの例:複数の機能で使用される API スキーマ
- 汎用の場合:
commonレイヤーに移動します - 機能固有の場合:機能レイヤーに保持し、他の機能から参照します
- 重複させない:レイヤーの組み合わせを使用します
SQS キュー
パターン:{project}-{queue-name}-{environment}
例:
queueName: `cme-job-processing-${environment}`
queueName: `aip-notifications-${environment}`
SNS トピック
パターン:{project}-{topic-name}-{environment}
例:
topicName: `cme-alerts-${environment}`
topicName: `aip-events-${environment}`
EventBridge ルール
パターン:{project}-{rule-name}-{environment}
例:
ruleName: `cme-daily-sync-${environment}`
ruleName: `aip-cleanup-${environment}`
Step Functions
パターン:{project}-{state-machine-name}-{environment}
例:
stateMachineName: `cme-workflow-${environment}`
stateMachineName: `aip-pipeline-${environment}`
Secrets Manager
パターン:{project}/{environment}/{secret-name}
例:
secretName: `cme/${environment}/api-key`
secretName: `aip/${environment}/db-password`
SSM パラメータ
パターン:/{project}/{environment}/{namespace}/{key}
例:
/cme/dev/lambda/job-extractor/LLM_API_KEY
/cme/prod/api/corsAllowedOrigins
/aip/dev/frontend/api-endpoint
注:過去との互換性のため、SSM ではプロジェクト名に camelCase を使用します。
CloudWatch Log Groups
パターン:/aws/lambda/{project}-{function-name}-{environment}
例:
/aws/lambda/cme-job-extractor-dev
/aws/lambda/cme-recruiter-chat-prod
/aws/lambda/aip-data-sync-dev
注:Lambda によって自動生成されます。Lambda の命名規則に従います。
CDK の実装パターン
コンストラクトの Props
export interface ResourceConstructProps {
projectPrefix: string; // 'cme', 'aip', etc.
environment: string; // 'dev', 'prod', 'staging'
account: string;
region: string;
}
Lambda 関数
const myFunction = new lambda.Function(this, 'MyFunction', {
functionName: `${props.projectPrefix}-my-function-${props.environment}`,
runtime: lambda.Runtime.NODEJS_22_X,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda'),
environment: {
ENVIRONMENT: props.environment,
PROJECT: props.projectPrefix
}
});
DynamoDB テーブル
const myTable = new dynamodb.Table(this, 'MyTable', {
tableName: `${props.projectPrefix}-my-table-${props.environment}`,
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
removalPolicy: props.environment === 'prod'
? cdk.RemovalPolicy.RETAIN
: cdk.RemovalPolicy.DESTROY
});
S3 バケット
const myBucket = new s3.Bucket(this, 'MyBucket', {
bucketName: `${props.projectPrefix}-my-bucket-${props.environment}`,
removalPolicy: props.environment === 'prod'
? cdk.RemovalPolicy.RETAIN
: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: props.environment !== 'prod'
});
環境変数の設定
必須の環境変数
# Must be set before deployment
export ENVIRONMENT=dev # or 'prod', 'staging', etc.
export PROJECT_PREFIX=myapp # Short project identifier
デプロイスクリプト
#!/bin/bash
set -e
if [ -z "$ENVIRONMENT" ]; then
echo "Error: ENVIRONMENT is not set"
echo "Usage: ENVIRONMENT=dev ./deploy.sh"
exit 1
fi
if [ -z "$PROJECT_PREFIX" ]; then
echo "Error: PROJECT_PREFIX is not set"
echo "Usage: PROJECT_PREFIX=myapp ENVIRONMENT=dev ./deploy.sh"
exit 1
fi
echo "Deploying $PROJECT_PREFIX to environment: $ENVIRONMENT"
cdk deploy --all
GitHub Actions
name: Deploy
on:
push:
branches:
- main # Deploys to prod
- develop # Deploys to dev
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set environment
run: |
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
echo "ENVIRONMENT=prod" >> $GITHUB_ENV
else
echo "ENVIRONMENT=dev" >> $GITHUB_ENV
fi
echo "PROJECT_PREFIX=myapp" >> $GITHUB_ENV
- name: Deploy
run: |
echo "Deploying $PROJECT_PREFIX to $ENVIRONMENT"
./deploy.sh
検証チェックリスト
リソースをデプロイする前に、以下を確認してください。
- プロジェクトのプレフィックス(
cme-、aip-など)で始まっている - 環境(
-dev、-prod、-staging)で終わっている - 小文字とハイフンを使用している(API Gateway の表示名を除く)
- 環境値をハードコードしていない(変数を使用する)
- リソースの用途が名前から明確にわかる
- パターン
{project}-{resource-name}-{environment}に従っている - デプロイ前に環境変数が設定されている
よくある落とし穴
❌ 落とし穴 1:環境のハードコード
// ❌ WRONG - Hardcoded 'dev'
bucketName: `my-app-dev`
// ✅ CORRECT - Use variable
bucketName: `my-app-${environment}`
❌ 落とし穴 2:環境変数の設定漏れ
// ❌ WRONG - No environment
functionName: 'my-function'
// ✅ CORRECT - Include environment
functionName: `my-function-${environment}`
❌ 落とし穴 3:一貫性のないパターン
// ❌ WRONG - Inconsistent
functionName: `my-function-${environment}` // Has environment
tableName: `my-table` // Missing environment
// ✅ CORRECT - Consistent
functionName: `my-function-${environment}`
tableName: `my-table-${environment}`
❌ 落とし穴 4:プロジェクトのプレフィックス漏れ
// ❌ WRONG - No project identification
functionName: `job-extractor-${environment}`
// ✅ CORRECT - Include project prefix
functionName: `cme-job-extractor-${environment}`
❌ 落とし穴 5:アカウントが異なれば環境のサフィックスは不要だと思い込む
// ❌ WRONG ASSUMPTION
// "We use different AWS accounts for dev/prod, so we don't need environment in names"
functionName: 'job-extractor' // No environment suffix
// ✅ CORRECT - Always include environment
functionName: `job-extractor-${environment}`
// REALITY:
// - Human error: You might be in wrong account without realizing
// - Visual confirmation: Name tells you it's prod even if you're confused about account
// - Account strategy might change (single → multi or multi → single)
// - Consistency: Same pattern works for single and multi-account setups
// - Safety layer: Costs nothing, prevents costly mistakes
古い名前からの移行
監査フェーズ
- アカウント内のすべての AWS リソースを一覧表示します
- 名前に環境が含まれていないリソースを特定します
- プロジェクトのプレフィックスが含まれていないリソースを特定します
- 影響を受ける環境を記録します
- 移行戦略を計画します
移行フェーズ
- 正しい名前で新しいリソースをデプロイします
- 古いリソースから新しいリソースにデータを移行します
- 新しいリソースを使用するようアプリケーションを更新します
- 新しいリソースが動作していることを確認します
- 検証後に古いリソースを削除します
検証
分離を確認する方法
AWS コンソールでの確認:
# List all Lambda functions
aws lambda list-functions --query 'Functions[*].FunctionName'
# Should see:
# - cme-my-function-dev
# - cme-my-function-prod
# ✅ Clear project and environment separation
# NOT:
# - my-function
# ❌ No project or environment identifier
DynamoDB の確認:
# List all tables
aws dynamodb list-tables
# Should see:
# - cme-my-table-dev
# - cme-my-table-prod
# ✅ Clear separation
デプロイテスト:
# Deploy dev
ENVIRONMENT=dev ./deploy.sh
# Deploy prod
ENVIRONMENT=prod ./deploy.sh
# Verify:
# - No resource overwrites
# - Both environments coexist
# - No conflicts or errors
クイックリファレンス
✅ 実施すること
- すべてのリソース名にプロジェクトのプレフィックスを含める
- すべてのリソース名に
${environment}を含める - すべてのリソースで一貫した命名パターンを使用する
- デプロイ前に環境変数が設定されていることを確認する
- 同じアカウントへの dev と prod の両方のデプロイをテストする
- プロジェクトの README に命名規則を記載する
❌ 避けること
- 環境値('dev'、'prod')をハードコードする
- リソース名からプロジェクトのプレフィックスを省略する
- AWS アカウントが異なれば命名は不要だと思い込む
- 「一時」リソースや「テスト」リソースで環境を省略する
- リソースの種類ごとに異なる命名パターンを使用する
- 環境変数を確認せずにデプロイする
関連するパターン
- 構成管理 - 環境固有の構成
- インフラストラクチャの概要 - インフラストラクチャの一般的なパターン
- セキュリティの概要 - セキュリティに関する考慮事項
まとめ
重要なルール:
- すべての AWS リソース名にプロジェクトのプレフィックスを含める必要があります
- すべての AWS リソース名に環境識別子を含める必要があります
- パターン
{project}-{resource-name}-{environment}を使用します
理由:
- リソースの競合やデータ破損を防ぎます
- プロジェクトの所有者を明確にできます
- 同じアカウントへの複数環境の安全なデプロイが可能になります
- リソースの識別と管理が容易になります
方法:すべてのリソース名で ${projectPrefix} と ${environment} の変数を一貫して使用します。
検証:同じアカウントに dev と prod の両方をデプロイし、競合がないことを確認します。
重要:これは任意ではありません。本番環境のインシデントを防ぎ、リソースを明確に管理するための重要なパターンです。
段階的な改善
このスキルで防止できるはずの動作について開発者から修正を受けた場合は、今後同じ修正が必要にならないよう、このスキルに加える具体的な改訂案を提案してください。