[Terraform]Aurora MySQLのログ出力先ログクラスをInfrequent Accessにしてみた

[Terraform]Aurora MySQLのログ出力先ログクラスをInfrequent Accessにしてみた

Clock Icon2024.10.29

はじめに

コンサルティング部の神野です。
Aurora MySQLからCloudWatchに出力されるログクラスをInfrequent Accessとし、
コストを抑えたいケースなどがあるかと思います。
本記事では、Infrequent Accessとして出力する設定をTerraformで実装する方法を紹介します。

Infrequent Accessについて

通常のログクラスよりもデータ転送料が安いログクラスとなります。詳細は下記記事をご参照いただくのがいいかと思います。

https://dev.classmethod.jp/articles/amazon-cloudwatch-logs-infrequent-access-log-class/

前提

今回はMySQL Auroraを使用し、エンジンバージョンは下記の通りです。

DBエンジン種類 エンジンバージョン
Aurora(MySQL) 8.0.mysql_aurora.3.07.1

構築

今回はTerraformで構築していきます。
main.tfファイルを作成し、作成するリソースについて記載します。

前提

Terraformを使用するため事前にインストールが必要になります。
使用したバージョンは下記となります。

  • Terraform・・・v1.9.4(provider registry.terraform.io/hashicorp/aws v5.61.0)

変数

クラスターのDB識別子cluster_identifierのみ変数化します。理由は、ロググループの作成およびAurora作成の両方でこの名称を使用するため、外出ししておきます。

main.tf
# 変数の設定
locals {
  cluster_identifier = "infrequent_logs_aurora_cluster"
}

ロググループ

  • Auroraで出力するエラーログ、一般ログ、スリークエリログ、監査ログ全てに対応するためfor_eachでそれぞれのロググループを作成します。
  • log_group_classは低頻度アクセス用のログクラスであるINFREQUENT_ACCESSを指定します。
  • それぞれのロググループ名を/aws/rds/cluster/<クラスター名>/ログ種別となるように命名しておきます。
main.tf
resource "aws_cloudwatch_log_group" "aurora_logs" {
  for_each = toset(["error", "general", "slowquery", "audit"])

  name              = "/aws/rds/cluster/${local.cluster_identifier}/${each.key}"
  retention_in_days = 7
  log_group_class   = "INFREQUENT_ACCESS"
}

VPC・ネットワーク

RDSを配置するVPCやサブネット、サブネットグループ、セキュリティグループを作成します。

main.tf
# プライベートサブネットの作成(RDS用)
resource "aws_subnet" "private1a" {
  vpc_id            = aws_vpc.this.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a"
}

resource "aws_subnet" "private1c" {
  vpc_id            = aws_vpc.this.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "ap-northeast-1c"
}

# DBのセキュリティグループ
resource "aws_security_group" "aurora" {
  name        = "aurora-security-group"
  description = "Security group for Aurora cluster"
  vpc_id      = aws_vpc.this.id

  # VPC内からの接続を許可(MySQL/Aurora用のポート3306)
  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = [aws_vpc.this.cidr_block]
  }

  # アウトバウンドトラフィックを全て許可
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "aurora-sg"
  }
}

# Auroraを配置するサブネットグループ
resource "aws_db_subnet_group" "aurora" {
  name       = "aurora-subnet-group"
  subnet_ids = [aws_subnet.private1a.id, aws_subnet.private1c.id]
}

RDS

監査ログや一般ログ、スロークエリログを有効にする設定を入れておきます。

クラスターパラメータグループの設定

監査ログの設定を有効化します。server_audit_logging1(有効)、server_audit_eventsCONNECT,QUERY,TABLE(有効にするイベント)とします。

main.tf
# クラスターパラメータグループ(監査ログ用)
resource "aws_rds_cluster_parameter_group" "this" {
  family = "aurora-mysql8.0"
  name   = "aurora-mysql80-cluster-custom-params"

  parameter {
    name  = "server_audit_logging"
    value = "1"
  }

  parameter {
    name  = "server_audit_events"
    value = "CONNECT,QUERY,TABLE"
  }
}

インスタンスパラメータグループの設定

一般ログ・スロークエリログの設定を有効化します。
スリークエリログはslow_query_log1(有効)、long_query_time2(閾値の秒数)に設定し、
一般ログはgeneral_log1(有効)を選択します。

