EXERCISE 60分

佐藤CTOからの指令:「新サービスのインフラをIaCで構築してほしい。Terraformのモジュール設計、CDKによるアプリケーションスタック、テスト、マルチ環境戦略を一通り設計してくれ。」

#ミッション難易度目安時間
1Terraformモジュール設計★★☆15分
2CDKスタック設計★★★15分
3IaCテスト戦略★★☆15分
4マルチ環境戦略★★★15分

Mission 1: Terraformモジュール設計

以下のインフラをTerraformのモジュールとして設計せよ。

要件:
- ECS Fargate クラスタ(Web + API)
- RDS PostgreSQL(Primary + Read Replica)
- ElastiCache Redis クラスタ
- ALB + WAF
- VPC (Public/Private/Isolated Subnet)
解答例
graph TD
    subgraph ModDir["modules/"]
        Net["networking/
VPC, Subnets, NAT GW, SG
main.tf / variables.tf / outputs.tf"] ECSCluster["ecs-cluster/
ECS Cluster, Capacity Providers"] ECSSvc["ecs-service/
ECS Service, Task Def, Auto Scaling
再利用: web/api で同モジュール"] RDS["rds/
RDS Instance, Parameter Group"] ElastiC["elasticache/
Redis Cluster, Replication Group"] ALB["alb/
ALB, Target Group, Listener Rules"] WAF["waf/
WAF Web ACL, Rules"] end subgraph EnvDir["environments/"] Dev["dev/
main.tf / terraform.tfvars / backend.tf"] Stg["staging/"] Prod["production/"] end Dev -.->|module呼び出し| ModDir Stg -.->|module呼び出し| ModDir Prod -.->|module呼び出し| ModDir style ModDir fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e40af style EnvDir fill:#d1fae5,stroke:#059669,color:#065f46 style Net fill:#f3f4f6,stroke:#9ca3af,color:#374151 style ECSSvc fill:#f3f4f6,stroke:#9ca3af,color:#374151 style RDS fill:#f3f4f6,stroke:#9ca3af,color:#374151 style Dev fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#92400e style Stg fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#92400e style Prod fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#92400e

Mission 2: CDKスタック設計

同じインフラをAWS CDKで設計する場合のスタック分割を設計せよ。

解答例
// lib/stacks/
// スタック分割の考え方:
// 1. ライフサイクルが異なるリソースは別スタック
// 2. 変更頻度が高いものと低いものを分離
// 3. 依存関係の方向を一方向に

class NetworkStack extends cdk.Stack {
  public readonly vpc: ec2.Vpc;
  // VPCは変更頻度が最も低い → 独立スタック
}

class DatabaseStack extends cdk.Stack {
  public readonly cluster: rds.DatabaseCluster;
  public readonly redis: elasticache.CfnReplicationGroup;
  // DB は破壊的変更のリスクが高い → 独立スタック + deletion protection
}

class ComputeStack extends cdk.Stack {
  // ECS Service, Task Definition, Auto Scaling
  // 最も変更頻度が高い → デプロイしやすく
}

class MonitoringStack extends cdk.Stack {
  // CloudWatch Dashboards, Alarms, SNS Topics
}

// app.ts
const network = new NetworkStack(app, 'Network', { env });
const database = new DatabaseStack(app, 'Database', { env, vpc: network.vpc });
const compute = new ComputeStack(app, 'Compute', {
  env, vpc: network.vpc, db: database.cluster, redis: database.redis
});
new MonitoringStack(app, 'Monitoring', { env, service: compute.service });

Mission 3: IaCテスト戦略

IaCコードの品質を保証するテスト戦略を設計せよ。

解答例
■ テストピラミッド

1. 静的解析(PR時、数秒)
   - tflint: Terraform構文チェック
   - checkov / tfsec: セキュリティスキャン
   - cdk synth: CDKの合成テスト

2. ユニットテスト(PR時、数分)
   - CDK: assertions + Template.fromStack()
   - Terraform: terraform validate + plan

3. 統合テスト(マージ後、10-30分)
   - Terratest: 実際にリソースを作成して検証
   - 一時的な環境で apply → テスト → destroy

4. コンプライアンスチェック(全環境、定期実行)
   - AWS Config Rules
   - cfn-guard: CloudFormationポリシー検証
// CDK ユニットテストの例
import { Template } from 'aws-cdk-lib/assertions';

test('RDS has deletion protection enabled', () => {
  const template = Template.fromStack(databaseStack);
  template.hasResourceProperties('AWS::RDS::DBInstance', {
    DeletionProtection: true,
    StorageEncrypted: true,
    MultiAZ: true,
  });
});

test('ECS Service has auto scaling configured', () => {
  const template = Template.fromStack(computeStack);
  template.resourceCountIs('AWS::ApplicationAutoScaling::ScalableTarget', 1);
});

Mission 4: マルチ環境戦略

dev / staging / production の3環境を効率的に管理する戦略を設計せよ。

解答例
観点devstagingproduction
目的開発・実験本番同等テストユーザー向け
インスタンスサイズ最小(t3.small)本番の1/2フルスペック
冗長性Single-AZMulti-AZMulti-AZ
データテストデータ匿名化本番データ本番データ
State管理S3 (dev bucket)S3 (staging bucket)S3 (prod bucket)
承認フロー自動手動承認手動承認 + Slack通知
コスト対策夜間停止夜間停止常時稼働
# terraform.tfvars での環境差分管理
# environments/production/terraform.tfvars
environment         = "production"
instance_type       = "c5.xlarge"
min_capacity        = 3
max_capacity        = 50
multi_az            = true
deletion_protection = true
backup_retention    = 30