takt/builtins/en/facets/knowledge/terraform-aws.md
nrslib 1cd063680c feat: Terraform/AWS ピースとファセット一式を追加
hoicil-spot-tf の規約を分析し、専用のピース・ファセットを作成。
plan → implement → 3並列レビュー → fix → COMPLETE のワークフロー。
カテゴリに「インフラストラクチャ」を追加。
2026-02-25 23:50:52 +09:00

242 lines
6.9 KiB
Markdown

# Terraform AWS Knowledge
## Module Design
Split modules by domain (network, database, application layer). Do not create generic utility modules.
| Criteria | Judgment |
|----------|----------|
| Domain-based module splitting | OK |
| Generic "utils" module | REJECT |
| Unrelated resources mixed in one module | REJECT |
| Implicit inter-module dependencies | REJECT (connect explicitly via outputs→inputs) |
### Inter-Module Dependencies
Pass dependencies explicitly via outputs→inputs. Avoid implicit references (using `data` sources to look up other module resources).
```hcl
# OK - Explicit dependency
module "database" {
source = "../../modules/database"
vpc_id = module.network.vpc_id
subnet_ids = module.network.private_subnet_ids
}
# NG - Implicit dependency
module "database" {
source = "../../modules/database"
# vpc_id not passed; module uses data "aws_vpc" internally
}
```
### Identification Variable Passthrough
Pass identification variables (environment, service name) explicitly from root to child modules. Do not rely on globals or hardcoding.
```hcl
# OK - Explicit passthrough
module "database" {
environment = var.environment
service = var.service
application_name = var.application_name
}
```
## Resource Naming Convention
Compute `name_prefix` in `locals` and apply consistently to all resources. Append resource-specific suffixes.
| Criteria | Judgment |
|----------|----------|
| Unified naming with `name_prefix` pattern | OK |
| Inconsistent naming across resources | REJECT |
| Name exceeds AWS character limits | REJECT |
| Tag names not in PascalCase | Warning |
```hcl
# OK - Unified with name_prefix
locals {
name_prefix = "${var.environment}-${var.service}-${var.application_name}"
}
resource "aws_ecs_cluster" "main" {
name = "${local.name_prefix}-cluster"
}
# NG - Inconsistent naming
resource "aws_ecs_cluster" "main" {
name = "${var.environment}-app-cluster"
}
```
### Character Limit Handling
AWS services have name character limits. Use shortened forms when approaching limits.
| Service | Limit | Example |
|---------|-------|---------|
| Target Group | 32 chars | `${var.environment}-${var.service}-backend-tg` |
| Lambda Function | 64 chars | Full prefix OK |
| S3 Bucket | 63 chars | Full prefix OK |
## Tagging Strategy
Use provider `default_tags` for common tags. No duplicate tagging on individual resources.
| Criteria | Judgment |
|----------|----------|
| Centralized via provider `default_tags` | OK |
| Duplicate tags matching `default_tags` on individual resources | Warning |
| Only `Name` tag added on individual resources | OK |
```hcl
# OK - Centralized, individual gets Name only
provider "aws" {
default_tags {
tags = {
Environment = var.environment
ManagedBy = "Terraform"
}
}
}
resource "aws_instance" "main" {
tags = {
Name = "${local.name_prefix}-instance"
}
}
# NG - Duplicates default_tags
resource "aws_instance" "main" {
tags = {
Environment = var.environment
ManagedBy = "Terraform"
Name = "${local.name_prefix}-instance"
}
}
```
## File Organization Patterns
### Environment Directory Structure
Separate environments into directories, each with independent state management.
```
environments/
├── production/
│ ├── terraform.tf # Version constraints
│ ├── providers.tf # Provider config (default_tags)
│ ├── backend.tf # S3 backend
│ ├── variables.tf # Environment variables
│ ├── main.tf # Module invocations
│ └── outputs.tf # Outputs
└── staging/
└── ...
```
### Module File Structure
| File | Contents |
|------|----------|
| `main.tf` | `locals` and `data` sources only |
| `variables.tf` | Input variable definitions only (no resources) |
| `outputs.tf` | Output definitions only (no resources) |
| `{resource_type}.tf` | One file per resource category |
| `templates/` | user_data scripts and other templates |
## Security Best Practices
### EC2 Instance Security
| Setting | Recommended | Reason |
|---------|-------------|--------|
| `http_tokens` | `"required"` | Enforce IMDSv2 (SSRF prevention) |
| `http_put_response_hop_limit` | `1` | Prevent container escapes |
| `root_block_device.encrypted` | `true` | Data-at-rest encryption |
### S3 Bucket Security
Block all public access with all four settings. Use OAC (Origin Access Control) for CloudFront distributions.
```hcl
# OK - Complete block
resource "aws_s3_bucket_public_access_block" "this" {
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
```
### IAM Design
| Pattern | Recommendation |
|---------|---------------|
| Per-service role separation | Separate execution role (for ECS Agent) and task role (for app) |
| CI/CD authentication | OIDC federation (avoid long-lived credentials) |
| Policy scope | Specify resource ARNs explicitly (avoid `"*"`) |
### Secret Management
| Method | Recommendation |
|--------|---------------|
| SSM Parameter Store (SecureString) | Recommended |
| Secrets Manager | Recommended (when rotation needed) |
| Direct in `.tfvars` | Conditional OK (gitignore required) |
| Hardcoded in `.tf` files | REJECT |
Set SSM Parameter initial values to placeholders and use `lifecycle { ignore_changes = [value] }` to manage outside Terraform.
## Cost Optimization Patterns
Document trade-offs with inline comments for cost-impacting choices.
| Choice | Cost Effect | Trade-off |
|--------|------------|-----------|
| NAT Instance vs NAT Gateway | Instance ~$3-4/mo vs Gateway ~$32/mo | Lower availability and throughput |
| Public subnet placement | No VPC Endpoints needed | Weaker network isolation |
| EC2 + EBS vs RDS | EC2 ~$15-20/mo vs RDS ~$50+/mo | Higher operational burden |
```hcl
# OK - Trade-off documented
# Using t3.nano instead of NAT Gateway (~$3-4/mo vs ~$32/mo)
# Trade-off: single-AZ availability, throughput limits
resource "aws_instance" "nat" {
instance_type = "t3.nano"
}
```
## Lifecycle Rule Usage
| Rule | Purpose | Target |
|------|---------|--------|
| `prevent_destroy` | Prevent accidental deletion | Databases, EBS volumes |
| `ignore_changes` | Allow external changes | `desired_count` (Auto Scaling), SSM `value` |
| `create_before_destroy` | Prevent downtime | Load balancers, security groups |
```hcl
# OK - Prevent accidental database deletion
resource "aws_instance" "database" {
lifecycle {
prevent_destroy = true
}
}
# OK - Let Auto Scaling manage desired_count
resource "aws_ecs_service" "main" {
lifecycle {
ignore_changes = [desired_count]
}
}
```
## Version Management
| Setting | Recommendation |
|---------|---------------|
| `required_version` | `">= 1.5.0"` or higher (`default_tags` support) |
| Provider version | Pin minor version with `~>` (e.g., `~> 5.80`) |
| State locking | `use_lockfile = true` required |