はじめに
前提
RDS を構築する前に、ネットワーク環境(VPC,Subnet,Security Group)や、CloudWatch Logs にログを転送するための IAM Role などが必要です。
Terraform でインフラ構築するときは、その一つ一つのコンポーネントを理解しておく必要があります。
ただ、今回は RDS Oracle 構築の話を中心に書きたいと思いますので、周辺の説明はサンプルコードの記載に留めて省略していきたいと思います。
RDS Oracle 構築に必要なもの
RDS Oracle を構築するための resource は aws_db_instance です。
そして、この aws_db_instance を実行するために必要な要素をがこちらです。
- aws_db_subnet_group
- aws_security_group
- aws_iam_role
- aws_db_parameter_group
- aws_db_option_group
上記の一部はなくても default 設定が反映されるので構築は可能です。
まずは、これらのコンポーネントの作成方法から見ていきたいと思います。
準備
aws_db_subnet_group
db subnet を作成する前に、subnet を複数作成しておく必要がありますが、そこは省きたいと思います。
# DB Subnet
# https://www.terraform.io/docs/providers/aws/r/db_subnet_group.html
resource "aws_db_subnet_group" "db_subnet" {
name = "sample-db-subnet-gp"
subnet_ids = [
aws_subnet.subnet_rds.0.id, # 作成済みの subnet id を参照
aws_subnet.subnet_rds.1.id, # 作成済みの subnet id を参照
aws_subnet.subnet_rds.2.id # 作成済みの subnet id を参照
]
tags = {
Service = "sample"
}
}
aws_security_group
セキュリティ要件によってはアウトバウンド通信の制御も必要でしょう。今回はインバウンド通信だけ制限します。
# Security Group
# https://www.terraform.io/docs/providers/aws/r/security_group.html
resource "aws_security_group" "rds_sg" {
name = "sample-rds-sg"
description = "sample rds security group"
vpc_id = aws_vpc.vpc.id # 作成済みの vpc id を参照
# 許可するインバウンド通信を記載
ingress {
description = "Oracle"
from_port = 1521
to_port = 1521
protocol = "tcp"
security_groups = [
aws_security_group.public_sg.id # list 形式で記載, public subnet id を参照
]
}
# 許可するアウトバウンド通信を記載
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "sample-rds-sg"
Service = "sample"
}
}
aws_iam_role
コンソールで RDS を作成した際には、AWS RDS がログを CloudWatch Logs に転送する設定を選択すると、専用のサービスロール(AmazonRDSEnhancedMonitoringRole )が自動的に RDS にセットされています。
これも Terraform の管理対象に含めるために、以下のロールを作成します。
# aws_iam_role
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "rds_monitoring_role" {
name = "sample-rds-monitoring-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "monitoring.rds.amazonaws.com"
},
"Effect": "Allow"
}
]
}
EOF
tags = {
Name = "sample-rds-monitoring-role"
Service = "sample"
}
}
# aws_iam_policy_attachment
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment
resource "aws_iam_policy_attachment" "rds_monitoring_policy_attachment" {
name = "rds_monitoring_policy_attachment"
roles = [aws_iam_role.rds_monitoring_role.name] # list
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
}
ポイントは、AssumeRole を "monitoring.rds.amazonaws.com" とすることです。 "rds.amazonaws.com" ではありません。
詳細はこちらの issues を参照ください。
aws_db_parameter_group
何も設定しないのは寂しいので監査設定を入れておきます。
# aws_db_parameter_group
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group
resource "aws_db_parameter_group" "rds_oracle_pg" {
name = "sample-rds-oracle-pg"
family = "oracle-se2-19"
parameter {
name = "audit_trail"
value = "DB,EXTENDED"
apply_method = "pending-reboot"
}
tags = {
Service = "sample"
}
}
aws_db_option_group
タイムゾーンを東京にしておきます。
# aws_db_option_group
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_option_group
resource "aws_db_option_group" "rds_oracle_opg" {
name = "sample-rds-oracle-opg"
engine_name = "oracle-se2"
major_engine_version = 19
option {
option_name = "Timezone"
option_settings {
name = "TIME_ZONE"
value = "Asia/Tokyo"
}
}
tags = {
Service = "sample"
}
}
RDS Oracle 構築
aws_db_instance
Terraform で迷うところが、エンジンバージョンなどの記載方法です。少しでも間違えると、そんなバージョンありません、というエラーが出てしまいます。
なるべく全ての項目を指定する形で作成しました。
# aws_db_instance
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/db_instance
resource "aws_db_instance" "rds_oracle_instance" {
identifier = "sample-oracle"
instance_class = "db.r5.large"
engine = "oracle-se2"
engine_version = "19.0.0.0.ru-2019-07.rur-2019-07.r1"
license_model = "license-included"
multi_az = false # default false
name = "SAMPLEDB" # must be upper, default ORCL
username = "xxxxxx"
password = "xxxxxxxxxxxx"
# storage
storage_type = "gp2" # The default is "io1"
allocated_storage = 20 # depends on storage_type
max_allocated_storage = 1000 # 0 to disable Storage Autoscaling.
storage_encrypted = true # declare KMS key ARN if true, default false
# kms_key_id = "" # set KMS ARN, default "aws/rds"
# network
db_subnet_group_name = aws_db_subnet_group.db_subnet.name
vpc_security_group_ids = [aws_security_group.private_sg.id]
port = 1521
# monitoring
performance_insights_enabled = false # default false
monitoring_interval = 60 # 0, 1, 5, 10, 15, 30, 60 (seconds). default 0 (off)
monitoring_role_arn = aws_iam_role.rds_monitoring_role.arn
enabled_cloudwatch_logs_exports = ["alert", "audit", "listener", "trace"]
# backup snapshot
backup_retention_period = 0 # default 7 (days). 0 = disabled.
backup_window = "01:00-01:30" # must not overlap with maintenance_window.
copy_tags_to_snapshot = true # default false
delete_automated_backups = true # default true
deletion_protection = false # default false
skip_final_snapshot = true # default false
# final_snapshot_identifier = "" # must be provided if skip_final_snapshot is set to false.
# options
parameter_group_name = aws_db_parameter_group.rds_oracle_pg.name
option_group_name = aws_db_option_group.rds_oracle_opg.name
character_set_name = "UTF8" # Oracle and Microsoft SQL
auto_minor_version_upgrade = false # default true
maintenance_window = "Mon:02:00-Mon:03:00"
# tags
tags = {
Service = "sample"
}
}
データベース名は大文字で
リソースを作成した後に、パラメータを変更したり、オプションを変更したりといったことはよくありますね。
そこで注意しなければいけないことが、データベース名の文字です。小文字で書いてしまうと、毎回リソースを destroy してから、再度 create する挙動になってしまいます。
データベース名を大文字で書いておけば destroy してから、再度 create する挙動とはなりません。
原因は、Terafform と Oracle の相互の仕様によるものと思われますが、直接ソースを見たわけではないので私も詳しくは分かりません。
バックアップの保持期間(backup_retention_period)は慎重に
上記のコードでは、backup_retention_period = 0 としています。理由は、すぐにリソースを削除できるようにするためです。
本番用では要件に合わせてバックアップの保持期間(backup_retention_period)を設定すべきです。
ただ、検証等で使う場合はすぐに削除してしまうこともあるかと思います。
気を付けなければいけないのは、※RDS Oracle の自動スナップショットはオプショングループと紐づけられるという仕様です。
自動スナップショットが存在する限り、オプショングループは使用中となり削除できなくなります。
つまり、バックアップの保持期間(backup_retention_period)を 1 以上に設定しておくと、バックアップのスナップショットが自動で作成されてしまい、オプショングループの削除が出来なくなってしまう罠に陥る場合があります。
自動スナップショットが時間の経過とともに削除されれば、オプショングループも削除できるようになります。
terraform apply
実行してみます。
PS C:\Users\...\terraform_aws> terraform apply
Plan: 5 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
実行結果を確認
実行結果をコンソールで確認してみます。
一通り確認することができました。
以上です。
OracleTerraformRDS