【保存版】Terraformで作るAWS RDS環境構築完全ガイド2024 〜実践的な11のベストプラクティス〜

Terraformを使用したRDS構築の基礎知識

Terraformとは

TerraformはHashiCorpが開発したインフラストラクチャ・アズ・コード(IaC)ツールです。AWSのRDSを含む各種リソースを、コードで宣言的に管理できます。

TerraformとRDSの関係性を理解する

TerraformでRDSを管理するメリット:

  • インフラのバージョン管理: GitなどでRDS構成の変更履歴を追跡可能
  • 環境の再現性: 本番/開発/検証環境を同じコードで構築可能
  • 自動化: プロビジョニングや設定変更を自動化
  • ドリフト検知: 手動変更された設定の検出が容易

Terraformで定義できるRDSの主要コンポーネント

  1. RDSインスタンス基本設定
resource "aws_db_instance" "example" {
  identifier        = "example-database"
  engine            = "mysql"
  engine_version    = "8.0.28"
  instance_class    = "db.t3.micro"
  allocated_storage = 20

  # 認証情報
  username = "admin"
  password = "your_password_here"

  # ネットワーク設定
  vpc_security_group_ids = [aws_security_group.rds.id]
  db_subnet_group_name   = aws_db_subnet_group.example.name
}
  1. サブネットグループ
resource "aws_db_subnet_group" "example" {
  name       = "example-subnet-group"
  subnet_ids = [aws_subnet.private1.id, aws_subnet.private2.id]

  tags = {
    Name = "Example DB subnet group"
  }
}
  1. パラメータグループ
resource "aws_db_parameter_group" "example" {
  family = "mysql8.0"
  name   = "example-paramgroup"

  parameter {
    name  = "character_set_server"
    value = "utf8mb4"
  }

  parameter {
    name  = "collation_server"
    value = "utf8mb4_unicode_ci"
  }
}
  1. セキュリティグループ
resource "aws_security_group" "rds" {
  name        = "example-rds-sg"
  description = "Security group for RDS instance"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = [aws_security_group.app.id]
  }
}

主要な設定項目の解説

設定項目説明重要度
engineデータベースエンジンの種類(MySQL, PostgreSQL等)必須
instance_classインスタンスタイプ(性能とコストに影響)必須
allocated_storageストレージサイズ(GB)必須
backup_retention_periodバックアップ保持期間(日数)推奨
multi_azマルチAZ配置の有効化推奨
storage_encryptedストレージの暗号化推奨

ベストプラクティス

  1. 命名規則の統一
  • 環境や用途を識別できる命名規則を採用
  • プレフィックスやサフィックスの一貫した使用
  1. モジュール化
  • 再利用可能なモジュールとしてRDS設定を管理
  • 環境差分はvariablesで吸収
  1. セキュリティ対策
  • IAMデータベース認証の活用
  • セキュリティグループの最小権限設定
  • ストレージ暗号化の有効化

実践的なRDS環境構築のためのTerraform実装例

基本的なRDSインスタンスの作成方法

基本的なRDS構成のコード例:

# プロバイダー設定
provider "aws" {
  region = "ap-northeast-1"
}

# VPC設定
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

  tags = {
    Name = "main"
  }
}

# サブネット設定
resource "aws_subnet" "private1" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a"
}

resource "aws_subnet" "private2" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.2.0/24"
  availability_zone = "ap-northeast-1c"
}

# RDSサブネットグループ
resource "aws_db_subnet_group" "main" {
  name       = "main"
  subnet_ids = [aws_subnet.private1.id, aws_subnet.private2.id]
}

# RDSインスタンス
resource "aws_db_instance" "main" {
  identifier        = "main-db"
  engine            = "mysql"
  engine_version    = "8.0.28"
  instance_class    = "db.t3.micro"
  allocated_storage = 20

  db_name  = "myappdb"
  username = "admin"
  password = var.db_password

  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.rds.id]

  skip_final_snapshot = true
}

マルチAZ構成の実装手順

高可用性を実現するマルチAZ構成:

