Skip to main content
  1. 記事一覧/

TerraformでAmazon RDS for Oracleを構築するサンプルコードを書いてみた

··5 mins

みなさん、こんにちは。今回はTerraformの入門ということでAmazon RDS for Oracleのサンプルコードを書いてみましたのでこちらを紹介していきたいと思います。

なお、サンプルコードを書いた際のTerraformおよびAWSプロバイダーのバージョンは次のとおりです。最新バージョンでは定義方法が異なっている可能性があるため、実際にコードを書く際は最新の「Terraformドキュメント」と「AWSプロバイダードキュメント」を確認しながら開発を進めていただければと思います。

例)versions.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Requirements
terraform {
  required_version = "~> 1.3.6"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.55.0"
    }
  }
}

サンプルコードを書いてみた #

今回は次のような構成のサンプルコードを書いてみました。なお、変数定義部分などの一部省略している点、ならびにステップごとの細かい説明などは省いていますのでご承知おきください。詳細については「AWSプロバイダードキュメント」をご参照ください。

ちなみに、すべてのサンプルコードに共通してプロバイダー定義は次のようにしています。

例)providers.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# デフォルトのプロバイダー設定
provider "aws" {
  region = var.aws_region
  default_tags {
    tags = {
      Owner     = "matt"
      Terraform = "true"
    }
  }
}

例1. RDSサブネットグループの作成 #

RDSサブネットグループの実装例で、こちらについては特筆すべき点はとくにないと思います。

例)main.tf

1
2
3
4
5
6
7
8
9
# RDSサブネットグループの定義
resource "aws_db_subnet_group" "this" {
  name       = var.rds_subnet_group_name
  subnet_ids = [for x in data.aws_subnet.private : x.id]

  tags = {
    Name = var.rds_subnet_group_name
  }
}

例)data.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# VPC情報の取得
data "aws_vpc" "this" {
  cidr_block = var.vpc_cidr_block
}

# サブネット情報の取得
data "aws_subnet" "private" {
  for_each = var.private_subnets

  vpc_id            = data.aws_vpc.default.id
  availability_zone = each.value.availability_zone
  cidr_block        = each.value.cidr_block
}

例2. RDSパラメータグループの作成 #

RDSパラメータグループの実装例で、定義するパラメータの個数などは環境によってマチマチだと思いますので、変数側で調整できるようにdynamicブロックを使って動的に定義しています。

例)main.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# RDSパラメータグループの定義
resource "aws_db_parameter_group" "this" {
  name   = var.rds_parameter_group_name
  family = var.rds_engine_family

  dynamic "parameter" {
    for_each = var.rds_parameters
    content {
      name         = parameter.value.name
      value        = parameter.value.value
      apply_method = parameter.value.apply_method
    }
  }

  tags = {
    Name = var.rds_parameter_group_name
  }
}

例)variables.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# RDSパラメータ一覧
variable "rds_parameters" {
  type    = map(any)
  default = {
    audit_trail = {
      name         = "audit_trail"
      value        = "DB,EXTENDED"
      apply_method = "pending-reboot"
    }
  }
}

例3. RDSオプショングループの作成 #

RDSオプショングループの実装例で、タイムゾーンの設定とS3統合の設定だけしています。S3統合を有効にしているのは、なんとなくDATA PUMPを使って手軽にエクスポート/インポートをしたいケースもあるかな、と思って有効にしています。

例)main.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# RDSオプショングループの定義
resource "aws_db_option_group" "this" {
  name                 = var.rds_option_group_name
  engine_name          = var.rds_engine
  major_engine_version = var.rds_engine_major_version

  option {
    option_name = "Timezone"

    option_settings {
      name  = "TIME_ZONE"
      value = "Asia/Tokyo"
    }
  }

  option {
    option_name = "S3_INTEGRATION"
    version     = "1.0"
  }

  tags = {
    Name = var.rds_option_group_name
  }
}

例4. RDSインスタンスの作成 #

RDSインスタンスの実装例で、モニタリング用やS3統合用のIAMロールの定義なども併せて記載しています。

なお、マスターユーザ/パスワード情報はSecrets Managerで管理というケースが最近は多くなってきていると思いますが、今回の例ではパスワード情報はプロジェクト管理とし、ここではあくまで構築用の初期パスワードという扱いでSSMパラメータストアにSecureStingとして事前に格納しておいた情報を扱うようにしています。

