Terraformを使用したRDS構築の基礎知識
Terraformとは
TerraformはHashiCorpが開発したインフラストラクチャ・アズ・コード(IaC)ツールです。AWSのRDSを含む各種リソースを、コードで宣言的に管理できます。
TerraformとRDSの関係性を理解する
TerraformでRDSを管理するメリット:
- インフラのバージョン管理: GitなどでRDS構成の変更履歴を追跡可能
- 環境の再現性: 本番/開発/検証環境を同じコードで構築可能
- 自動化: プロビジョニングや設定変更を自動化
- ドリフト検知: 手動変更された設定の検出が容易
Terraformで定義できるRDSの主要コンポーネント
- 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 }
- サブネットグループ
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" } }
- パラメータグループ
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" } }
- セキュリティグループ
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 | ストレージの暗号化 | 推奨 |
ベストプラクティス
- 命名規則の統一
- 環境や用途を識別できる命名規則を採用
- プレフィックスやサフィックスの一貫した使用
- モジュール化
- 再利用可能なモジュールとしてRDS設定を管理
- 環境差分はvariablesで吸収
- セキュリティ対策
- 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_az | true | 本番環境では必須 |
backup_retention_period | 7-35日 | 要件に応じて調整 |
deletion_protection | true | 本番環境では必須 |
monitoring_interval | 60秒 | 標準的な監視間隔 |
performance_insights_enabled | true | パフォーマンス分析に有用 |
実装時の注意点
- リソース名の一意性
- グローバルで一意なリソース名の使用
- 環境識別子のプレフィックス付与
- セキュリティ設定
- パスワードは変数化して管理
- セキュリティグループの適切な設定
- 暗号化の有効化
- コスト最適化
- インスタンスサイズの適切な選択
- 不要なバックアップの削除
- 自動スケーリングの上限設定
セキュリティとパフォーマンスの最適化
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データベース認証 | 推奨 |
パフォーマンス最適化ポイント
- インスタンスサイジング
- ワークロードに適したインスタンスクラス選択
- メモリとCPUの使用率監視
- ストレージ最適化
- プロビジョンドIOPS使用判断
- 自動スケーリング閾値設定
- 監視体制
- 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" } }
監視メトリクス一覧
メトリクス | 閾値 | アラート条件 |
---|---|---|
CPUUtilization | 80% | 5分間で2回超過 |
FreeStorageSpace | 20GB | 即時アラート |
DatabaseConnections | 接続上限の80% | 5分間で3回超過 |
ReadIOPS/WriteIOPS | プロビジョン値の90% | 15分間で3回超過 |
メンテナンス計画のポイント
- アップグレード戦略
- マイナーバージョン自動適用
- メジャーバージョン手動適用
- 事前テスト環境での検証
- メンテナンスウィンドウ設定
- バックアップウィンドウとの重複回避
- タイムゾーンを考慮した時間帯設定
- 複数リージョンの考慮
- 運用自動化
- 定期的なスナップショット取得
- パラメータグループの変更管理
- メトリクスベースの自動スケーリング
トラブルシューティングとベストプラクティス
よくある問題とその解決方法
- リソース作成失敗
# 問題: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" } }
- パフォーマンス問題
# 監視設定の強化 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失敗 | 依存関係の不備 | 依存リソースの明示的指定 |
接続エラー | セキュリティグループ設定 | インバウンドルール確認 |
パフォーマンス低下 | リソース不足 | インスタンスクラス変更 |
バックアップ失敗 | ストレージ容量不足 | 自動スケーリング設定 |
本番環境での運用ベストプラクティス
- 変更管理プロセス
# 変更履歴管理 resource "aws_db_instance" "main" { # バージョン管理タグ tags = { ManagedBy = "Terraform" Version = var.infrastructure_version LastModified = timestamp() } # 意図しない変更防止 lifecycle { prevent_destroy = true ignore_changes = [ password, latest_restorable_time ] } }
- セキュリティ強化
# セキュリティ設定 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 }
本番環境チェックリスト
- デプロイメント前
- 依存関係の確認
- セキュリティ設定の検証
- バックアップ戦略の確認
- 運用フェーズ
- 監視体制の確立
- 定期的な設定レビュー
- パフォーマンス最適化
- メンテナンス計画
- 計画的なバージョンアップ
- パラメータ調整の影響確認
- ダウンタイム最小化戦略
インフラストラクチャコード管理
# ステート管理 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" } }