resource "aws_db_instance" "main" {
  # 基本設定は前述と同じ

  multi_az               = true
  backup_retention_period = 7
  backup_window          = "03:00-04:00"
  maintenance_window     = "Mon:04:00-Mon:05:00"

  auto_minor_version_upgrade = true

  # パフォーマンス設定
  max_allocated_storage = 1000  # ストレージの自動スケーリング上限
  monitoring_interval   = 60    # 拡張モニタリング間隔
  monitoring_role_arn   = aws_iam_role.rds_monitoring.arn

  # 災害対策設定
  deletion_protection = true
}

バックアップとリストア設定の実装

自動バックアップと復元ポイントの設定:

# S3バケット(バックアップ保存用)
resource "aws_s3_bucket" "backup" {
  bucket = "my-rds-backup-bucket"
}

resource "aws_s3_bucket_public_access_block" "backup" {
  bucket = aws_s3_bucket.backup.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# RDSインスタンスの設定
resource "aws_db_instance" "main" {
  # 基本設定は前述と同じ

  backup_retention_period = 14
  backup_window          = "03:00-04:00"

  # スナップショット設定
  copy_tags_to_snapshot = true

  # 自動マイナーバージョンアップグレード
  auto_minor_version_upgrade = true

  # Performance Insights設定
  performance_insights_enabled = true
  performance_insights_retention_period = 7
}

# CloudWatchアラーム(バックアップ失敗検知用)
resource "aws_cloudwatch_metric_alarm" "backup_failed" {
  alarm_name          = "rds-backup-failed"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "1"
  metric_name         = "BackupFailed"
  namespace           = "AWS/RDS"
  period             = "300"
  statistic          = "Sum"
  threshold          = "0"

  dimensions = {
    DBInstanceIdentifier = aws_db_instance.main.id
  }

  alarm_description = "RDSバックアップ失敗を検知"
  alarm_actions     = [aws_sns_topic.alerts.arn]
}

リソース設定のポイント

設定項目推奨値説明
multi_aztrue本番環境では必須
backup_retention_period7-35日要件に応じて調整
deletion_protectiontrue本番環境では必須
monitoring_interval60秒標準的な監視間隔
performance_insights_enabledtrueパフォーマンス分析に有用

実装時の注意点

  1. リソース名の一意性
  • グローバルで一意なリソース名の使用
  • 環境識別子のプレフィックス付与
  1. セキュリティ設定
  • パスワードは変数化して管理
  • セキュリティグループの適切な設定
  • 暗号化の有効化
  1. コスト最適化
  • インスタンスサイズの適切な選択
  • 不要なバックアップの削除
  • 自動スケーリングの上限設定

セキュリティとパフォーマンスの最適化

IAMとセキュリティグループの適切な設定

# IAMロール
resource "aws_iam_role" "rds_monitoring" {
  name = "rds-monitoring-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "monitoring.rds.amazonaws.com"
        }
      }
    ]
  })
}

# セキュリティグループ
resource "aws_security_group" "rds" {
  name   = "rds-sg"
  vpc_id = aws_vpc.main.id

  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = [aws_security_group.app.id]
    description     = "Allow MySQL access from application"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  lifecycle {
    create_before_destroy = true
  }
}

# IAMデータベース認証の設定
resource "aws_db_instance" "main" {
  # 既存の設定に追加
  iam_database_authentication_enabled = true
}

暗号化オプションの実装方法

# KMSキー
resource "aws_kms_key" "rds" {
  description             = "KMS key for RDS encryption"
  deletion_window_in_days = 7
  enable_key_rotation     = true
}

resource "aws_kms_alias" "rds" {
  name          = "alias/rds-encryption"
  target_key_id = aws_kms_key.rds.key_id
}

# 暗号化設定付きRDSインスタンス
resource "aws_db_instance" "main" {
  # 既存の設定に追加
  storage_encrypted = true
  kms_key_id       = aws_kms_key.rds.arn

  # SSL接続の強制
  parameter_group_name = aws_db_parameter_group.main.name
}