main.tf
# インスタンスパラメータグループ(一般ログ、スロークエリログ用)
resource "aws_db_parameter_group" "this" {
  family = "aurora-mysql8.0"
  name   = "aurora-mysql80-instance-custom-params"

  parameter {
    name  = "slow_query_log"
    value = "1"
  }

  parameter {
    name  = "long_query_time"
    value = "2"
  }

  parameter {
    name  = "general_log"
    value = "1"
  }
}

RDSの設定

クラスターとインスタンスの作成を行います。
クラスターの設定では、enabled_cloudwatch_logs_exports"error", "general", "slowquery", "audit"として全てのログを有効化しておきます。

main.tf
# クラスター
resource "aws_rds_cluster" "aurora" {
  cluster_identifier              = local.cluster_identifier
  engine                          = "aurora-mysql"
  engine_version                  = "8.0.mysql_aurora.3.07.1"
  master_username                 = "admin"
  # パスワードは修正ください
  master_password                 = "XXX"
  backup_retention_period         = 5
  preferred_backup_window         = "07:00-09:00"
  db_subnet_group_name            = aws_db_subnet_group.aurora.name
  db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora.name

  enabled_cloudwatch_logs_exports = ["error", "general", "slowquery", "audit"]

}

# インスタンス
resource "aws_rds_cluster_instance" "aurora" {
  identifier         = "myaurorainstance"
  cluster_identifier = aws_rds_cluster.aurora.id
  instance_class     = "db.t3.medium"
  engine             = aws_rds_cluster.aurora.engine
  engine_version     = aws_rds_cluster.aurora.engine_version

  db_parameter_group_name = aws_db_parameter_group.aurora.name
}

実行

コードが書けたところで問題なく作成できるかplanコマンドを実行して確認します。

planコマンド

実行コマンド
terraform plan

plan結果

planコマンド上は問題なく作成されそうですね。
applyコマンドも実行します。

