前提
Aurora PostgreSQL を構築する前に、ネットワーク環境(VPC,Subnet,Security Group)や、CloudWatch Logs にログを転送するための IAM Role などが必要です。
Terraform でインフラ構築するときは、その一つ一つのコンポーネントを理解しておく必要があります。
ただ、今回は Aurora PostgreSQL 構築の話を中心に書きたいと思いますので、周辺の説明はサンプルコードの記載に留めて省略していきたいと思います。
Aurora PostgreSQL に必要なもの
Aurora PostgreSQL を構築するために必要な resource は aws_rds_cluster と aws_rds_cluster_instance です。
そして、それらを実行するために必要な resource をがこちらです。
- aws_db_subnet_group
- aws_security_group
- aws_iam_role
- aws_rds_cluster_parameter_group
- aws_db_parameter_group
AWS は親切なので default で "よろしく" やってくれるところがありますが、それでは現場で通用しませんので、1つ1つ設定していきたいと思います。
準備
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 = "PostgreSQL"
from_port = 5432
to_port = 5432
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 を作成した際には、ログを CloudWatch Logs に転送する設定を選択すると、専用のサービスロール(AmazonRDSEnhancedMonitoringRole )が自動的にセットされています。
これも 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_rds_cluster_parameter_group
監査設定、hint句、ロケール(国際化と地域化)の設定を入れておきます。
# aws_rds_cluster_parameter_group
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group
resource "aws_rds_cluster_parameter_group" "aurora_postgre_cpg" {
name = "sample-aurora-postgre-cpg"
family = "aurora-postgresql11"
tags = {
Service = "sample"
}
# install libraries
parameter {
name = "shared_preload_libraries"
value = "pg_stat_statements ,pg_hint_plan ,pgaudit"
apply_method = "pending-reboot"
}
# audit setting
parameter {
name = "pgaudit.log_catalog"
value = true
apply_method = "immediate"
}
parameter {
name = "pgaudit.log_parameter"
value = true
apply_method = "immediate"
}
parameter {
name = "pgaudit.log_relation"
value = true
apply_method = "immediate"
}
parameter {
name = "pgaudit.log_statement_once"
value = true
apply_method = "immediate"
}
parameter {
name = "pgaudit.log"
value = "ddl ,misc ,role"
apply_method = "immediate"
}
parameter {
name = "pgaudit.role"
value = "rds_pgaudit"
apply_method = "immediate"
}
# no local
parameter {
name = "lc_messages"
value = "C"
apply_method = "immediate"
}
parameter {
name = "lc_monetary"
value = "C"
apply_method = "immediate"
}
parameter {
name = "lc_numeric"
value = "C"
apply_method = "immediate"
}
parameter {
name = "lc_time"
value = "C"
apply_method = "immediate"
}
}
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" "aurora_postgre_pg" {
name = "sample-aurora-postgre-pg"
family = "aurora-postgresql11"
tags = {
Service = "sample"
}
}
Aurora PostgreSQL 構築
aws_rds_cluster
まずは、クラスターを構築します。
# aws_rds_cluster
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster
resource "aws_rds_cluster" "aurora_postgre_cls" {
cluster_identifier = "sample-aurora-postgre-cls"
engine = "aurora-postgresql"
engine_version = "11.7"
engine_mode = "provisioned" # global,multimaster,parallelquery,serverless, default provisioned
database_name = "testdb01"
master_username = "xxxxxxx"
master_password = "xxxxxxxxxxx"
# storage
storage_encrypted = true # declare KMS key ARN if true, default false
# kms_key_id = "" # set KMS ARN if storage_encrypted is true, default "aws/rds"
# network
db_subnet_group_name = aws_db_subnet_group.db_subnet.name
vpc_security_group_ids = [aws_security_group.rds_sg.id]
port = 5432
# backup snapshot
backup_retention_period = 1 # must be between 1 and 35. default 1 (days)
copy_tags_to_snapshot = true # default false
deletion_protection = false # default false
skip_final_snapshot = true # default false
final_snapshot_identifier = "sample-aurora-postgre" # must be provided if skip_final_snapshot is set to false.
# monitoring
enabled_cloudwatch_logs_exports = ["postgresql"]
# backup window
preferred_backup_window = "02:00-02:30"
# options
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora_postgre_cpg.name
# tags
tags = {
Service = "sample"
}
}
aws_rds_cluster_instance
クラスターにインスタンスを追加します。count でインスタンスの数を調整できるようにしています。
# aws_rds_cluster_instance
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance
resource "aws_rds_cluster_instance" "aurora_postgre_instance" {
count = 2
identifier = "sample-aurora-postgre-${count.index}"
cluster_identifier = aws_rds_cluster.aurora_postgre_cls.cluster_identifier
instance_class = "db.r5.large"
engine = "aurora-postgresql"
engine_version = "11.7"
# netowrok
#availability_zone = "" # eu-west-1a,eu-west-1b,eu-west-1c
# 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.monitoring_role.arn
# maintenance window
preferred_maintenance_window = "Mon:03:00-Mon:04:00"
# options
db_parameter_group_name = aws_db_parameter_group.aurora_postgre_pg.name
auto_minor_version_upgrade = false
# tags
tags = {
Service = "sample"
}
}
注意ポイント① preferred_backup_window
preferred_backup_window は aws_rds_cluster 側で設定します。
preferred_backup_window を aws_rds_cluster_instance 側で設定しようとすると以下のエラーが発生します。
Error: error creating RDS DB Instance: InvalidParameterCombination: The requested DB Instance will be a member of a DB Cluster. Set backup window for the DB Cluster.
status code: 400, request id: 21428a77-42e2-41d0-923f-7fff91186f32
on sample_aurora_postgresql.tf line 206, in resource "aws_rds_cluster_instance" "aurora_postgre_instance":
206: resource "aws_rds_cluster_instance" "aurora_postgre_instance" {
preferred_backup_window は クラスター側、インスタンス側、どちらでも設定が可能です。
注意ポイント② ネットワーク
データベースのネットワーク設計では、AZ(アベイラビリティゾーン)を指定したい場合がありますね。
そんな時は、クラスター側でサブネットを設定して、インスタンス側でAZ(アベイラビリティゾーン)を指定すること、分かりやすいかなと思います。
terraform apply
実行してみます。
PS C:\Users\...\terraform_aws> terraform apply
Plan: 8 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: 8 added, 0 changed, 0 destroyed.
実行結果を確認
実行結果をコンソールで確認してみます。
上手く作成できました。以上です。
PostgreSQLTerraformRDS