# パラメータグループ(SSL強制)
resource "aws_db_parameter_group" "main" {
  family = "mysql8.0"

  parameter {
    name  = "require_secure_transport"
    value = "ON"
  }
}

パフォーマンスチューニングのベストプラクティス

# パフォーマンス最適化用パラメータグループ
resource "aws_db_parameter_group" "performance" {
  family = "mysql8.0"
  name   = "performance-optimized"

  parameter {
    name  = "innodb_buffer_pool_size"
    value = "{DBInstanceClassMemory*3/4}"
  }

  parameter {
    name  = "max_connections"
    value = "1000"
  }

  parameter {
    name  = "slow_query_log"
    value = "1"
  }

  parameter {
    name  = "long_query_time"
    value = "2"
  }
}

# パフォーマンスインサイト設定
resource "aws_db_instance" "main" {
  # 既存の設定に追加
  parameter_group_name               = aws_db_parameter_group.performance.name
  performance_insights_enabled       = true
  performance_insights_retention_period = 7
  monitoring_interval               = 60
  monitoring_role_arn              = aws_iam_role.rds_monitoring.arn

  # オートスケーリング設定
  max_allocated_storage            = 1000
}

セキュリティチェックリスト

項目実装方法重要度
ネットワーク分離プライベートサブネット配置必須
アクセス制御セキュリティグループ必須
データ暗号化KMS + storage_encrypted必須
通信暗号化SSL/TLS強制推奨
認証強化IAMデータベース認証推奨

パフォーマンス最適化ポイント

  1. インスタンスサイジング
  • ワークロードに適したインスタンスクラス選択
  • メモリとCPUの使用率監視
  1. ストレージ最適化
  • プロビジョンドIOPS使用判断
  • 自動スケーリング閾値設定
  1. 監視体制
  • Performance Insights活用
  • CloudWatchメトリクス設定
  • スロークエリログ分析

運用管理のための高度な設定

モニタリングとアラート設定の実装

# CloudWatchアラーム設定
resource "aws_cloudwatch_metric_alarm" "cpu_utilization" {
  alarm_name          = "rds-high-cpu"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/RDS"
  period             = "300"
  statistic          = "Average"
  threshold          = "80"

  dimensions = {
    DBInstanceIdentifier = aws_db_instance.main.id
  }

  alarm_actions = [aws_sns_topic.alerts.arn]
}

resource "aws_cloudwatch_metric_alarm" "free_storage" {
  alarm_name          = "rds-low-storage"
  comparison_operator = "LessThanThreshold"
  evaluation_periods  = "1"
  metric_name         = "FreeStorageSpace"
  namespace           = "AWS/RDS"
  period             = "300"
  statistic          = "Average"
  threshold          = "20000000000" # 20GB

  dimensions = {
    DBInstanceIdentifier = aws_db_instance.main.id
  }

  alarm_actions = [aws_sns_topic.alerts.arn]
}

# SNSトピック
resource "aws_sns_topic" "alerts" {
  name = "rds-alerts"
}

# CloudWatchログエクスポート
resource "aws_db_instance" "main" {
  # 既存の設定に追加
  enabled_cloudwatch_logs_exports = [
    "error",
    "general",
    "slowquery"
  ]
}

メンテナンスウィンドウとアップグレード戦略

# メンテナンス設定付きRDSインスタンス
resource "aws_db_instance" "main" {
  # 既存の設定に追加
  maintenance_window = "Mon:03:00-Mon:04:00"
  backup_window      = "02:00-03:00"

  auto_minor_version_upgrade = true
  allow_major_version_upgrade = false

  # ブルーグリーンデプロイメント用タグ
  tags = {
    Environment = var.environment
    Version     = var.db_version
  }
}

# メンテナンス期間中のアラート抑制
resource "aws_cloudwatch_metric_alarm" "cpu_utilization" {
  # 既存の設定に追加
  treat_missing_data = "ignore"

  tags = {
    MaintenanceWindow = "Mon:03:00-Mon:04:00"
  }
}