plan結果(長いので省略しています)
結果コマンド
terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # aws_cloudwatch_log_group.aurora_logs["audit"] will be created
  + resource "aws_cloudwatch_log_group" "aurora_logs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = "INFREQUENT_ACCESS"
      + name              = "/aws/rds/cluster/infrequentlogsauroracluster/audit"
      + name_prefix       = (known after apply)
      + retention_in_days = 7
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.aurora_logs["error"] will be created
  + resource "aws_cloudwatch_log_group" "aurora_logs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = "INFREQUENT_ACCESS"
      + name              = "/aws/rds/cluster/infrequentlogsauroracluster/error"
      + name_prefix       = (known after apply)
      + retention_in_days = 7
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.aurora_logs["general"] will be created
  + resource "aws_cloudwatch_log_group" "aurora_logs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = "INFREQUENT_ACCESS"
      + name              = "/aws/rds/cluster/infrequentlogsauroracluster/general"
      + name_prefix       = (known after apply)
      + retention_in_days = 7
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.aurora_logs["slowquery"] will be created
  + resource "aws_cloudwatch_log_group" "aurora_logs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = "INFREQUENT_ACCESS"
      + name              = "/aws/rds/cluster/infrequentlogsauroracluster/slowquery"
      + name_prefix       = (known after apply)
      + retention_in_days = 7
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_db_parameter_group.aurora will be created
  + resource "aws_db_parameter_group" "aurora" {
      + arn         = (known after apply)
      + description = "Managed by Terraform"
      + family      = "aurora-mysql8.0"
      + id          = (known after apply)
      + name        = "aurora-mysql80-instance-custom-params"
      + name_prefix = (known after apply)
      + tags_all    = (known after apply)

      + parameter {
          + apply_method = "immediate"
          + name         = "general_log"
          + value        = "1"
        }
      + parameter {
          + apply_method = "immediate"
          + name         = "long_query_time"
          + value        = "2"
        }
      + parameter {
          + apply_method = "immediate"
          + name         = "slow_query_log"
          + value        = "1"
        }
    }

  # aws_db_subnet_group.aurora will be created
  + resource "aws_db_subnet_group" "aurora" {
      + arn                     = (known after apply)
      + description             = "Managed by Terraform"
      + id                      = (known after apply)
      + name                    = "aurora-subnet-group"
      + name_prefix             = (known after apply)
      + subnet_ids              = (known after apply)
      + supported_network_types = (known after apply)
      + tags_all                = (known after apply)
      + vpc_id                  = (known after apply)
    }

  # aws_rds_cluster.aurora will be created
  + resource "aws_rds_cluster" "aurora" {
      + allocated_storage                     = (known after apply)
      + apply_immediately                     = (known after apply)
      + arn                                   = (known after apply)
      + availability_zones                    = (known after apply)
      + backup_retention_period               = 5
      + ca_certificate_identifier             = (known after apply)
      + ca_certificate_valid_till             = (known after apply)
      + cluster_identifier                    = "infrequentlogsauroracluster"
      + cluster_identifier_prefix             = (known after apply)
      + cluster_members                       = (known after apply)
      + cluster_resource_id                   = (known after apply)
      + copy_tags_to_snapshot                 = false
      + database_name                         = (known after apply)
      + db_cluster_parameter_group_name       = "aurora-mysql80-cluster-custom-params"
      + db_subnet_group_name                  = "aurora-subnet-group"
      + db_system_id                          = (known after apply)
      + delete_automated_backups              = true
      + enable_global_write_forwarding        = false
      + enable_http_endpoint                  = false
      + enable_local_write_forwarding         = false
      + enabled_cloudwatch_logs_exports       = [
          + "audit",
          + "error",
          + "general",
          + "slowquery",
        ]
      + endpoint                              = (known after apply)
      + engine                                = "aurora-mysql"
      + engine_lifecycle_support              = (known after apply)
      + engine_mode                           = "provisioned"
      + engine_version                        = "8.0.mysql_aurora.3.07.1"
      + engine_version_actual                 = (known after apply)
      + hosted_zone_id                        = (known after apply)
      + iam_roles                             = (known after apply)
      + id                                    = (known after apply)
      + kms_key_id                            = (known after apply)
      + master_password                       = (sensitive value)
      + master_user_secret                    = (known after apply)
      + master_user_secret_kms_key_id         = (known after apply)
      + master_username                       = "admin"
      + network_type                          = (known after apply)
      + performance_insights_kms_key_id       = (known after apply)
      + performance_insights_retention_period = (known after apply)
      + port                                  = (known after apply)
      + preferred_backup_window               = "07:00-09:00"
      + preferred_maintenance_window          = (known after apply)
      + reader_endpoint                       = (known after apply)
      + skip_final_snapshot                   = false
      + storage_encrypted                     = (known after apply)
      + storage_type                          = (known after apply)
      + tags_all                              = (known after apply)
      + vpc_security_group_ids                = (known after apply)
    }

  # aws_rds_cluster_instance.aurora will be created
  + resource "aws_rds_cluster_instance" "aurora" {
      + apply_immediately                     = (known after apply)
      + arn                                   = (known after apply)
      + auto_minor_version_upgrade            = true
      + availability_zone                     = (known after apply)
      + ca_cert_identifier                    = (known after apply)
      + cluster_identifier                    = (known after apply)
      + copy_tags_to_snapshot                 = false
      + db_parameter_group_name               = "aurora-mysql80-instance-custom-params"
      + db_subnet_group_name                  = (known after apply)
      + dbi_resource_id                       = (known after apply)
      + endpoint                              = (known after apply)
      + engine                                = "aurora-mysql"
      + engine_version                        = "8.0.mysql_aurora.3.07.1"
      + engine_version_actual                 = (known after apply)
      + id                                    = (known after apply)
      + identifier                            = "myaurorainstance"
      + identifier_prefix                     = (known after apply)
      + instance_class                        = "db.t3.medium"
      + kms_key_id                            = (known after apply)
      + monitoring_interval                   = 0
      + monitoring_role_arn                   = (known after apply)
      + network_type                          = (known after apply)
      + performance_insights_enabled          = (known after apply)
      + performance_insights_kms_key_id       = (known after apply)
      + performance_insights_retention_period = (known after apply)
      + port                                  = (known after apply)
      + preferred_backup_window               = (known after apply)
      + preferred_maintenance_window          = (known after apply)
      + promotion_tier                        = 0
      + publicly_accessible                   = (known after apply)
      + storage_encrypted                     = (known after apply)
      + tags_all                              = (known after apply)
      + writer                                = (known after apply)
    }

  # aws_rds_cluster_parameter_group.aurora will be created
  + resource "aws_rds_cluster_parameter_group" "aurora" {
      + arn         = (known after apply)
      + description = "Managed by Terraform"
      + family      = "aurora-mysql8.0"
      + id          = (known after apply)
      + name        = "aurora-mysql80-cluster-custom-params"
      + name_prefix = (known after apply)
      + tags_all    = (known after apply)

      + parameter {
          + apply_method = "immediate"
          + name         = "server_audit_events"
          + value        = "CONNECT,QUERY,TABLE"
        }
      + parameter {
          + apply_method = "immediate"
          + name         = "server_audit_logging"
          + value        = "1"
        }
    }

  # aws_security_group.aurora will be created
  + resource "aws_security_group" "aurora" {
      + arn                    = (known after apply)
      + description            = "Security group for Aurora cluster"
      + egress                 = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = false
              + to_port          = 0
                # (1 unchanged attribute hidden)
            },
        ]
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "10.0.0.0/16",
                ]
              + from_port        = 3306
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 3306
                # (1 unchanged attribute hidden)
            },
        ]
      + name                   = "aurora-security-group"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags                   = {
          + "Name" = "aurora-sg"
        }
      + tags_all               = {
          + "Name" = "aurora-sg"
        }
      + vpc_id                 = (known after apply)
    }

  # aws_subnet.private1a will be created
  + resource "aws_subnet" "private1a" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = false
      + availability_zone                              = "ap-northeast-1a"
      + availability_zone_id                           = (known after apply)
      + cidr_block                                     = "10.0.1.0/24"
      + enable_dns64                                   = false
      + enable_resource_name_dns_a_record_on_launch    = false
      + enable_resource_name_dns_aaaa_record_on_launch = false
      + id                                             = (known after apply)
      + ipv6_cidr_block_association_id                 = (known after apply)
      + ipv6_native                                    = false
      + map_public_ip_on_launch                        = false
      + owner_id                                       = (known after apply)
      + private_dns_hostname_type_on_launch            = (known after apply)
      + tags_all                                       = (known after apply)
      + vpc_id                                         = (known after apply)
    }

  # aws_subnet.private1c will be created
  + resource "aws_subnet" "private1c" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = false
      + availability_zone                              = "ap-northeast-1c"
      + availability_zone_id                           = (known after apply)
      + cidr_block                                     = "10.0.2.0/24"
      + enable_dns64                                   = false
      + enable_resource_name_dns_a_record_on_launch    = false
      + enable_resource_name_dns_aaaa_record_on_launch = false
      + id                                             = (known after apply)
      + ipv6_cidr_block_association_id                 = (known after apply)
      + ipv6_native                                    = false
      + map_public_ip_on_launch                        = false
      + owner_id                                       = (known after apply)
      + private_dns_hostname_type_on_launch            = (known after apply)
      + tags_all                                       = (known after apply)
      + vpc_id                                         = (known after apply)
    }

  # aws_vpc.this will be created
  + resource "aws_vpc" "this" {
      + arn                                  = (known after apply)
      + cidr_block                           = "10.0.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_dns_hostnames                 = true
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags                                 = {
          + "Name" = "main-vpc"
        }
      + tags_all                             = {
          + "Name" = "main-vpc"
        }
    }