例)main.tf

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# RDSインスタンスの定義
resource "aws_db_instance" "this" {
  identifier               = var.rds_instance_name
  instance_class           = var.rds_instance_class
  engine                   = var.rds_engine
  engine_version           = var.rds_engine_version
  license_model            = "license-included"
  multi_az                 = var.rds_malti_az
  username                 = data.aws_ssm_parameter.rds_master_username.value
  password                 = data.aws_ssm_parameter.rds_master_password.value
  parameter_group_name     = aws_db_parameter_group.this.name
  option_group_name        = aws_db_option_group.this.name

  # storage
  storage_type          = var.rds_storage_type
  allocated_storage     = var.rds_allocated_storage
  max_allocated_storage = var.rds_max_allocated_storage
  storage_encrypted     = true
  kms_key_id            = data.aws_kms_key.this.arn

  # network
  db_subnet_group_name   = aws_db_subnet_group.this.name
  vpc_security_group_ids = [aws_security_group.this.id]
  port                   = var.rds_port

  # monitoring
  monitoring_interval                   = var.rds_monitoring_interval
  monitoring_role_arn                   = aws_iam_role.monitoring.arn
  performance_insights_enabled          = true
  performance_insights_kms_key_id       = data.aws_kms_key.this.arn
  performance_insights_retention_period = var.rds_performance_insights_retention_period

  # backup
  backup_retention_period  = var.rds_backup_retention_period
  backup_window            = var.rds_backup_window
  copy_tags_to_snapshot    = true
  delete_automated_backups = true
  deletion_protection      = false
  skip_final_snapshot      = true

  # maintenance
  maintenance_window         = var.rds_maintenance_windows
  auto_minor_version_upgrade = false
  publicly_accessible        = false
  apply_immediately          = true

  lifecycle {
    ignore_changes = [password]
  }

  tags = {
    Name = var.rds_instance_name
  }
}

# 空のセキュリティグループの定義
resource "aws_security_group" "this" {
  name   = var.security_group_name
  vpc_id = data.aws_vpc.this.id

  tags = {
    Name = var.security_group_name
  }

  lifecycle {
    create_before_destroy = true
  }
}

# モニタリング用のIAMロール定義
resource "aws_iam_role" "monitoring" {
  name = var.monitoring_role_name

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

  tags = {
    Name = monitoring_role_name
  }
}

# モニタリング用のIAMロールへのポリシー追加
resource "aws_iam_role_policy_attachment" "this" {
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
  role       = aws_iam_role.monitoring.name
}

# S3統合用のIAMロール定義
resource "aws_iam_role" "s3_integration" {
  name = var.iam_s3integration_role_name

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

  tags = {
    Name = var.iam_s3integration_role_name
  }
}

# S3統合用のIAMポリシー定義
resource "aws_iam_policy" "s3integration" {
  name = var.iam_s3integration_policy_name
  path = "/"

  policy = jsonencode({
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
          "s3:ListBucket",
          "s3:GetObject",
          "s3:PutObject",
          "s3:DeleteObject",
          "s3:PutObjectAcl"
        ],
        "Resource": [
          "${data.aws_s3_bucket.s3_integration.arn}",
          "${data.aws_s3_bucket.s3_integration.arn}/*"
        ]
      },
      {
        "Effect": "Allow",
        "Action": [
          "kms:Encrypt",
          "kms:ReEncrypt*",
          "kms:Decrypt",
          "kms:DescribeKey",
          "kms:GenerateDataKey"
        ],
        "Resource": [
          "${data.aws_kms_key.this.arn}"
        ]
      }
    ]
  })

  tags = {
    Name = var.iam_s3integration_policy_name
  }
}

# S3統合用IAMロールにIAMポリシーを割り当て
resource "aws_iam_role_policy_attachment" "s3_integration" {
  policy_arn = aws_iam_policy.s3_integration.arn
  role       = aws_iam_role.s3_integration.name
}

# RDBインスタンスにS3統合用のIAMロールの割り当て
resource "aws_db_instance_role_association" "s3_integration" {
  db_instance_identifier = aws_db_instance.this.id
  feature_name           = "S3_INTEGRATION"
  role_arn               = aws_iam_role.s3_integration.arn
}

例)data.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# VPC情報の取得
data "aws_vpc" "this" {
  cidr_block = var.vpc_cidr_block
}

# SSMパラメータ情報の取得(管理ユーザ名)
data "aws_ssm_parameter" "rds_master_username" {
  name = var.ssm_parameters.rds_master_username.name
}

# SSMパラメータ情報の取得(管理ユーザの初期パスワード)
data "aws_ssm_parameter" "rds_master_password" {
  name = var.ssm_parameters.rds_master_password.name
}

# 暗号鍵情報の取得
data "aws_kms_key" "this" {
  key_id = var.kms_key_alias_name
}

# S3統合用S3バケット情報の取得
data "aws_s3_bucket" "s3_integration" {
  bucket = var.s3_bucket_name
}

例)outputs.tf

1
2
3
4
output "security_group_id" {
  description = "The ID of the security group"
  value       = try(aws_security_group.this.id, "")
}

終わりに #

今回はTerraformの入門ということで、Amazon RDS for Oracleのサンプルコードをいくつかご紹介してきましたがいかがだったでしょうか。こんな記事でも誰かの役に立っていただけるのであれば幸いです。

なお、今回ご紹介したコードはあくまでサンプルであり、動作を保証するものではございません。そのまま使用したことによって発生したトラブルなどについては一切責任を負うことはできませんのでご注意ください。


  • AWS は、米国その他の諸国における Amazon.com, Inc. またはその関連会社の商標です。
  • Terraform は、HashiCorp, Inc. の米国およびその他の国における商標または登録商標です。
  • その他、記載されている会社名および商品・製品・サービス名は、各社の商標または登録商標です。