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"
}
}