Plan: 13 to add, 0 to change, 0 to destroy.

──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.

applyコマンド

実行コマンド
terraform apply

apply結果

apply結果(長いので省略しています)
結果コマンド
terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # aws_cloudwatch_log_group.aurora_logs["audit"] will be created
  + resource "aws_cloudwatch_log_group" "aurora_logs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = "INFREQUENT_ACCESS"
      + name              = "/aws/rds/cluster/infrequentlogsauroracluster/audit"
      + name_prefix       = (known after apply)
      + retention_in_days = 7
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.aurora_logs["error"] will be created
  + resource "aws_cloudwatch_log_group" "aurora_logs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = "INFREQUENT_ACCESS"
      + name              = "/aws/rds/cluster/infrequentlogsauroracluster/error"
      + name_prefix       = (known after apply)
      + retention_in_days = 7
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.aurora_logs["general"] will be created
  + resource "aws_cloudwatch_log_group" "aurora_logs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = "INFREQUENT_ACCESS"
      + name              = "/aws/rds/cluster/infrequentlogsauroracluster/general"
      + name_prefix       = (known after apply)
      + retention_in_days = 7
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_cloudwatch_log_group.aurora_logs["slowquery"] will be created
  + resource "aws_cloudwatch_log_group" "aurora_logs" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + log_group_class   = "INFREQUENT_ACCESS"
      + name              = "/aws/rds/cluster/infrequentlogsauroracluster/slowquery"
      + name_prefix       = (known after apply)
      + retention_in_days = 7
      + skip_destroy      = false
      + tags_all          = (known after apply)
    }

  # aws_db_parameter_group.aurora will be created
  + resource "aws_db_parameter_group" "aurora" {
      + arn         = (known after apply)
      + description = "Managed by Terraform"
      + family      = "aurora-mysql8.0"
      + id          = (known after apply)
      + name        = "aurora-mysql80-instance-custom-params"
      + name_prefix = (known after apply)
      + tags_all    = (known after apply)

      + parameter {
          + apply_method = "immediate"
          + name         = "general_log"
          + value        = "1"
        }
      + parameter {
          + apply_method = "immediate"
          + name         = "long_query_time"
          + value        = "2"
        }
      + parameter {
          + apply_method = "immediate"
          + name         = "slow_query_log"
          + value        = "1"
        }
    }

  # aws_db_subnet_group.aurora will be created
  + resource "aws_db_subnet_group" "aurora" {
      + arn                     = (known after apply)
      + description             = "Managed by Terraform"
      + id                      = (known after apply)
      + name                    = "aurora-subnet-group"
      + name_prefix             = (known after apply)
      + subnet_ids              = (known after apply)
      + supported_network_types = (known after apply)
      + tags_all                = (known after apply)
      + vpc_id                  = (known after apply)
    }

  # aws_rds_cluster.aurora will be created
  + resource "aws_rds_cluster" "aurora" {
      + allocated_storage                     = (known after apply)
      + apply_immediately                     = (known after apply)
      + arn                                   = (known after apply)
      + availability_zones                    = (known after apply)
      + backup_retention_period               = 5
      + ca_certificate_identifier             = (known after apply)
      + ca_certificate_valid_till             = (known after apply)
      + cluster_identifier                    = "infrequentlogsauroracluster"
      + cluster_identifier_prefix             = (known after apply)
      + cluster_members                       = (known after apply)
      + cluster_resource_id                   = (known after apply)
      + copy_tags_to_snapshot                 = false
      + database_name                         = (known after apply)
      + db_cluster_parameter_group_name       = "aurora-mysql80-cluster-custom-params"
      + db_subnet_group_name                  = "aurora-subnet-group"
      + db_system_id                          = (known after apply)
      + delete_automated_backups              = true
      + enable_global_write_forwarding        = false
      + enable_http_endpoint                  = false
      + enable_local_write_forwarding         = false
      + enabled_cloudwatch_logs_exports       = [
          + "audit",
          + "error",
          + "general",
          + "slowquery",
        ]
      + endpoint                              = (known after apply)
      + engine                                = "aurora-mysql"
      + engine_lifecycle_support              = (known after apply)
      + engine_mode                           = "provisioned"
      + engine_version                        = "8.0.mysql_aurora.3.07.1"
      + engine_version_actual                 = (known after apply)
      + hosted_zone_id                        = (known after apply)
      + iam_roles                             = (known after apply)
      + id                                    = (known after apply)
      + kms_key_id                            = (known after apply)
      + master_password                       = (sensitive value)
      + master_user_secret                    = (known after apply)
      + master_user_secret_kms_key_id         = (known after apply)
      + master_username                       = "admin"
      + network_type                          = (known after apply)
      + performance_insights_kms_key_id       = (known after apply)
      + performance_insights_retention_period = (known after apply)
      + port                                  = (known after apply)
      + preferred_backup_window               = "07:00-09:00"
      + preferred_maintenance_window          = (known after apply)
      + reader_endpoint                       = (known after apply)
      + skip_final_snapshot                   = false
      + storage_encrypted                     = (known after apply)
      + storage_type                          = (known after apply)
      + tags_all                              = (known after apply)
      + vpc_security_group_ids                = (known after apply)
    }

  # aws_rds_cluster_instance.aurora will be created
  + resource "aws_rds_cluster_instance" "aurora" {
      + apply_immediately                     = (known after apply)
      + arn                                   = (known after apply)
      + auto_minor_version_upgrade            = true
      + availability_zone                     = (known after apply)
      + ca_cert_identifier                    = (known after apply)
      + cluster_identifier                    = (known after apply)
      + copy_tags_to_snapshot                 = false
      + db_parameter_group_name               = "aurora-mysql80-instance-custom-params"
      + db_subnet_group_name                  = (known after apply)
      + dbi_resource_id                       = (known after apply)
      + endpoint                              = (known after apply)
      + engine                                = "aurora-mysql"
      + engine_version                        = "8.0.mysql_aurora.3.07.1"
      + engine_version_actual                 = (known after apply)
      + id                                    = (known after apply)
      + identifier                            = "myaurorainstance"
      + identifier_prefix                     = (known after apply)
      + instance_class                        = "db.t3.medium"
      + kms_key_id                            = (known after apply)
      + monitoring_interval                   = 0
      + monitoring_role_arn                   = (known after apply)
      + network_type                          = (known after apply)
      + performance_insights_enabled          = (known after apply)
      + performance_insights_kms_key_id       = (known after apply)
      + performance_insights_retention_period = (known after apply)
      + port                                  = (known after apply)
      + preferred_backup_window               = (known after apply)
      + preferred_maintenance_window          = (known after apply)
      + promotion_tier                        = 0
      + publicly_accessible                   = (known after apply)
      + storage_encrypted                     = (known after apply)
      + tags_all                              = (known after apply)
      + writer                                = (known after apply)
    }

  # aws_rds_cluster_parameter_group.aurora will be created
  + resource "aws_rds_cluster_parameter_group" "aurora" {
      + arn         = (known after apply)
      + description = "Managed by Terraform"
      + family      = "aurora-mysql8.0"
      + id          = (known after apply)
      + name        = "aurora-mysql80-cluster-custom-params"
      + name_prefix = (known after apply)
      + tags_all    = (known after apply)

      + parameter {
          + apply_method = "immediate"
          + name         = "server_audit_events"
          + value        = "CONNECT,QUERY,TABLE"
        }
      + parameter {
          + apply_method = "immediate"
          + name         = "server_audit_logging"
          + value        = "1"
        }
    }

  # aws_security_group.aurora will be created
  + resource "aws_security_group" "aurora" {
      + arn                    = (known after apply)
      + description            = "Security group for Aurora cluster"
      + egress                 = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + from_port        = 0
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "-1"
              + security_groups  = []
              + self             = false
              + to_port          = 0
                # (1 unchanged attribute hidden)
            },
        ]
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "10.0.0.0/16",
                ]
              + from_port        = 3306
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 3306
                # (1 unchanged attribute hidden)
            },
        ]
      + name                   = "aurora-security-group"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags                   = {
          + "Name" = "aurora-sg"
        }
      + tags_all               = {
          + "Name" = "aurora-sg"
        }
      + vpc_id                 = (known after apply)
    }

  # aws_subnet.private1a will be created
  + resource "aws_subnet" "private1a" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = false
      + availability_zone                              = "ap-northeast-1a"
      + availability_zone_id                           = (known after apply)
      + cidr_block                                     = "10.0.1.0/24"
      + enable_dns64                                   = false
      + enable_resource_name_dns_a_record_on_launch    = false
      + enable_resource_name_dns_aaaa_record_on_launch = false
      + id                                             = (known after apply)
      + ipv6_cidr_block_association_id                 = (known after apply)
      + ipv6_native                                    = false
      + map_public_ip_on_launch                        = false
      + owner_id                                       = (known after apply)
      + private_dns_hostname_type_on_launch            = (known after apply)
      + tags_all                                       = (known after apply)
      + vpc_id                                         = (known after apply)
    }

  # aws_subnet.private1c will be created
  + resource "aws_subnet" "private1c" {
      + arn                                            = (known after apply)
      + assign_ipv6_address_on_creation                = false
      + availability_zone                              = "ap-northeast-1c"
      + availability_zone_id                           = (known after apply)
      + cidr_block                                     = "10.0.2.0/24"
      + enable_dns64                                   = false
      + enable_resource_name_dns_a_record_on_launch    = false
      + enable_resource_name_dns_aaaa_record_on_launch = false
      + id                                             = (known after apply)
      + ipv6_cidr_block_association_id                 = (known after apply)
      + ipv6_native                                    = false
      + map_public_ip_on_launch                        = false
      + owner_id                                       = (known after apply)
      + private_dns_hostname_type_on_launch            = (known after apply)
      + tags_all                                       = (known after apply)
      + vpc_id                                         = (known after apply)
    }

  # aws_vpc.this will be created
  + resource "aws_vpc" "this" {
      + arn                                  = (known after apply)
      + cidr_block                           = "10.0.0.0/16"
      + default_network_acl_id               = (known after apply)
      + default_route_table_id               = (known after apply)
      + default_security_group_id            = (known after apply)
      + dhcp_options_id                      = (known after apply)
      + enable_dns_hostnames                 = true
      + enable_dns_support                   = true
      + enable_network_address_usage_metrics = (known after apply)
      + id                                   = (known after apply)
      + instance_tenancy                     = "default"
      + ipv6_association_id                  = (known after apply)
      + ipv6_cidr_block                      = (known after apply)
      + ipv6_cidr_block_network_border_group = (known after apply)
      + main_route_table_id                  = (known after apply)
      + owner_id                             = (known after apply)
      + tags                                 = {
          + "Name" = "main-vpc"
        }
      + tags_all                             = {
          + "Name" = "main-vpc"
        }
    }

