前提
Aurora PostgreSQL を構築する前に、ネットワーク環境(VPC,Subnet,Security Group)や、CloudWatch Logs にログを転送するための IAM Role などが必要です。
Terraform でインフラ構築するときは、その一つ一つのコンポーネントを理解しておく必要があります。
ただ、今回は RDS SQLServer 構築の話を中心に書きたいと思いますので、周辺の説明はサンプルコードの記載に留めて省略していきたいと思います。
Aurora PostgreSQL に必要なもの
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
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 = "SQLServer"
from_port = 1433
to_port = 1433
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" "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" ではありません。
今回は監査設定も入れますので S3 へ監査ログを転送するためのロールも作成します。
# rds_role
resource "aws_iam_role" "rds_role" {
name = "rds-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "rds.amazonaws.com"
},
"Effect": "Allow"
}
]
}
EOF
tags = {
Name = "sample-rds-role"
Service = "sample"
}
}
resource "aws_iam_policy_attachment" "rds_policy_1_attachment" {
name = "rds_policy_1_attachment"
roles = [aws_iam_role.rds_role.name]
policy_arn = aws_iam_policy.rds_policy_1.arn
}
# aws_iam_policy
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy
# https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.SQLServer.Options.Audit.html
# https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/SQLServer.Procedural.Importing.html
resource "aws_iam_policy" "rds_policy_1" {
name = "rds_policy_1"
path = "/"
description = "rds_policy_1"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:PutObject",
"s3:GetObject",
"S3:GetBucketAcl",
"s3:GetBucketLocation",
"s3:GetObjectMetaData",
"s3:ListMultipartUploadParts",
"s3:AbortMultipartUpload"
],
"Resource": "*"
}
]
}
EOF
}
aws_db_parameter_group
SQLServer にはあまり詳しくないため、パラメータグループは特に設定はなしとしておきます。
# aws_db_parameter_group
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group
resource "aws_db_parameter_group" "rds_sqlserver_pg" {
name = "sample-rds-sqlserver-pg"
family = "sqlserver-se-14.0"
tags = {
Service = "sample"
}
}
aws_db_option_group
3つのオプションを設定します。
# aws_db_option_group
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_option_group
resource "aws_db_option_group" "rds_sqlserver_opg" {
name = "sample-rds-sqlserver-opg"
engine_name = "sqlserver-se"
major_engine_version = "14.00"
option {
option_name = "Timezone"
option_settings {
name = "TIME_ZONE"
value = "Tokyo_Standard_Time"
}
}
option {
option_name = "SQLSERVER_BACKUP_RESTORE"
option_settings {
name = "IAM_ROLE_ARN"
value = aws_iam_role.rds_role.arn
}
}
option {
option_name = "SQLSERVER_AUDIT"
option_settings {
name = "ENABLE_COMPRESSION"
value = true
}
option_settings {
name = "S3_BUCKET_ARN"
value = "arn:aws:s3:::koizumi-logs"
}
option_settings {
name = "IAM_ROLE_ARN"
value = aws_iam_role.rds_role.arn
}
option_settings {
name = "RETENTION_TIME"
value = 0
}
}
tags = {
Service = "sample"
}
}
RDS SQLServer 構築
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_sqlserver_instance" {
identifier = "sample-sqlserver"
instance_class = "db.r5.large"
engine = "sqlserver-se"
engine_version = "14.00.3281.6.v1"
license_model = "license-included"
multi_az = false # default false
username = "xxxxx"
password = "xxxxxxxxxx"
# storage
storage_type = "gp2" # The default is "io1", "gp2", "standard" (magnetic)
allocated_storage = 20 # depends on storage_type
max_allocated_storage = 1000 # Must be greater than or equal to allocated_storage or 0 to disable Storage Autoscaling.
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.private_sg.id]
port = 1433
# 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
enabled_cloudwatch_logs_exports = ["agent", "error"]
# backup snapshot
backup_retention_period = 0 # default 7 (days). 0 = disabled.
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 = "sample-sqlserver-snapshot" # must be provided if skip_final_snapshot is set to false.
# window time
backup_window = "01:00-01:30"
maintenance_window = "Mon:02:00-Mon:03:00"
# options
parameter_group_name = aws_db_parameter_group.rds_sqlserver_pg.name
option_group_name = aws_db_option_group.rds_sqlserver_opg.name
character_set_name = "Japanese_CI_AS" # Oracle and Microsoft SQL
timezone = "Tokyo Standard Time" # only SQLServer
auto_minor_version_upgrade = false # default true
# tags
tags = {
Service = "sample"
}
}
terraform apply
実行してみます。
PS C:\Users\...\terraform_aws> terraform apply
Plan: 10 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: 10 added, 0 changed, 0 destroyed.
実行結果を確認
実行結果をコンソールで確認してみます。
一通り確認することができました。
以上です。
TerraformRDSSQLServer