監視メトリクス一覧

メトリクス閾値アラート条件
CPUUtilization80%5分間で2回超過
FreeStorageSpace20GB即時アラート
DatabaseConnections接続上限の80%5分間で3回超過
ReadIOPS/WriteIOPSプロビジョン値の90%15分間で3回超過

メンテナンス計画のポイント

  1. アップグレード戦略
  • マイナーバージョン自動適用
  • メジャーバージョン手動適用
  • 事前テスト環境での検証
  1. メンテナンスウィンドウ設定
  • バックアップウィンドウとの重複回避
  • タイムゾーンを考慮した時間帯設定
  • 複数リージョンの考慮
  1. 運用自動化
  • 定期的なスナップショット取得
  • パラメータグループの変更管理
  • メトリクスベースの自動スケーリング

トラブルシューティングとベストプラクティス

よくある問題とその解決方法

  1. リソース作成失敗
# 問題:VPC設定の不備
resource "aws_db_instance" "main" {
  # 正しいVPC設定
  db_subnet_group_name = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.rds.id]

  # 可用性ゾーンの明示的指定
  availability_zone = "ap-northeast-1a"
}

# 解決策:サブネットグループの確認
resource "aws_db_subnet_group" "main" {
  name = "main"
  subnet_ids = [
    aws_subnet.private1.id,
    aws_subnet.private2.id
  ]

  tags = {
    Name = "Main DB subnet group"
  }
}
  1. パフォーマンス問題
# 監視設定の強化
resource "aws_cloudwatch_metric_alarm" "performance" {
  alarm_name          = "rds-performance-degradation"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "3"
  metric_name         = "ReadLatency"
  namespace           = "AWS/RDS"
  period             = "300"
  statistic          = "Average"
  threshold          = "0.01"

  dimensions = {
    DBInstanceIdentifier = aws_db_instance.main.id
  }

  alarm_actions = [aws_sns_topic.alerts.arn]
}

トラブルシューティングガイド

問題主な原因解決策
terraform apply失敗依存関係の不備依存リソースの明示的指定
接続エラーセキュリティグループ設定インバウンドルール確認
パフォーマンス低下リソース不足インスタンスクラス変更
バックアップ失敗ストレージ容量不足自動スケーリング設定

本番環境での運用ベストプラクティス

  1. 変更管理プロセス
# 変更履歴管理
resource "aws_db_instance" "main" {
  # バージョン管理タグ
  tags = {
    ManagedBy = "Terraform"
    Version   = var.infrastructure_version
    LastModified = timestamp()
  }

  # 意図しない変更防止
  lifecycle {
    prevent_destroy = true
    ignore_changes = [
      password,
      latest_restorable_time
    ]
  }
}
  1. セキュリティ強化
# セキュリティ設定
resource "aws_db_instance" "main" {
  # セキュリティベストプラクティス
  storage_encrypted = true
  deletion_protection = true
  skip_final_snapshot = false
  final_snapshot_identifier = "${var.environment}-final-snapshot"

  # IAM認証の有効化
  iam_database_authentication_enabled = true
}

本番環境チェックリスト

  1. デプロイメント前
  • 依存関係の確認
  • セキュリティ設定の検証
  • バックアップ戦略の確認
  1. 運用フェーズ
  • 監視体制の確立
  • 定期的な設定レビュー
  • パフォーマンス最適化
  1. メンテナンス計画
  • 計画的なバージョンアップ
  • パラメータ調整の影響確認
  • ダウンタイム最小化戦略

インフラストラクチャコード管理

# ステート管理
terraform {
  backend "s3" {
    bucket = "terraform-state-bucket"
    key    = "rds/production.tfstate"
    region = "ap-northeast-1"

    encrypt = true
    dynamodb_table = "terraform-locks"
  }
}

# 環境変数
variable "environment" {
  type = string
  description = "Environment name (e.g., prod, staging)"
}

locals {
  common_tags = {
    Environment = var.environment
    ManagedBy   = "Terraform"
    Project     = "RDS-Infrastructure"
  }
}