Plan: 13 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

aws_cloudwatch_log_group.aurora_logs["general"]: Creating...
aws_cloudwatch_log_group.aurora_logs["audit"]: Creating...
aws_cloudwatch_log_group.aurora_logs["slowquery"]: Creating...
aws_db_parameter_group.aurora: Creating...
aws_rds_cluster_parameter_group.aurora: Creating...
aws_vpc.this: Creating...
aws_cloudwatch_log_group.aurora_logs["error"]: Creating...
aws_cloudwatch_log_group.aurora_logs["general"]: Creation complete after 1s [id=/aws/rds/cluster/infrequentlogsauroracluster/general]
aws_cloudwatch_log_group.aurora_logs["audit"]: Creation complete after 1s [id=/aws/rds/cluster/infrequentlogsauroracluster/audit]
aws_cloudwatch_log_group.aurora_logs["slowquery"]: Creation complete after 1s [id=/aws/rds/cluster/infrequentlogsauroracluster/slowquery]
aws_cloudwatch_log_group.aurora_logs["error"]: Creation complete after 1s [id=/aws/rds/cluster/infrequentlogsauroracluster/error]
aws_db_parameter_group.aurora: Creation complete after 2s [id=aurora-mysql80-instance-custom-params]
aws_rds_cluster_parameter_group.aurora: Creation complete after 2s [id=aurora-mysql80-cluster-custom-params]
aws_vpc.this: Still creating... [10s elapsed]
aws_vpc.this: Creation complete after 12s [id=vpc-0eeee4357fda6f82c]
aws_subnet.private1c: Creating...
aws_subnet.private1a: Creating...
aws_security_group.aurora: Creating...
aws_subnet.private1a: Creation complete after 0s [id=subnet-024a27635f13d66d5]
aws_subnet.private1c: Creation complete after 0s [id=subnet-093923a0e02752eb8]
aws_db_subnet_group.aurora: Creating...
aws_db_subnet_group.aurora: Creation complete after 1s [id=aurora-subnet-group]
aws_security_group.aurora: Creation complete after 2s [id=sg-091c13822fc15c07c]
aws_rds_cluster.aurora: Creating...
aws_rds_cluster.aurora: Still creating... [10s elapsed]
aws_rds_cluster.aurora: Still creating... [20s elapsed]
aws_rds_cluster.aurora: Still creating... [30s elapsed]
aws_rds_cluster.aurora: Still creating... [40s elapsed]
aws_rds_cluster.aurora: Still creating... [50s elapsed]
aws_rds_cluster.aurora: Still creating... [1m0s elapsed]
aws_rds_cluster.aurora: Creation complete after 1m2s [id=infrequentlogsauroracluster]
aws_rds_cluster_instance.aurora: Creating...
aws_rds_cluster_instance.aurora: Still creating... [10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [1m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [1m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [1m20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [1m30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [1m40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [1m50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [2m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [2m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [2m20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [2m30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [2m40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [2m50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [3m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [3m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [3m20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [3m30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [3m40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [3m50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [4m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [4m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [4m20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [4m30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [4m40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [4m50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [5m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [5m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [5m20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [5m30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [5m40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [5m50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [6m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [6m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [6m20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [6m30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [6m40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [6m50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [7m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [7m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [7m20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [7m30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [7m40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [7m50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [8m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [8m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [8m20s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [8m30s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [8m40s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [8m50s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [9m0s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [9m10s elapsed]
aws_rds_cluster_instance.aurora: Still creating... [9m20s elapsed]
aws_rds_cluster_instance.aurora: Creation complete after 9m29s [id=myaurorainstance]

Apply complete! Resources: 13 added, 0 changed, 0 destroyed.

無事作成されましたね!後はコンソール上でロググループを確認してみます。

動作確認

対象のロググループが作成されている確認します。
CleanShot 2024-10-29 at 13.56.48@2x

auditerrorgeneralslowqueryでそれぞれログクラスがInfrequent Accessで作成されていますね!

実際にログが出力されているかも確認します。例として監査ログを見てます。

  1. /aws/rds/cluster/infrequentlogsauroracluster/auditリンクを押下
    CleanShot 2024-10-29 at 14.01.58@2x
  2. Logs Insights で表示ボタンを押下
    CleanShot 2024-10-29 at 14.03.28@2x
  3. クエリの実行ボタンを押下
    CleanShot 2024-10-29 at 14.04.44@2x
  4. 出力されたログの中身を確認
    CleanShot 2024-10-29 at 14.06.28@2x

Infrequent Accessのロググループに監査ログがちゃんと出力されていますね!

おわりに

Aurora MySQLからCloudWatchに出力されるログのログクラスをInfrequent AccessとTerraformで設定する方法について、
いかがでしたでしょうか。
少しでも参考になれば幸いです!

本記事を最後までご覧いただきありがとうございました。

補足

ソースコード全体も共有させていただきます。
必要に応じてご参照ください。

ソースコード全体
main.tf
terraform {
  required_version = ">=0.13"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~>5.61.0"
    }
  }
}

provider "aws" {
  region  = "ap-northeast-1"
}

# 変数の設定
locals {
  cluster_identifier = "infrequentlogsauroracluster"
}

# ロググループの作成
resource "aws_cloudwatch_log_group" "aurora_logs" {
  for_each = toset(["error", "general", "slowquery", "audit"])

  name              = "/aws/rds/cluster/${local.cluster_identifier}/${each.key}"
  retention_in_days = 7
  log_group_class   = "INFREQUENT_ACCESS"
}

# VPCの作成
resource "aws_vpc" "this" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "main-vpc"
  }
}

# プライベートサブネットの作成(RDS用)
resource "aws_subnet" "private1a" {
  vpc_id            = aws_vpc.this.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a"
}

resource "aws_subnet" "private1c" {
  vpc_id            = aws_vpc.this.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "ap-northeast-1c"
}

# DBのセキュリティグループ
resource "aws_security_group" "aurora" {
  name        = "aurora-security-group"
  description = "Security group for Aurora cluster"
  vpc_id      = aws_vpc.this.id

  # VPC内からの接続を許可(MySQL/Aurora用のポート3306)
  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = [aws_vpc.this.cidr_block]
  }

  # アウトバウンドトラフィックを全て許可
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "aurora-sg"
  }
}

# Auroraを配置するサブネットグループ
resource "aws_db_subnet_group" "aurora" {
  name       = "aurora-subnet-group"
  subnet_ids = [aws_subnet.private1a.id, aws_subnet.private1c.id]
}

# クラスターパラメータグループ(監査ログ用)
resource "aws_rds_cluster_parameter_group" "aurora" {
  family = "aurora-mysql8.0"
  name   = "aurora-mysql80-cluster-custom-params"

  parameter {
    name  = "server_audit_logging"
    value = "1"
  }

  parameter {
    name  = "server_audit_events"
    value = "CONNECT,QUERY,TABLE"
  }
}

# インスタンスパラメータグループ(一般ログ、スロークエリログ用)
resource "aws_db_parameter_group" "aurora" {
  family = "aurora-mysql8.0"
  name   = "aurora-mysql80-instance-custom-params"

  parameter {
    name  = "slow_query_log"
    value = "1"
  }

  parameter {
    name  = "long_query_time"
    value = "2"
  }

  parameter {
    name  = "general_log"
    value = "1"
  }
}

# クラスター
resource "aws_rds_cluster" "aurora" {
  cluster_identifier              = local.cluster_identifier
  engine                          = "aurora-mysql"
  engine_version                  = "8.0.mysql_aurora.3.07.1"
  master_username                 = "admin"
  master_password                 = "changeme123"
  backup_retention_period         = 5
  preferred_backup_window         = "07:00-09:00"
  db_subnet_group_name            = aws_db_subnet_group.aurora.name
  db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.aurora.name
  vpc_security_group_ids = [aws_security_group.aurora.id]

  enabled_cloudwatch_logs_exports = ["error", "general", "slowquery", "audit"]

}

# インスタンス
resource "aws_rds_cluster_instance" "aurora" {
  identifier         = "myaurorainstance"
  cluster_identifier = aws_rds_cluster.aurora.id
  instance_class     = "db.t3.medium"
  engine             = aws_rds_cluster.aurora.engine
  engine_version     = aws_rds_cluster.aurora.engine_version

  db_parameter_group_name = aws_db_parameter_group.aurora.name
}

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.